@stalfh233/omc-cli 0.0.0-stage → 0.4.10
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/LICENSE +21 -0
- package/README.md +293 -3
- package/coverage/m1-coverage-manifest-v1.json +1278 -0
- package/dist/approval-token.js +102 -0
- package/dist/args.js +25 -0
- package/dist/artifacts.js +119 -0
- package/dist/bench/call-face-eval.js +256 -0
- package/dist/bench/context-attribution.js +151 -0
- package/dist/bench/discovery-cost-eval.js +230 -0
- package/dist/bench/driver.js +81 -0
- package/dist/bench/evals.js +236 -0
- package/dist/bench/fake-http-server.js +65 -0
- package/dist/bench/instrument.js +87 -0
- package/dist/bench/intent-face-eval.js +343 -0
- package/dist/bench/run.js +166 -0
- package/dist/bench/scenario.js +343 -0
- package/dist/bench/types.js +76 -0
- package/dist/bi-wire.js +41 -0
- package/dist/bizservice-config.js +581 -0
- package/dist/call.js +153 -0
- package/dist/capability-absences.js +23 -0
- package/dist/capability-overview.js +492 -0
- package/dist/capability-shape.js +154 -0
- package/dist/cli-contract.js +70 -0
- package/dist/cli-output.js +73 -0
- package/dist/cli.js +1418 -0
- package/dist/code-rules.js +69 -0
- package/dist/command-transport.js +155 -0
- package/dist/config-store.js +195 -0
- package/dist/context.js +21 -0
- package/dist/contract-consistency.js +66 -0
- package/dist/contract-resources.js +62 -0
- package/dist/coverage-consistency.js +62 -0
- package/dist/coverage-registry.js +76 -0
- package/dist/coverage.js +130 -0
- package/dist/data-list-filter.js +114 -0
- package/dist/discovery.js +390 -0
- package/dist/endpoints.js +154 -0
- package/dist/environment-policy.js +26 -0
- package/dist/execution-metadata.js +1092 -0
- package/dist/fake/app.js +45 -0
- package/dist/fake/b2-registration.js +594 -0
- package/dist/fake/businessrule.js +242 -0
- package/dist/fake/datarule.js +72 -0
- package/dist/fake/dictionary.js +108 -0
- package/dist/fake/environment.js +30 -0
- package/dist/fake/field.js +167 -0
- package/dist/fake/form.js +101 -0
- package/dist/fake/index.js +121 -0
- package/dist/fake/list-view.js +289 -0
- package/dist/fake/model.js +136 -0
- package/dist/fake/online-js.js +18 -0
- package/dist/fake/report.js +253 -0
- package/dist/fake/routes.js +47 -0
- package/dist/fake/rule-lifecycle.js +37 -0
- package/dist/fake/runtime-data.js +367 -0
- package/dist/fake/state.js +67 -0
- package/dist/fake/workflow.js +364 -0
- package/dist/field-change.js +200 -0
- package/dist/field-families.js +896 -0
- package/dist/form-layout.js +111 -0
- package/dist/form-support.js +821 -0
- package/dist/goal-routes.js +468 -0
- package/dist/governed-execution.js +87 -0
- package/dist/human-summary.js +212 -0
- package/dist/identity.js +62 -0
- package/dist/intent/baseline.js +57 -0
- package/dist/intent/capabilities/bizservice.js +274 -0
- package/dist/intent/capabilities/businessrule.js +493 -0
- package/dist/intent/capabilities/datarule.js +187 -0
- package/dist/intent/capabilities/field.js +545 -0
- package/dist/intent/capabilities/form.js +136 -0
- package/dist/intent/capabilities/index.js +64 -0
- package/dist/intent/capabilities/listview.js +157 -0
- package/dist/intent/capabilities/model.js +100 -0
- package/dist/intent/capabilities/onlinejs.js +108 -0
- package/dist/intent/capabilities/report.js +355 -0
- package/dist/intent/capabilities/workflow.js +458 -0
- package/dist/intent/capability.js +6 -0
- package/dist/intent/cli.js +91 -0
- package/dist/intent/compare.js +56 -0
- package/dist/intent/compiler.js +79 -0
- package/dist/intent/dsl.js +129 -0
- package/dist/intent/plan-file.js +63 -0
- package/dist/intent/readback.js +65 -0
- package/dist/intent/schema.js +158 -0
- package/dist/intent/validation.js +30 -0
- package/dist/intent/yaml.js +315 -0
- package/dist/json-column.js +68 -0
- package/dist/lanes/app-contract.js +95 -0
- package/dist/lanes/app-coverage.js +16 -0
- package/dist/lanes/app.js +174 -0
- package/dist/lanes/apply-changes.js +231 -0
- package/dist/lanes/b2-registration-contract.js +292 -0
- package/dist/lanes/b2-registration-coverage.js +48 -0
- package/dist/lanes/b2-registration.js +1187 -0
- package/dist/lanes/businessrule-contract.js +232 -0
- package/dist/lanes/businessrule-coverage.js +16 -0
- package/dist/lanes/businessrule.js +221 -0
- package/dist/lanes/contract-support.js +65 -0
- package/dist/lanes/coverage-declaration.js +9 -0
- package/dist/lanes/datarule-contract.js +155 -0
- package/dist/lanes/datarule-coverage.js +19 -0
- package/dist/lanes/datarule-protocol.js +308 -0
- package/dist/lanes/datarule.js +818 -0
- package/dist/lanes/dictionary-contract.js +78 -0
- package/dist/lanes/dictionary-coverage.js +24 -0
- package/dist/lanes/dictionary.js +235 -0
- package/dist/lanes/environment-contract.js +70 -0
- package/dist/lanes/environment-coverage.js +14 -0
- package/dist/lanes/environment.js +163 -0
- package/dist/lanes/field-contract.js +223 -0
- package/dist/lanes/field-coverage.js +27 -0
- package/dist/lanes/field.js +374 -0
- package/dist/lanes/form-contract.js +97 -0
- package/dist/lanes/form-coverage.js +16 -0
- package/dist/lanes/form.js +185 -0
- package/dist/lanes/lane-ids.js +34 -0
- package/dist/lanes/list-view-contract.js +175 -0
- package/dist/lanes/list-view-coverage.js +20 -0
- package/dist/lanes/list-view-shapes.js +1207 -0
- package/dist/lanes/list-view.js +578 -0
- package/dist/lanes/meta-contract.js +85 -0
- package/dist/lanes/meta.js +255 -0
- package/dist/lanes/model-contract.js +168 -0
- package/dist/lanes/model-coverage.js +20 -0
- package/dist/lanes/model.js +986 -0
- package/dist/lanes/online-js-contract.js +99 -0
- package/dist/lanes/online-js-coverage.js +28 -0
- package/dist/lanes/online-js.js +127 -0
- package/dist/lanes/report-contract.js +144 -0
- package/dist/lanes/report-coverage.js +21 -0
- package/dist/lanes/report.js +476 -0
- package/dist/lanes/rule-graph.js +1846 -0
- package/dist/lanes/rule-lifecycle-contract.js +92 -0
- package/dist/lanes/rule-lifecycle-coverage.js +20 -0
- package/dist/lanes/rule-lifecycle.js +176 -0
- package/dist/lanes/runtime-data-contract.js +264 -0
- package/dist/lanes/runtime-data-coverage.js +25 -0
- package/dist/lanes/runtime-data.js +1054 -0
- package/dist/lanes/workflow-contract.js +223 -0
- package/dist/lanes/workflow-coverage.js +40 -0
- package/dist/lanes/workflow.js +1813 -0
- package/dist/online-js-layout.js +58 -0
- package/dist/online-js-source.js +276 -0
- package/dist/package-tool.js +51 -0
- package/dist/package.js +73 -0
- package/dist/plan.js +73 -0
- package/dist/read.js +144 -0
- package/dist/redact.js +28 -0
- package/dist/rule-support.js +587 -0
- package/dist/runtime-support.js +134 -0
- package/dist/server.js +92 -0
- package/dist/session-manager.js +30 -0
- package/dist/session.js +149 -0
- package/dist/skills.js +112 -0
- package/dist/support.js +98 -0
- package/dist/tool-types.js +127 -0
- package/dist/tools.js +59 -0
- package/dist/usage-log.js +197 -0
- package/dist/wire.js +287 -0
- package/dist/workflow-support.js +99 -0
- package/dist/write-lease.js +26 -0
- package/dist/write-lock.js +109 -0
- package/dist/write.js +176 -0
- package/dist/zip.js +156 -0
- package/docs/tool-surface-map.md +42 -0
- package/package.json +71 -6
- package/skills/omc-acceptance-criteria.md +47 -0
- package/skills/omc-business-configuration.md +257 -0
- package/skills/omc-capabilities.md +197 -0
- package/skills/omc-capability-scouting.md +55 -0
- package/skills/omc-config-draft-review.md +171 -0
- package/skills/omc-five-piece-flow.md +35 -0
- package/skills/omc-glossary.md +86 -0
- package/skills/omc-refusals.md +110 -0
- package/skills/omc-requirement-analysis.md +161 -0
- package/skills/omc-requirement-vocabulary.md +51 -0
- package/skills/omc-start-here.md +82 -0
- package/skills/omc-tool-selection.md +119 -0
- package/skills/omc-write-hazards.md +87 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { ENDPOINTS } from "../../endpoints.js";
|
|
2
|
+
import { assertDataRuleOptions } from "../../lanes/datarule.js";
|
|
3
|
+
import { wireCall, wireRows } from "../../wire.js";
|
|
4
|
+
import { optionalSame, sameValue } from "../compare.js";
|
|
5
|
+
import { isScalarString, pushError } from "../validation.js";
|
|
6
|
+
import { toPlain } from "../yaml.js";
|
|
7
|
+
import { errorDetail } from "../../tool-types.js";
|
|
8
|
+
const KEYS = new Set(["propertyCode", "dataRuleType", "options", "checkType", "childRule", "name", "sortKey", "absent"]);
|
|
9
|
+
/** Keys that describe a live rule and are meaningless on a declared-absent one. */
|
|
10
|
+
const PRESENT_ONLY_KEYS = ["options", "checkType", "childRule", "name", "sortKey"];
|
|
11
|
+
function decodeOptions(value) {
|
|
12
|
+
if (typeof value !== "string")
|
|
13
|
+
return value;
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(value);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function rowOf(row) {
|
|
22
|
+
const codes = rowCodes(row);
|
|
23
|
+
return {
|
|
24
|
+
id: String(row.id ?? ""),
|
|
25
|
+
propertyCode: codes.length === 1 ? codes[0] : codes.join(","),
|
|
26
|
+
dataRuleType: Number(row.dataRuleType),
|
|
27
|
+
options: decodeOptions(row.options),
|
|
28
|
+
...(row.checkType !== undefined && row.checkType !== null ? { checkType: Number(row.checkType) } : {}),
|
|
29
|
+
...(row.childRule !== undefined ? { childRule: row.childRule === true } : {}),
|
|
30
|
+
...(row.name !== undefined && row.name !== null ? { name: String(row.name) } : {}),
|
|
31
|
+
// The platform defaults an omitted sortKey to 0; an intent that omits it must
|
|
32
|
+
// read back equal (bench56: `sortKey:0` vs undefined produced a perpetual
|
|
33
|
+
// `datarule-mismatch`, so a fully-delivered apply was reported refused).
|
|
34
|
+
...(row.sortKey !== undefined && row.sortKey !== null && Number(row.sortKey) !== 0 ? { sortKey: Number(row.sortKey) } : {}),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function normalizeOptions(dataRuleType, options, propertyCode) {
|
|
38
|
+
const normalized = { ...options };
|
|
39
|
+
// The tool mirrors the target field(s) into options.propertyCodes (the real
|
|
40
|
+
// designer shape the engine reads); declare the same here so a converged
|
|
41
|
+
// environment has no false drift.
|
|
42
|
+
if (propertyCode.length > 0 && normalized.propertyCodes === undefined)
|
|
43
|
+
normalized.propertyCodes = propertyCode;
|
|
44
|
+
if (dataRuleType === 2) {
|
|
45
|
+
for (const key of ["shortTextStitch", "value", "aggregation"]) {
|
|
46
|
+
if (normalized[key] !== undefined && typeof normalized[key] === "object")
|
|
47
|
+
normalized[key] = JSON.stringify(normalized[key]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return normalized;
|
|
51
|
+
}
|
|
52
|
+
/** Stored target field codes (propertyCodes array preferred, legacy singular fallback). */
|
|
53
|
+
function rowCodes(row) {
|
|
54
|
+
if (Array.isArray(row.propertyCodes) && row.propertyCodes.length > 0)
|
|
55
|
+
return row.propertyCodes.map((code) => String(code));
|
|
56
|
+
const single = row.propertyCode;
|
|
57
|
+
return single !== undefined && single !== null && String(single).length > 0 ? [String(single)] : [];
|
|
58
|
+
}
|
|
59
|
+
export const dataruleCapability = {
|
|
60
|
+
id: "datarule",
|
|
61
|
+
title: "字段级控件规则",
|
|
62
|
+
requires: ["field"],
|
|
63
|
+
operations: ["create", "update"],
|
|
64
|
+
validate(node, draft, ctx) {
|
|
65
|
+
const rulesNode = node.entries.find((entry) => entry.key === "datarules")?.value;
|
|
66
|
+
if (rulesNode === undefined || (rulesNode.kind === "scalar" && rulesNode.value === null))
|
|
67
|
+
return;
|
|
68
|
+
if (rulesNode.kind !== "seq") {
|
|
69
|
+
pushError(ctx, "intent-datarules-not-a-list", "datarules 必须是列表", `${ctx.base}.datarules`, "value");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
rulesNode.items.forEach((ruleNode, index) => {
|
|
73
|
+
const base = `${ctx.base}.datarules[${index}]`;
|
|
74
|
+
if (ruleNode.kind !== "map") {
|
|
75
|
+
pushError(ctx, "intent-datarule-not-a-map", "datarule 必须是映射", base, "value");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
for (const entry of ruleNode.entries)
|
|
79
|
+
if (!KEYS.has(entry.key))
|
|
80
|
+
pushError(ctx, "intent-key-unknown", `datarule 不支持键 "${entry.key}"(可用:${[...KEYS].join(" / ")})`, `${base}.${entry.key}`);
|
|
81
|
+
const get = (key) => ruleNode.entries.find((entry) => entry.key === key)?.value;
|
|
82
|
+
const property = get("propertyCode");
|
|
83
|
+
const type = get("dataRuleType");
|
|
84
|
+
const options = get("options");
|
|
85
|
+
const checkType = get("checkType");
|
|
86
|
+
const childRule = get("childRule");
|
|
87
|
+
const name = get("name");
|
|
88
|
+
const sortKey = get("sortKey");
|
|
89
|
+
const absent = get("absent");
|
|
90
|
+
if (!isScalarString(property) || property.value.trim().length === 0)
|
|
91
|
+
pushError(ctx, "intent-datarule-property-invalid", "datarule.propertyCode 必须是非空字符串", `${base}.propertyCode`, "value");
|
|
92
|
+
if (type?.kind !== "scalar" || typeof type.value !== "number" || !Number.isInteger(type.value) || type.value < 1 || type.value > 5)
|
|
93
|
+
pushError(ctx, "intent-datarule-type-invalid", "datarule.dataRuleType 必须是 1..5", `${base}.dataRuleType`, "value");
|
|
94
|
+
if (absent !== undefined && (absent.kind !== "scalar" || typeof absent.value !== "boolean"))
|
|
95
|
+
pushError(ctx, "intent-datarule-absent-invalid", "datarule.absent 必须是布尔", `${base}.absent`, "value");
|
|
96
|
+
if (absent?.kind === "scalar" && absent.value === true) {
|
|
97
|
+
for (const key of PRESENT_ONLY_KEYS)
|
|
98
|
+
if (ruleNode.entries.some((entry) => entry.key === key))
|
|
99
|
+
pushError(ctx, "intent-datarule-absent-with-shape", `数据规则声明 absent:true 表示删除该规则,不能再声明 ${key}`, `${base}.${key}`);
|
|
100
|
+
if (isScalarString(property) && type?.kind === "scalar" && typeof type.value === "number")
|
|
101
|
+
draft.datarules.push({ propertyCode: property.value.trim(), dataRuleType: type.value, absent: true });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (options?.kind !== "map")
|
|
105
|
+
pushError(ctx, "intent-datarule-options-invalid", "datarule.options 必须是映射", `${base}.options`, "value");
|
|
106
|
+
if (checkType !== undefined && (checkType.kind !== "scalar" || typeof checkType.value !== "number"))
|
|
107
|
+
pushError(ctx, "intent-datarule-checktype-invalid", "datarule.checkType 必须是数字", `${base}.checkType`, "value");
|
|
108
|
+
if (childRule !== undefined && (childRule.kind !== "scalar" || typeof childRule.value !== "boolean"))
|
|
109
|
+
pushError(ctx, "intent-datarule-childrule-invalid", "datarule.childRule 必须是布尔", `${base}.childRule`, "value");
|
|
110
|
+
if (name !== undefined && (!isScalarString(name) || name.value.trim().length === 0))
|
|
111
|
+
pushError(ctx, "intent-datarule-name-invalid", "datarule.name 必须是非空字符串", `${base}.name`, "value");
|
|
112
|
+
if (sortKey !== undefined && (sortKey.kind !== "scalar" || typeof sortKey.value !== "number"))
|
|
113
|
+
pushError(ctx, "intent-datarule-sortkey-invalid", "datarule.sortKey 必须是数字", `${base}.sortKey`, "value");
|
|
114
|
+
if (!isScalarString(property) || type?.kind !== "scalar" || typeof type.value !== "number" || options?.kind !== "map")
|
|
115
|
+
return;
|
|
116
|
+
const rawOptions = options.entries ? Object.fromEntries(options.entries.map((entry) => [entry.key, entry.value.kind === "scalar" ? entry.value.value : toPlain(entry.value)])) : {};
|
|
117
|
+
const normalizedOptions = normalizeOptions(type.value, rawOptions, property.value.trim());
|
|
118
|
+
const parsedCheckType = checkType?.kind === "scalar" && typeof checkType.value === "number" ? checkType.value : undefined;
|
|
119
|
+
try {
|
|
120
|
+
assertDataRuleOptions(type.value, normalizedOptions, parsedCheckType);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
pushError(ctx, "intent-datarule-options-invalid", errorDetail(error), `${base}.options`, "value");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const item = {
|
|
127
|
+
propertyCode: property.value.trim(),
|
|
128
|
+
dataRuleType: type.value,
|
|
129
|
+
options: normalizedOptions,
|
|
130
|
+
...(checkType?.kind === "scalar" && typeof checkType.value === "number" ? { checkType: checkType.value } : {}),
|
|
131
|
+
...(childRule?.kind === "scalar" && typeof childRule.value === "boolean" ? { childRule: childRule.value } : {}),
|
|
132
|
+
...(isScalarString(name) ? { name: name.value.trim() } : {}),
|
|
133
|
+
...(sortKey?.kind === "scalar" && typeof sortKey.value === "number" ? { sortKey: sortKey.value } : {}),
|
|
134
|
+
};
|
|
135
|
+
draft.datarules.push(item);
|
|
136
|
+
});
|
|
137
|
+
},
|
|
138
|
+
async read(session, intent, draft) {
|
|
139
|
+
if (!intent.datarules?.length)
|
|
140
|
+
return;
|
|
141
|
+
const rows = wireRows((await wireCall(session, { path: ENDPOINTS.dataRuleList, query: { schemaCode: draft.code } })).data);
|
|
142
|
+
draft.datarules = rows.filter((row) => row.schemaCode === draft.code && intent.datarules.some((rule) => rowCodes(row).includes(rule.propertyCode) && rule.dataRuleType === Number(row.dataRuleType))).map(rowOf);
|
|
143
|
+
},
|
|
144
|
+
plan(intent, baseline, emit) {
|
|
145
|
+
if (!intent.datarules?.length)
|
|
146
|
+
return;
|
|
147
|
+
for (const rule of intent.datarules) {
|
|
148
|
+
const current = (baseline.datarules ?? []).find((row) => row.propertyCode === rule.propertyCode && row.dataRuleType === rule.dataRuleType);
|
|
149
|
+
const resource = `datarule:${intent.code}.${rule.propertyCode}.${rule.dataRuleType}`;
|
|
150
|
+
if (rule.absent === true) {
|
|
151
|
+
if (current)
|
|
152
|
+
emit.change("datarule.delete", { id: current.id, schemaCode: intent.code }, resource, "datarule-declared-absent");
|
|
153
|
+
else
|
|
154
|
+
emit.skip(resource, "datarule-already-absent");
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (!current)
|
|
158
|
+
emit.change("datarule.create", { schemaCode: intent.code, ...rule }, resource, "datarule-absent");
|
|
159
|
+
else if (!sameValue(current.options, rule.options) || !optionalSame(current.checkType, rule.checkType) || !optionalSame(current.childRule, rule.childRule) || !optionalSame(current.name, rule.name) || !optionalSame(current.sortKey, rule.sortKey))
|
|
160
|
+
emit.change("datarule.update", { id: current.id, schemaCode: intent.code, ...rule }, resource, "datarule-drift");
|
|
161
|
+
else
|
|
162
|
+
emit.skip(resource, "datarule-present");
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
decode(baseline, draft) {
|
|
166
|
+
draft.datarules = (baseline.datarules ?? []).map((rule) => ({ ...rule }));
|
|
167
|
+
},
|
|
168
|
+
compare(intent, live, emit) {
|
|
169
|
+
if (!intent.datarules?.length)
|
|
170
|
+
return;
|
|
171
|
+
const current = live.datarules ?? [];
|
|
172
|
+
for (const rule of intent.datarules) {
|
|
173
|
+
const row = current.find((item) => item.propertyCode === rule.propertyCode && item.dataRuleType === rule.dataRuleType);
|
|
174
|
+
const resource = `datarule:${intent.code}.${rule.propertyCode}.${rule.dataRuleType}`;
|
|
175
|
+
if (rule.absent === true) {
|
|
176
|
+
if (row)
|
|
177
|
+
emit.difference("datarule-present-unexpected", resource, `字段 ${intent.code}.${rule.propertyCode} 的数据规则声明 absent:true 但仍存在`);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (!row)
|
|
181
|
+
emit.difference("datarule-missing", resource, `字段 ${intent.code}.${rule.propertyCode} 的数据规则不存在`);
|
|
182
|
+
else if (!sameValue(row.options, rule.options) || !optionalSame(row.checkType, rule.checkType) || !optionalSame(row.childRule, rule.childRule) || !optionalSame(row.name, rule.name) || !optionalSame(row.sortKey, rule.sortKey))
|
|
183
|
+
emit.difference("datarule-mismatch", resource, `字段 ${intent.code}.${rule.propertyCode} 的数据规则不等价`);
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
//# sourceMappingURL=datarule.js.map
|