@stalfh233/omc-cli 0.6.18 → 0.6.19
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-stdout.js +1 -0
- package/dist/cli.js +3 -2
- package/dist/field-families.js +6 -5
- package/dist/lanes/field.js +11 -5
- package/dist/lanes/folder.js +29 -2
- package/dist/residue.js +116 -0
- package/package.json +3 -3
package/dist/cli-stdout.js
CHANGED
package/dist/cli.js
CHANGED
|
@@ -57,6 +57,7 @@ import { listSkills, readSkill, readSkillOutline, readSkillSection, searchSkills
|
|
|
57
57
|
import { parseToolInput, ToolInputError } from "./tool-types.js";
|
|
58
58
|
import { WireError, wireCall } from "./wire.js";
|
|
59
59
|
import { DEFAULT_PULL_CONCURRENCY, GraphIndexAbsentError, GraphPullLockHeldError, MAX_PULL_CONCURRENCY, impactGraph, publishGraphPull, queryGraphReferences, readGraphStatus, searchGraphRules, } from "./graph.js";
|
|
60
|
+
import { cmdResidue } from "./residue.js";
|
|
60
61
|
import { ENDPOINTS } from "./endpoints.js";
|
|
61
62
|
import { makeToolContext } from "./context.js";
|
|
62
63
|
import { cmdRollbackList, cmdRollbackPlan, cmdRollbackApply } from "./rollback.js";
|
|
@@ -986,7 +987,6 @@ async function cmdArtifactGet(id, transport, options = {}) {
|
|
|
986
987
|
...artifactProjectionMetadata(content),
|
|
987
988
|
keys,
|
|
988
989
|
path: options.jq,
|
|
989
|
-
content: projected.content ?? null,
|
|
990
990
|
projections: [{ path: options.jq, content: projected.content ?? null, ...(projected.mapped !== undefined ? { mapped: projected.mapped } : {}), ...(projected.missedEntries !== undefined ? { missedEntries: projected.missedEntries } : {}), ...(projected.nullEntries !== undefined && projected.nullEntries > 0 ? { nullEntries: projected.nullEntries } : {}) }],
|
|
991
991
|
...(projected.mapped !== undefined ? { mapped: projected.mapped } : {}),
|
|
992
992
|
...(projected.nullEntries !== undefined && projected.nullEntries > 0 ? { nullEntries: projected.nullEntries } : {}),
|
|
@@ -1038,7 +1038,7 @@ async function cmdArtifactGet(id, transport, options = {}) {
|
|
|
1038
1038
|
const projected = projectArtifactPath(artifactContent, options.jq);
|
|
1039
1039
|
return emitTransportResult(projected.missed
|
|
1040
1040
|
? { status: "ok", artifactId: id, sha256: artifact.sha256, ...artifactProjectionMetadata(content), path: options.jq, content: null, pathMiss: true, missedAt: projected.at, available: projected.available, unanswered: true, hint: artifactPathMissHint(projected.at) }
|
|
1041
|
-
: { status: "ok", artifactId: id, sha256: artifact.sha256, ...artifactProjectionMetadata(content), path: options.jq,
|
|
1041
|
+
: { status: "ok", artifactId: id, sha256: artifact.sha256, ...artifactProjectionMetadata(content), path: options.jq, projections: [{ path: options.jq, content: projected.content ?? null, ...(projected.mapped !== undefined ? { mapped: projected.mapped } : {}), ...(projected.missedEntries !== undefined ? { missedEntries: projected.missedEntries } : {}), ...(projected.nullEntries !== undefined && projected.nullEntries > 0 ? { nullEntries: projected.nullEntries } : {}) }], ...(projected.mapped !== undefined ? { mapped: projected.mapped } : {}), ...(projected.missedEntries !== undefined ? { missedEntries: projected.missedEntries } : {}), ...(projected.nullEntries !== undefined && projected.nullEntries > 0 ? { nullEntries: projected.nullEntries } : {}), ...(artifactNullHint(projected.content, projected.nullEntries) !== undefined ? { hint: artifactNullHint(projected.content, projected.nullEntries) } : {}) }, transport);
|
|
1042
1042
|
}
|
|
1043
1043
|
// r6-onboarding 2026-10-21: 47 artifact fetches, 0 used a projection; the 10
|
|
1044
1044
|
// large ones (up to 55 KB) pulled whole workflow templates just to read one
|
|
@@ -2470,6 +2470,7 @@ async function main() {
|
|
|
2470
2470
|
pureKeys: (options.keys === true || bareJq) && options.summary !== true, ...(typeof options.keys === "string" ? { keys: options.keys } : {}), full: options.full === true }));
|
|
2471
2471
|
});
|
|
2472
2472
|
command.command("bench").option("--live-sample").option("--env <environment>").action(async (options) => { commandExitCode = await cmdBench([...(options.liveSample ? ["--live-sample"] : []), ...(options.env ? ["--env", options.env] : [])]); });
|
|
2473
|
+
command.command("residue <prefix>").description("跨面前缀残留扫描(model 全租户/folder/custompage;默认 deep 再查命中模型的 rule/datarule/onlinejs)——收尾「删净」一次证明,clean:true 即零残留。只读零写入;report 面暂停维护未扫描").option("--env <environment>", "环境名(默认按 cwd 的 .omc-env 解析)").option("--apps <codes>", "all(默认,全租户)或逗号分隔应用码").option("--no-deep", "只扫 model/folder/custompage,不深查命中模型").option("--max-output-bytes <bytes>").action(async (prefix, options) => { commandExitCode = await withTransport(options, request, (transport) => cmdResidue(prefix, { env: options.env, apps: options.apps, ...(options.deep === false ? { noDeep: true } : {}) }, transport)); });
|
|
2473
2474
|
const jqOption = () => new Option("--jq [path]", "路径投影(与 call --jq 同 DSL;可逗号多路径;裸 --jq 列顶层键)").argParser((value, previous = []) => [...previous, value]).default([]);
|
|
2474
2475
|
command.command("commands").option("--json").option("--compact").option("--filter <keyword>").option("--lane <id>").option("--max-output-bytes <bytes>").addOption(jqOption()).action(async (options) => { commandExitCode = await withTransport(options, request, (transport) => cmdDiscovery("commands", transport, undefined, { json: options.json === true, compact: options.compact === true, ...(options.filter ? { filter: options.filter } : {}), ...(options.lane ? { lane: options.lane } : {}), ...(options.jq !== undefined ? { jq: options.jq } : {}) })); });
|
|
2475
2476
|
command.command("describe <tool>").option("--full").option("--cache-ok", "允许 --full 在同会话重复读时短路为 artifact 指针(默认每次回全文)").option("--schema-only").option("--param <name>").option("--example [id]").option("--max-output-bytes <bytes>").addOption(jqOption()).action(async (tool, options) => {
|
package/dist/field-families.js
CHANGED
|
@@ -15,7 +15,7 @@ export const propertyTypeArg = z
|
|
|
15
15
|
export const relativeCodeArg = z
|
|
16
16
|
.string()
|
|
17
17
|
.optional()
|
|
18
|
-
.describe("
|
|
18
|
+
.describe("关联目标 code;租户唯一、按 code 全局解析,可跨应用");
|
|
19
19
|
/**
|
|
20
20
|
* Ticket 59 (P0): the wire `name_i18n` column must be a *parseable JSON object
|
|
21
21
|
* string*, never a bare display string. The admin designer runs an unguarded
|
|
@@ -167,7 +167,7 @@ export const subFieldArg = z
|
|
|
167
167
|
*/
|
|
168
168
|
export const fieldOptionsArg = z
|
|
169
169
|
.object({
|
|
170
|
-
schemaCode: z.string().optional().describe("
|
|
170
|
+
schemaCode: z.string().optional().describe("关联目标 code;租户唯一、按 code 全局解析,可跨应用"),
|
|
171
171
|
queryCode: z.string().optional().describe("relation query code (usually the target model code)"),
|
|
172
172
|
displayField: z.string().optional().describe("relation display field (usually 'name')"),
|
|
173
173
|
mappings: z
|
|
@@ -301,9 +301,9 @@ export function assertRelationTargetExists(args, candidates) {
|
|
|
301
301
|
: typeof raw === "string" && raw in FIELD_PROPERTY_TYPES ? FIELD_PROPERTY_TYPES[raw] : undefined;
|
|
302
302
|
if (type !== FIELD_PROPERTY_TYPES.WORK_SHEET && type !== FIELD_PROPERTY_TYPES.MULT_WORK_SHEET)
|
|
303
303
|
return;
|
|
304
|
-
const optionsCode = typeof args.options?.schemaCode === "string" ? args.options.schemaCode.trim() : "";
|
|
305
304
|
const relativeCode = typeof args.relativeCode === "string" ? args.relativeCode.trim() : "";
|
|
306
|
-
const
|
|
305
|
+
const optionsCode = typeof args.options?.schemaCode === "string" ? args.options.schemaCode.trim() : "";
|
|
306
|
+
const target = relativeCode || optionsCode;
|
|
307
307
|
// Some offline/fake transports do not expose a model-list face. An empty
|
|
308
308
|
// candidate set is therefore "unknown", not proof of absence; live model
|
|
309
309
|
// lists are non-empty and get the strict pre-write gate.
|
|
@@ -336,7 +336,8 @@ export function relationPublishFailureMessage(fields, candidates) {
|
|
|
336
336
|
const type = typeof raw === "number" ? raw : typeof raw === "string" && raw in FIELD_PROPERTY_TYPES ? FIELD_PROPERTY_TYPES[raw] : undefined;
|
|
337
337
|
if (type !== FIELD_PROPERTY_TYPES.WORK_SHEET && type !== FIELD_PROPERTY_TYPES.MULT_WORK_SHEET)
|
|
338
338
|
continue;
|
|
339
|
-
const
|
|
339
|
+
const relativeCode = typeof field.relativeCode === "string" ? field.relativeCode.trim() : "";
|
|
340
|
+
const target = relativeCode || (typeof options?.schemaCode === "string" ? options.schemaCode.trim() : "");
|
|
340
341
|
if (typeof options?.schemaCode === "string" && options.schemaCode.trim() && (!field.relativeCode || String(field.relativeCode).trim() === "")) {
|
|
341
342
|
return `字段 ${String(field.code ?? "(未知)")} 的关联目标 ${options.schemaCode} 仅写在 options.schemaCode;发布面不解析该位置(平台原始 errcode 300010「数据模型编码不能为空!」)。请重建/归一化为顶层 relativeCode=${options.schemaCode}`;
|
|
342
343
|
}
|
package/dist/lanes/field.js
CHANGED
|
@@ -12,16 +12,21 @@ import { defineTool, ToolRefusalError } from "../tool-types.js";
|
|
|
12
12
|
import { wireCall, wireRows, WireError } from "../wire.js";
|
|
13
13
|
import { executeFormDraftWrite, executeFormPublishWrite, readFormOrNull } from "../form-support.js";
|
|
14
14
|
import { FIELD_LANE_CONTRACT } from "./field-contract.js";
|
|
15
|
-
import { flattenTreeRows, mapBounded
|
|
15
|
+
import { flattenTreeRows, mapBounded } from "../support.js";
|
|
16
16
|
import { extractBizObjectPage } from "./runtime-data.js";
|
|
17
17
|
const FIELD_LANE = FIELD_LANE_CONTRACT.lane;
|
|
18
18
|
const FIELD_TOOLS = FIELD_LANE_CONTRACT.tools;
|
|
19
19
|
/** Read actual model schema codes; bare modelList may expose internal node ids. */
|
|
20
20
|
export async function modelSchemaCodes(session) {
|
|
21
21
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// Relation codes are tenant-global on the platform, not application-scoped.
|
|
23
|
+
// Enumerate every application for this call only; deliberately do not cache
|
|
24
|
+
// this merged candidate set across calls because model writes can change it.
|
|
25
|
+
const apps = wireRows((await wireCall(session, { path: ENDPOINTS.applicationList, query: {} })).data)
|
|
26
|
+
.map((row) => row.appCode ?? row.code)
|
|
27
|
+
.filter((code) => typeof code === "string" && code.length > 0);
|
|
28
|
+
const trees = await mapBounded(apps, 4, async (appCode) => flattenTreeRows(wireRows((await wireCall(session, { path: ENDPOINTS.applicationTree, query: { appCode } })).data)));
|
|
29
|
+
const codes = trees.flat()
|
|
25
30
|
.filter((row) => row.type === "BizModel")
|
|
26
31
|
.map((row) => String(row.code ?? row.schemaCode ?? row.bizSchemaCode ?? ""))
|
|
27
32
|
.filter((code) => code.length > 0);
|
|
@@ -29,7 +34,8 @@ export async function modelSchemaCodes(session) {
|
|
|
29
34
|
return codes;
|
|
30
35
|
}
|
|
31
36
|
catch {
|
|
32
|
-
// Fall through to the compatibility endpoint below
|
|
37
|
+
// Fall through to the compatibility endpoint below when the tenant-wide
|
|
38
|
+
// discovery face is unavailable (older/fake transports).
|
|
33
39
|
}
|
|
34
40
|
return wireRows((await wireCall(session, { path: ENDPOINTS.modelList, query: {} })).data)
|
|
35
41
|
.map((row) => String(row.schemaCode ?? row.bizSchemaCode ?? row.code ?? ""))
|
package/dist/lanes/folder.js
CHANGED
|
@@ -5,7 +5,7 @@ import { writeTool } from "../write.js";
|
|
|
5
5
|
import { wireCall, wireRows } from "../wire.js";
|
|
6
6
|
import { ENDPOINTS } from "../endpoints.js";
|
|
7
7
|
import { capabilityArg, environmentArg } from "../args.js";
|
|
8
|
-
import { resolveApplicationCode } from "../support.js";
|
|
8
|
+
import { jsonBytes, resolveApplicationCode } from "../support.js";
|
|
9
9
|
import { LANES } from "./lane-ids.js";
|
|
10
10
|
import { FOLDER_LANE_CONTRACT } from "./folder-contract.js";
|
|
11
11
|
/**
|
|
@@ -38,6 +38,33 @@ import { FOLDER_LANE_CONTRACT } from "./folder-contract.js";
|
|
|
38
38
|
*/
|
|
39
39
|
const LANE = LANES.folder;
|
|
40
40
|
const T = FOLDER_LANE_CONTRACT.tools;
|
|
41
|
+
/**
|
|
42
|
+
* folder.tree is a node inventory, so its useful inline budget is node-count
|
|
43
|
+
* first rather than the generic read compact threshold. Keep the existing
|
|
44
|
+
* byte guard as a second gate: a pathological 50-node tree still belongs in
|
|
45
|
+
* the artifact when the node payload itself is too large.
|
|
46
|
+
*/
|
|
47
|
+
export const FOLDER_TREE_INLINE_NODE_LIMIT = 50;
|
|
48
|
+
export const FOLDER_TREE_NODE_INLINE_CEILING_BYTES = 8192;
|
|
49
|
+
export function compactFolderTree(result) {
|
|
50
|
+
const nodes = Array.isArray(result.nodes) ? result.nodes : undefined;
|
|
51
|
+
if (nodes === undefined)
|
|
52
|
+
return { ...result };
|
|
53
|
+
if (nodes.length <= FOLDER_TREE_INLINE_NODE_LIMIT && jsonBytes(nodes) <= FOLDER_TREE_NODE_INLINE_CEILING_BYTES) {
|
|
54
|
+
return { ...result, nodes };
|
|
55
|
+
}
|
|
56
|
+
const countGate = nodes.length > FOLDER_TREE_INLINE_NODE_LIMIT;
|
|
57
|
+
const { nodes: _nodes, ...withoutNodes } = result;
|
|
58
|
+
return {
|
|
59
|
+
...withoutNodes,
|
|
60
|
+
nodesPreview: nodes.slice(0, 5),
|
|
61
|
+
note: `${String(result.note ?? "")} ${countGate
|
|
62
|
+
? `nodes 超过 ${FOLDER_TREE_INLINE_NODE_LIMIT} 条,完整节点已外置到 detailArtifactId;nodesPreview 仅展示前 5 条。`
|
|
63
|
+
: `nodes 正文超过 ${FOLDER_TREE_NODE_INLINE_CEILING_BYTES}B 字节闸,完整节点已外置到 detailArtifactId;这是字节闸,不是节点数限制。`}`.trim(),
|
|
64
|
+
// Deliberately omit nodes so governedRead adds the standard empty
|
|
65
|
+
// placeholder/truncatedKeys while the preview remains available.
|
|
66
|
+
};
|
|
67
|
+
}
|
|
41
68
|
/**
|
|
42
69
|
* Live 1.1.25 (r28d F2): platform `apppackage/create` seeds one top-level Folder
|
|
43
70
|
* whose `name_i18n.en` is the stable token `defaultGroup` (zh display is「默认分组」).
|
|
@@ -202,7 +229,7 @@ function folderTools(tools) {
|
|
|
202
229
|
: " applicationExists:false——应用不在 apppackage/list;空树不等于「空应用」。") +
|
|
203
230
|
" nodeCount/folderCount/modelCount 是全应用聚合,共享环境含其它会话资源;核对自己的资源请按 code 前缀过滤 nodes[],不要只比计数。",
|
|
204
231
|
};
|
|
205
|
-
}),
|
|
232
|
+
}, { compact: compactFolderTree }),
|
|
206
233
|
}));
|
|
207
234
|
writeTool({
|
|
208
235
|
tools,
|
package/dist/residue.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { ENDPOINTS } from "./endpoints.js";
|
|
3
|
+
import { wireCall, wireRows } from "./wire.js";
|
|
4
|
+
import { flattenTreeRows } from "./support.js";
|
|
5
|
+
import { ConfigStore, defaultPaths } from "./config-store.js";
|
|
6
|
+
import { SessionManager } from "./session-manager.js";
|
|
7
|
+
import { makeToolContext } from "./context.js";
|
|
8
|
+
import { emitInvalid, emitResult } from "./command-transport.js";
|
|
9
|
+
const MAX_ITEMS = 20;
|
|
10
|
+
function face(faceName, rows, extra = {}) {
|
|
11
|
+
return { face: faceName, ...extra, count: rows.length, items: rows.slice(0, MAX_ITEMS) };
|
|
12
|
+
}
|
|
13
|
+
function codeOf(row) {
|
|
14
|
+
return String(row.code ?? row.schemaCode ?? row.bizSchemaCode ?? "");
|
|
15
|
+
}
|
|
16
|
+
function nameOf(row, code) {
|
|
17
|
+
return String(row.name ?? row.displayName ?? row.title ?? code);
|
|
18
|
+
}
|
|
19
|
+
function codeStarts(row, prefix) {
|
|
20
|
+
return codeOf(row).startsWith(prefix);
|
|
21
|
+
}
|
|
22
|
+
function folderStarts(row, prefix) {
|
|
23
|
+
return codeStarts(row, prefix) || String(row.name ?? "").startsWith(prefix);
|
|
24
|
+
}
|
|
25
|
+
function scriptPresent(raw) {
|
|
26
|
+
if (typeof raw !== "string")
|
|
27
|
+
return false;
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
if (!Array.isArray(parsed))
|
|
31
|
+
return false;
|
|
32
|
+
return parsed.some((element) => {
|
|
33
|
+
const row = element;
|
|
34
|
+
return row.id === "customScript" && typeof row.innerHTML === "string" && row.innerHTML.trim() !== "";
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function tree(session, app) {
|
|
42
|
+
return flattenTreeRows(wireRows((await wireCall(session, { path: ENDPOINTS.applicationTree, query: { appCode: app } })).data));
|
|
43
|
+
}
|
|
44
|
+
async function modelRows(session, app) {
|
|
45
|
+
return (await tree(session, app)).filter((row) => row.type === "BizModel");
|
|
46
|
+
}
|
|
47
|
+
async function customPages(session, appSet) {
|
|
48
|
+
const rows = wireRows((await wireCall(session, { path: ENDPOINTS.customPageList, query: { modeType: "VUE_MODE" } })).data);
|
|
49
|
+
return rows.filter((row) => appSet.has(String(row.appCode ?? "")));
|
|
50
|
+
}
|
|
51
|
+
async function deepFaces(session, model) {
|
|
52
|
+
const schemaCode = codeOf(model);
|
|
53
|
+
const rules = wireRows((await wireCall(session, { path: ENDPOINTS.businessRuleListBySchemaCode, query: { schemaCode } })).data);
|
|
54
|
+
const datarules = wireRows((await wireCall(session, { path: ENDPOINTS.dataRuleList, query: { schemaCode } })).data);
|
|
55
|
+
let online = [];
|
|
56
|
+
try {
|
|
57
|
+
const sheet = (await wireCall(session, { path: ENDPOINTS.sheetGet, query: { schemaCode, sheetCode: schemaCode } })).data;
|
|
58
|
+
if (sheet && (scriptPresent(sheet.draftHtmlJson) || scriptPresent(sheet.publishedHtmlJson))) {
|
|
59
|
+
const raw = typeof sheet.publishedHtmlJson === "string" && scriptPresent(sheet.publishedHtmlJson) ? sheet.publishedHtmlJson : sheet.draftHtmlJson;
|
|
60
|
+
online = [{ present: true, ...(typeof raw === "string" ? { sha256: createHash("sha256").update(raw).digest("hex") } : {}) }];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// A missing form is an absent online-js face, not a scan failure.
|
|
65
|
+
}
|
|
66
|
+
return [
|
|
67
|
+
face("rule", rules.map((row) => ({ code: codeOf(row), name: nameOf(row, codeOf(row)) })), { model: schemaCode }),
|
|
68
|
+
face("datarule", datarules.map((row) => ({ code: codeOf(row), name: nameOf(row, codeOf(row)) })), { model: schemaCode }),
|
|
69
|
+
face("onlinejs", online, { model: schemaCode }),
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
export async function scanResidues(session, prefix, options = {}) {
|
|
73
|
+
const apps = wireRows((await wireCall(session, { path: ENDPOINTS.applicationList, query: {} })).data)
|
|
74
|
+
.map((row) => String(row.appCode ?? row.code ?? ""))
|
|
75
|
+
.filter(Boolean);
|
|
76
|
+
const selected = options.apps && options.apps !== "all" ? options.apps.split(",").map((app) => app.trim()).filter(Boolean) : apps;
|
|
77
|
+
const appSet = new Set(selected);
|
|
78
|
+
const faces = [];
|
|
79
|
+
const models = [];
|
|
80
|
+
for (const app of selected) {
|
|
81
|
+
const rows = await tree(session, app);
|
|
82
|
+
const matchingModels = rows.filter((row) => row.type === "BizModel" && codeStarts(row, prefix));
|
|
83
|
+
models.push(...matchingModels.map((row) => ({ ...row, appCode: app })));
|
|
84
|
+
faces.push(face("model", matchingModels.map((row) => ({ code: codeOf(row), name: nameOf(row, codeOf(row)) })), { app }));
|
|
85
|
+
faces.push(face("folder", rows.filter((row) => row.type === "Folder" && folderStarts(row, prefix)).map((row) => ({ code: codeOf(row), name: nameOf(row, codeOf(row)) })), { app }));
|
|
86
|
+
}
|
|
87
|
+
const pages = (await customPages(session, appSet)).filter((row) => codeStarts(row, prefix));
|
|
88
|
+
for (const app of selected) {
|
|
89
|
+
faces.push(face("custompage", pages.filter((row) => String(row.appCode ?? "") === app).map((row) => ({ code: codeOf(row), name: nameOf(row, codeOf(row)) })), { app }));
|
|
90
|
+
}
|
|
91
|
+
if (options.deep !== false) {
|
|
92
|
+
for (const model of models)
|
|
93
|
+
faces.push(...await deepFaces(session, model));
|
|
94
|
+
}
|
|
95
|
+
const totalResidues = faces.reduce((sum, item) => sum + item.count, 0);
|
|
96
|
+
return {
|
|
97
|
+
prefix,
|
|
98
|
+
faces,
|
|
99
|
+
totalResidues,
|
|
100
|
+
clean: totalResidues === 0,
|
|
101
|
+
note: "report 面暂停维护未扫描;workflow 模板跟模型走(模型删即删)",
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export async function cmdResidue(prefix, options, transport) {
|
|
105
|
+
if (!prefix || prefix.trim() === "")
|
|
106
|
+
return emitInvalid(transport, { message: "residue 的 prefix 必填" });
|
|
107
|
+
try {
|
|
108
|
+
const context = makeToolContext({ sessions: new SessionManager(new ConfigStore(defaultPaths())) });
|
|
109
|
+
const session = await context.sessions.session(options.env);
|
|
110
|
+
return emitResult(await scanResidues(session, prefix, { apps: options.apps, deep: options.noDeep !== true }), transport);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
return emitResult({ status: "error", blocker: "residue-scan-failed", message: error instanceof Error ? error.message : String(error) }, transport);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=residue.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stalfh233/omc-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.19",
|
|
4
4
|
"description": "CloudPivot 8.6 configuration capability CLI — governed, fail-closed, coverage-manifest bounded.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"commander": "14.0.3",
|
|
58
|
-
"omc-core": "0.6.
|
|
58
|
+
"omc-core": "0.6.19",
|
|
59
59
|
"proper-lockfile": "4.1.2",
|
|
60
60
|
"write-file-atomic": "6.0.0",
|
|
61
61
|
"zod": "^3.23.8",
|
|
@@ -73,6 +73,6 @@
|
|
|
73
73
|
"directory": "packages/omc-cli"
|
|
74
74
|
},
|
|
75
75
|
"optionalDependencies": {
|
|
76
|
-
"@stalfh233/omc-fake-platform": "0.6.
|
|
76
|
+
"@stalfh233/omc-fake-platform": "0.6.19"
|
|
77
77
|
}
|
|
78
78
|
}
|