@stalfh233/omc-cli 0.0.0-stage → 0.4.0
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 +304 -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,223 @@
|
|
|
1
|
+
import { CONTRACT_FAMILY, CONTRACT_REFERENCE_VERSION, assertDescriptionCarries, assertLaneContract, behaviorBinding, describeTool, emitterBinding } from "./contract-support.js";
|
|
2
|
+
import { LANES } from "./lane-ids.js";
|
|
3
|
+
import { assertCapabilityShapeContract } from "../capability-shape.js";
|
|
4
|
+
import { RESERVED_CODES } from "../code-rules.js";
|
|
5
|
+
export const FIELD_CONTROL_CODES = Object.freeze({
|
|
6
|
+
// 8.6.26 BizFormPropertyType (authoritative enum)
|
|
7
|
+
1: { name: "SINGLE_LINE_TEXT", status: "known" },
|
|
8
|
+
2: { name: "LONGTEXT", status: "known" },
|
|
9
|
+
3: { name: "DATE", status: "known" },
|
|
10
|
+
4: { name: "NUMBER", status: "known" },
|
|
11
|
+
5: { name: "RADIO", status: "known" },
|
|
12
|
+
6: { name: "CHECKBOX", status: "known" },
|
|
13
|
+
7: { name: "SELECT", status: "known" },
|
|
14
|
+
8: { name: "LOGIC", status: "known" },
|
|
15
|
+
9: { name: "ATTACH_FILE", status: "known" },
|
|
16
|
+
10: { name: "PHOTO", status: "known", note: "no field family emits it — no BizPropertyType maps to control 10 (ticket 101); blocked for creation" },
|
|
17
|
+
11: { name: "LOCATION", status: "known" },
|
|
18
|
+
14: { name: "ADDRESS", status: "known" },
|
|
19
|
+
15: { name: "HANDWRITING_SIGNATURE", status: "known" },
|
|
20
|
+
17: { name: "HYPER_LINK", status: "known" },
|
|
21
|
+
19: { name: "SELECT_MULTI", status: "known" },
|
|
22
|
+
24: { name: "PHONE", status: "known", note: "no field family emits it — no BizPropertyType maps to control 24 (ticket 101); blocked for creation" },
|
|
23
|
+
28: { name: "TIME", status: "known" },
|
|
24
|
+
50: { name: "SINGLE_PERSON_SELECT", status: "known" },
|
|
25
|
+
51: { name: "MULTI_PERSON_SELECT", status: "known" },
|
|
26
|
+
60: { name: "SINGLE_DEPART_SELECT", status: "known" },
|
|
27
|
+
61: { name: "MULTI_DEPART_SELECT", status: "known" },
|
|
28
|
+
62: { name: "MULTI_PERSON_DEPART_SELECT", status: "known" },
|
|
29
|
+
80: { name: "RelevanceForm", status: "known" },
|
|
30
|
+
81: { name: "RelevanceFormEx", status: "known" },
|
|
31
|
+
82: { name: "RelevanceData", status: "known" },
|
|
32
|
+
89: { name: "Formula", status: "known" },
|
|
33
|
+
90: { name: "RelevanceQuery", status: "known", note: "present in the 8.6.26 enum; no accepted field family maps to it — creation not offered" },
|
|
34
|
+
100: { name: "SequenceNo", status: "known" },
|
|
35
|
+
101: { name: "Creator", status: "known" },
|
|
36
|
+
102: { name: "CreatedDeptId", status: "known", note: "system field control — projected from the createdDeptId system property (DefaultPropertyType.java:18-21 → DEPARTMENT_SELECTOR 60, created by BizMainSystemPropertyRegistry.java:88-101, defaultProperty=true); not user-creatable, never scaffolded (ticket 101)" },
|
|
37
|
+
103: { name: "Modifier", status: "known" },
|
|
38
|
+
104: { name: "CreatedTime", status: "known" },
|
|
39
|
+
105: { name: "ModifiedTime", status: "known" },
|
|
40
|
+
106: { name: "Owner", status: "known" },
|
|
41
|
+
201: { name: "Sheet", status: "known" },
|
|
42
|
+
249: { name: "Button", status: "known" },
|
|
43
|
+
499: { name: "Container", status: "known" },
|
|
44
|
+
500: { name: "Tab", status: "known", note: "layout container — DataModelInitUtils.java:61-75 recurses its panels; never a field, never scaffolded (ticket 101)" },
|
|
45
|
+
// designer/layout widgets wired directly by buildFormScaffold / research §2.3
|
|
46
|
+
200: { name: "Group", status: "designer" },
|
|
47
|
+
203: { name: "Title", status: "designer" },
|
|
48
|
+
400: { name: "HtmlContainer", status: "designer" },
|
|
49
|
+
// observed, no authoritative name in the 8.6.26 enum or research
|
|
50
|
+
202: { name: "unknown-202", status: "unknown" },
|
|
51
|
+
// 8.6.39-origin codes; absent from the 8.6.26 enum — refuse on 8.6.26
|
|
52
|
+
250: { name: "OCR", status: "adapted-unknown" },
|
|
53
|
+
251: { name: "ELECTRONIC_SIGN", status: "adapted-unknown" },
|
|
54
|
+
252: { name: "unknown-252", status: "adapted-unknown" },
|
|
55
|
+
253: { name: "unknown-253", status: "adapted-unknown" },
|
|
56
|
+
1001: { name: "unknown-1001", status: "adapted-unknown" },
|
|
57
|
+
});
|
|
58
|
+
/** The live-accepted wire field families, shared by the contract and the arg schema. */
|
|
59
|
+
export const FIELD_FAMILY_LIST = "SHORT_TEXT, LONG_TEXT, NUMERICAL, DATE, LOGICAL, SELECTION, ATTACHMENT, CHILD_TABLE, WORK_SHEET, ADDRESS, MULT_WORK_SHEET, RADIO, CHECKBOX, DROPDOWN_BOX, DROPDOWN_MULTI_BOX, RELEVANCE_DATA, HYPER_LINK, TIME, STAFF_SELECTOR, STAFF_MULTI_SELECTOR, DEPARTMENT_SELECTOR, DEPARTMENT_MULTI_SELECTOR, FORMULA";
|
|
60
|
+
/**
|
|
61
|
+
* Designer-standard default options for a DATE(3) field. The runtime reads
|
|
62
|
+
* `options.format` on the first save (BizObjectFacadeImpl.java:2949); without
|
|
63
|
+
* it the save answers 50000. This is the single source for that default.
|
|
64
|
+
*/
|
|
65
|
+
export const FIELD_DATE_DEFAULT_OPTIONS = Object.freeze({
|
|
66
|
+
dictionaryData: "",
|
|
67
|
+
format: "YYYY-MM-DD",
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Platform-supported DATE(3) `options.format` enum. The runtime compares the
|
|
71
|
+
* stored value LITERALLY (DateBizField.contentFromClient has an if/else over
|
|
72
|
+
* exactly these strings, else `不支持的format:<value>`): the UPPERCASE tokens
|
|
73
|
+
* below work; Java's `yyyy-MM-dd` (lowercase y/d) is NOT one of them and makes
|
|
74
|
+
* the first runtime save answer 50000 (2026-09-30 R5 live). Kept beside the
|
|
75
|
+
* default so the default is provably in the enum.
|
|
76
|
+
*/
|
|
77
|
+
export const FIELD_DATE_FORMATS = Object.freeze([
|
|
78
|
+
"YYYY", "YYYY-MM", "YYYY/MM",
|
|
79
|
+
"YYYY-MM-DD", "YYYY/MM/DD",
|
|
80
|
+
"YYYY-MM-DD HH:mm", "YYYY/MM/DD HH:mm",
|
|
81
|
+
"YYYY-MM-DD HH:mm:ss", "YYYY/MM/DD HH:mm:ss",
|
|
82
|
+
"YYYY-MM-DD CN-APM", "YYYY/MM/DD CN-APM",
|
|
83
|
+
"YYYY-MM-DD CN-APM HH:mm", "YYYY/MM/DD CN-APM HH:mm",
|
|
84
|
+
"YYYY-MM-DD EN-APM", "YYYY/MM/DD EN-APM",
|
|
85
|
+
"YYYY-MM-DD EN-APM HH:mm", "YYYY/MM/DD EN-APM HH:mm",
|
|
86
|
+
"YYYY年MM月DD日", "YYYY年MM月",
|
|
87
|
+
]);
|
|
88
|
+
/** FORMULA(100) options wire (8.6.26 FormulaPropertyOptions + admin field serializer). */
|
|
89
|
+
export const FIELD_FORMULA_WIRE = Object.freeze({
|
|
90
|
+
outerOptions: '{"formulaConfig":"<JSON string>","persistent":true[, "format":""|"percentile" — readback-only mirror, fwb §100]}',
|
|
91
|
+
innerConfig: '{"resultType":0|2,"resultFormat":""|"percentile","formulaType":"EXPRESSION","expression":"<JSON string {formula,editorText,editorMark}>"}',
|
|
92
|
+
expressionFormula: '<fieldCode> placeholders, e.g. {omc_a} + {omc_b}',
|
|
93
|
+
aggregationConfig: 'AGGREGATION nested {schemaCode,dataItemCode,calculateType,formula,queryConditions} = 表单「计算」控件的「聚合计算」(UI 实测 2026-10-07:跨模型聚合,求和/最大/最小/…). FormulaProcessor.executeMainAggregation 用 queryConditions 查该 schema、对匹配行的 dataItemCode 求值 formula. shape-validated & allowed. **计算类需求默认不用 FORMULA 字段**:子表求和回主表、子表列同行运算一律「普通字段 + 计算规则」(`datarule.create` dataRuleType:2,recipes `field-compute-subtable-sum` / `field-compute-child-column`,前台真机算得 7.00/350);FORMULA 字段仅作已存量读取。计算由**门户前端**执行、API 不回填(写测试数据带预算值;正确性人工前台确认)。',
|
|
94
|
+
legacyRejected: "resultType/expression top-level keys are not read by the platform and are refused",
|
|
95
|
+
runtimeVerification: "FORMULA 字段视为「配置好即在前台会算」:计算由门户**前端**执行,API save/update/submit 不回填/重算(真机 2026-09-25/2026-10-07)。写测试数据时显式带上预算好的计算值;**公式正确性由人工在前台(配表单→填表)确认**,不要用 API 回读断言。带子表计算字段的模型 API data.save/update 可能 50000(服务端重算 NPE),前台正常。",
|
|
96
|
+
});
|
|
97
|
+
/** RELEVANCE_DATA(16) options wire (8.6.26 RelevanceDataOptions + admin field serializer). */
|
|
98
|
+
export const FIELD_RELEVANCE_WIRE = Object.freeze({
|
|
99
|
+
options: '{"relevanceField":"<local WORK_SHEET field code>","referenceField":"<referenced field code>","referenceFieldPropertyType":<int>}',
|
|
100
|
+
semantics: "references another field through a local WORK_SHEET field; NOT a model relation (no schemaCode/mappings)",
|
|
101
|
+
});
|
|
102
|
+
/** Control-code classification for the 8.6.26 family (FIELD_CONTROL_CODES source of truth). */
|
|
103
|
+
export const FIELD_CONTROL_CODE_STATUS = Object.freeze({
|
|
104
|
+
known: Object.keys(FIELD_CONTROL_CODES).filter((code) => FIELD_CONTROL_CODES[Number(code)].status === "known").join(","),
|
|
105
|
+
designer: Object.keys(FIELD_CONTROL_CODES).filter((code) => FIELD_CONTROL_CODES[Number(code)].status === "designer").join(","),
|
|
106
|
+
unknown: Object.keys(FIELD_CONTROL_CODES).filter((code) => FIELD_CONTROL_CODES[Number(code)].status === "unknown").join(","),
|
|
107
|
+
adaptedUnknown: Object.keys(FIELD_CONTROL_CODES).filter((code) => FIELD_CONTROL_CODES[Number(code)].status === "adapted-unknown").join(","),
|
|
108
|
+
});
|
|
109
|
+
export const FIELD_LANE_CONTRACT = Object.freeze({
|
|
110
|
+
lane: LANES.field,
|
|
111
|
+
family: CONTRACT_FAMILY,
|
|
112
|
+
referenceVersion: CONTRACT_REFERENCE_VERSION,
|
|
113
|
+
endpoints: Object.freeze({
|
|
114
|
+
list: "fieldList",
|
|
115
|
+
create: "fieldCreate",
|
|
116
|
+
update: "fieldUpdate",
|
|
117
|
+
publish: "fieldPublish",
|
|
118
|
+
delete: "fieldForceDelete",
|
|
119
|
+
}),
|
|
120
|
+
wire: Object.freeze({
|
|
121
|
+
acceptedFamilies: FIELD_FAMILY_LIST,
|
|
122
|
+
blockedFamilies: "OCR, ELECTRONIC_SIGN, nested CHILD_TABLE",
|
|
123
|
+
childTableSubSchema: '{"code":"<父字段 code>","properties":[{"code","name","schemaCode":"<父字段 code>","propertyType","propertyEmpty","sortKey"}]}',
|
|
124
|
+
childTableFormControl: "Sheet(201) with columns[{type,width,key,parentKey,options}]; child column keys never enter viewJson",
|
|
125
|
+
dateDefaultOptions: JSON.stringify(FIELD_DATE_DEFAULT_OPTIONS),
|
|
126
|
+
formulaOptions: FIELD_FORMULA_WIRE.outerOptions,
|
|
127
|
+
formulaConfig: FIELD_FORMULA_WIRE.innerConfig,
|
|
128
|
+
formulaRuntimeVerification: FIELD_FORMULA_WIRE.runtimeVerification,
|
|
129
|
+
relevanceDataOptions: FIELD_RELEVANCE_WIRE.options,
|
|
130
|
+
publishScope: "model",
|
|
131
|
+
controlEmissionPolicy: "ticket 101: controls PHONE(24)/PHOTO(10) are blocked for creation (no BizPropertyType maps to them — BizPropertyType.java:27-54); Tab(500) is a layout container (DataModelInitUtils.java:61-75 recurses panels, never a field); CreatedDeptId(102) is a system-field projection (DefaultPropertyType.java:18-21 → DEPARTMENT_SELECTOR 60, BizMainSystemPropertyRegistry.java:88-101); the scaffold SKIPS any field type without a control mapping — unknown/blocked control types are never auto-created (fail-closed)",
|
|
132
|
+
fieldRowDefaultPolicy: "ticket 108 determination (live 8.6.26 write+read 2026-09-15 + fwb 8.6.39 readback): the 2026-09-14 key unions are MULTI-FIELD UNIONS of designer rows, not per-field required keys — the platform accepts-and-persists minimal rows, so the minimal default + caller passthrough is the INTENTIONAL boundary. Selection families 12/13/14/15 MUST-FIXED to omit dictionaryData (designer rows carry none; live proves the platform merely accepts the extra key — omc_mcp_t108dd readback carried it only because we sent it). Families 0/1/2/9/11/17 keep the designer-carried {dictionaryData:\"\"}; DATE(3) keeps required format (BizObjectFacadeImpl.java:2949); ATTACHMENT(6) stays intentionally empty (system rows often have no options)",
|
|
133
|
+
}),
|
|
134
|
+
wireBindings: Object.freeze({
|
|
135
|
+
acceptedFamilies: Object.freeze([emitterBinding("lanes/field-contract.FIELD_FAMILY_LIST", assertFieldContract)]),
|
|
136
|
+
blockedFamilies: Object.freeze([behaviorBinding("test/field-families.test.ts#field.create refuses OCR", assertFieldContract)]),
|
|
137
|
+
childTableSubSchema: Object.freeze([behaviorBinding("test/child-table.test.ts#field.create CHILD_TABLE sends a subSchema (not options) with parent-coded child columns", assertFieldContract)]),
|
|
138
|
+
childTableFormControl: Object.freeze([behaviorBinding("test/child-table.test.ts#form.draft scaffolds a Sheet201 control with columns and keeps child keys out of viewJson", assertFieldContract)]),
|
|
139
|
+
dateDefaultOptions: Object.freeze([emitterBinding("lanes/field-contract.FIELD_DATE_DEFAULT_OPTIONS", assertFieldContract)]),
|
|
140
|
+
formulaOptions: Object.freeze([behaviorBinding("test/formula-resultformat.test.ts#validateFormulaOptions accepts the fwb", assertFieldContract)]),
|
|
141
|
+
formulaConfig: Object.freeze([behaviorBinding("test/field-families.test.ts#field.create FORMULA persists formulaConfig + persistent", assertFieldContract)]),
|
|
142
|
+
formulaRuntimeVerification: Object.freeze([behaviorBinding("test/field-families.test.ts#field.create FORMULA ACCEPTS aggregation written as an EXPRESSION (form 计算控件 subtable SUM; UI+runtime-verified 2026-10-07)", assertFieldContract)]),
|
|
143
|
+
relevanceDataOptions: Object.freeze([behaviorBinding("test/field-families.test.ts#field.create RELEVANCE_DATA persists the referenceField options", assertFieldContract)]),
|
|
144
|
+
publishScope: Object.freeze([behaviorBinding("test/field-publish-batch.test.ts#field.publish batch: a single call publishes every draft field", assertFieldContract)]),
|
|
145
|
+
controlEmissionPolicy: Object.freeze([behaviorBinding("test/ticket-101-control-coverage.test.ts#controls 24 (PHONE) and 10 (PHOTO) are declared blocked", assertFieldContract)]),
|
|
146
|
+
fieldRowDefaultPolicy: Object.freeze([behaviorBinding("test/ticket-108-field-row-defaults.test.ts#intentional minimal defaults are pinned per the determination table", assertFieldContract)]),
|
|
147
|
+
}),
|
|
148
|
+
evidence: Object.freeze([
|
|
149
|
+
"ticket 01-3 (2026-09-11): a DATE(3) field created without options.format 50000s on the first runtime save",
|
|
150
|
+
"cp-sources/backend/decompiled-full/.../BizObjectFacadeImpl.java:2949 reads JSON.parseObject(options).get(\"format\")",
|
|
151
|
+
"form-schema-contract.md:404 designer date control defaults format/format1 to YYYY-MM-DD",
|
|
152
|
+
"8.6.26 FormulaPropertyOptions (cloudpivot-shared-8.6.26): options={formulaConfig:string,persistent}; FormulaConfig={resultType,resultFormat,formulaType,expression,aggregation}; FormulaProcessor reads config.expression as a JSON string {formula,editorText,editorMark} and blanks {fieldCode} placeholders",
|
|
153
|
+
"omc-core formula-field-contract.ts v1 (live-verified): {formulaConfig,persistent:true}, resultType 0|2, resultFormat \"\"|\"percentile\"",
|
|
154
|
+
"field-families-fwb-20260914.md:170-180 (fwb readback 2026-09-14): FORMULA(100) field row options = {formulaConfig, persistent, format} with formulaConfig.resultFormat \"percentile\" and outer format \"percentile\" — the evidenced non-empty resultFormat and the readback-only outer format key are accepted; unknown values stay refused fail-closed",
|
|
155
|
+
"ticket 24 live (2026-09-12): FORMULA options read back verbatim via field.list; EXPRESSION field evaluated 3+4=7 on save. An empty-queryConditions AGGREGATION probe evaluated to 0 — REVERSED 2026-10-07: that was a false negative; AGGREGATION (表单「计算」控件「聚合计算」, 跨模型聚合) is supported; subtable→main roll-up and child-column arithmetic are delivered as 普通字段+计算规则 (datarule type2, recipes field-compute-subtable-sum / field-compute-child-column; UI+runtime verified 2026-10-08) — the earlier FORMULA-field recipes were removed as the wrong vehicle",
|
|
156
|
+
"8.6.26 RelevanceDataOptions (bizmodel): {relevanceField,referenceField,referenceFieldPropertyType,referenceFieldControlType}; validateRelevanceDataPropertyConfig requires referenceField+relevanceField; admin field serializer adds originalOptions/format1",
|
|
157
|
+
"ticket 24 live (2026-09-12): FORMULA options readback + RELEVANCE_DATA create/publish/form-binding readback",
|
|
158
|
+
"ticket 61 source (8.6.26): the runtime list face resolves a relation's displayed value from the field ROW's top-level relativePropertyCode, not options.displayField — QueryRuntimeController.java:1214-1226 (getRelativePropertyCode; empty → \"name\" data title); BizPropertyController create/update :851/:987 never auto-fill it, so every relation create/update must carry it",
|
|
159
|
+
"capability-shape-spec.md: field-row and form-control options are declared once with required keys, defaults, and evidence; LOGICAL/ATTACHMENT/ADDRESS/HYPER_LINK/TIME are completed",
|
|
160
|
+
]),
|
|
161
|
+
tools: Object.freeze({
|
|
162
|
+
"field.list": Object.freeze({
|
|
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).",
|
|
165
|
+
}),
|
|
166
|
+
"field.create": Object.freeze({
|
|
167
|
+
scope: "create publish readback",
|
|
168
|
+
description: describeTool("Create a draft field on a model (bizproperty/create).", [
|
|
169
|
+
"Field type must be one of the live-accepted families; nested child tables and OCR/ELECTRONIC_SIGN are out of coverage.",
|
|
170
|
+
`Reserved/system codes are refused (code_reserved): ${[...RESERVED_CODES].join(", ")} — pick a business code (e.g. owner → taskOwner).`,
|
|
171
|
+
"The relation field family name is `WORK_SHEET` (there is no RELATED_SINGLE/RELATION): pass `propertyType:\"WORK_SHEET\"` + `relativeCode:<schemaCode>` + `options:{schemaCode,queryCode,displayField,displayFieldType,mappings}`; `mappings` is a JSON *string* (empty string when there is no mapping).",
|
|
172
|
+
"For single/multi-select pass `choices` (e.g. [\"A\",\"B\",\"C\"]) or `options.optionsSet` with optionsType custom/dictionary/businessModel; dictionary uses checkedDictionary/checkedDictionaryCode, businessModel uses schemaCode/sheetDataItem.",
|
|
173
|
+
"For a relation pass `relativeCode` and `options` (schemaCode/displayField/...). `searchFormula` and `conditions` are JSON strings for the relation data restriction/query conditions.",
|
|
174
|
+
"For a relation display field the tool writes the field-row top-level `relativePropertyCode` = options.displayField (the runtime reads THAT key, not options.displayField — QueryRuntimeController.java:1214-1226) and defaults options.displayFieldType:0 + displayFieldFormat:\"\".",
|
|
175
|
+
"For FORMULA pass `options.formulaConfig` (nested JSON string) + `options.persistent:true`; for RELEVANCE_DATA pass `options.relevanceField` + `options.referenceField` + `options.referenceFieldPropertyType`.",
|
|
176
|
+
"org 选人族(STAFF_SELECTOR 等 5/50/51/60/61)字段行 options 自动写成实例观测的发布安全形状(yst/fwb 发布面 2656 行:null 或 {defaultValue, mappings, virtualField[, noRepeat]};单选 defaultValue \"\",多选 [])。deptVisible/multi 是**表单控件面**判别键(disposeUpdateType/updateSelectionType 读 control.options,票 69 已由表单脚手架写入控件面),不出现在字段行。",
|
|
177
|
+
]),
|
|
178
|
+
}),
|
|
179
|
+
"field.update": Object.freeze({
|
|
180
|
+
scope: "create publish readback",
|
|
181
|
+
description: describeTool("Update an existing field (bizproperty/update) — merges `options` (and optional `choices`/`relativeCode`) onto the current draft/published record.", [
|
|
182
|
+
"**不切换 propertyType**:field.update 传 propertyType 会被静默忽略(errcode 0 但类型不变,r6 实证 2026-10-10)——已发布字段改类型只能 field.delete + field.create 重建(含关联 mappings 的同类型对齐场景:人员单选只能映射给人员单选)。choices 只对文本单选族(RADIO/DROPDOWN_BOX 等)合法,传给其它类型会被出门校验拒。",
|
|
183
|
+
"Use it to add relation `mappings` (source/target carry-through) or change field options.",
|
|
184
|
+
"A relation's display field is the field-row top-level `relativePropertyCode` (options.displayField is mirrored but not what the runtime reads); the tool rewrites it when you pass a new displayField.",
|
|
185
|
+
"表单条件(`options.requiredFormula`(必填)/`readonlyCondition`(只读)/`displayFormula`(显示))会**自动配对**一条 `bizdatarule` type3/4/5 行:门户**运行时**读字段 options,表单设计器**设计态** Set/Unset 读 `bizdatarule/list`——只写 options 会让设计器显示 Unset。readback.formConditionSync 报 created/updated/deleted/skipped;清空条件传空串(如 requiredFormula:\"\")会同时删规则行;字段未发布时只写 options 并在 skipped 说明原因。",
|
|
186
|
+
"Re-publish with field.publish for the change to take effect.",
|
|
187
|
+
]),
|
|
188
|
+
}),
|
|
189
|
+
"field.publish": Object.freeze({
|
|
190
|
+
scope: "create publish readback",
|
|
191
|
+
description: "Publish the model's draft fields (bizproperty/publish). **Model-scoped**: one call publishes every draft field of the schema — never call once per field. Optional `code`/`codes` verify which fields landed on the published face; the readback also lists all `publishedCodes`. 瞬态重试(ticket 79):**异常小资源环境下**(实测该 test 环境 MySQL 限 1GB/缓冲池 128MB、I/O 被 Quartz 调度器占满,事故夜 30 个 publish 事务挂起 >30s 最长 193s)publish 走 DDL+序列化器定义同步,失败尝试 DDL 自动提交而标志回滚,留下「MySQL 有列 / 序列化器视图无列」中间态,后续 publish 报 `表单:<t>_<schema>不存在列:<col>` 并逐列自愈。常规资源环境预计不触发;工具仍对该特征自动重试至多 3 次(退避 2s/5s),预算耗尽原样浮出。若仍失败:等 ≥30s 再重发本次 publish,勿重复建字段。与字段 options 形状无关(yst/fwb 发布面 2656 行 org 族字段行无强制键)。",
|
|
192
|
+
}),
|
|
193
|
+
"field.delete": Object.freeze({
|
|
194
|
+
scope: "create publish readback",
|
|
195
|
+
description: "Force-delete a field (bizproperty/force_delete) with exact-absence readback on both faces.",
|
|
196
|
+
}),
|
|
197
|
+
}),
|
|
198
|
+
});
|
|
199
|
+
export function assertFieldContract() {
|
|
200
|
+
assertCapabilityShapeContract();
|
|
201
|
+
assertLaneContract(FIELD_LANE_CONTRACT);
|
|
202
|
+
if (FIELD_DATE_DEFAULT_OPTIONS.format !== "YYYY-MM-DD")
|
|
203
|
+
throw new Error("field contract requires the DATE default format YYYY-MM-DD");
|
|
204
|
+
if (!String(FIELD_LANE_CONTRACT.wire.formulaOptions).includes("formulaConfig") || !String(FIELD_LANE_CONTRACT.wire.formulaOptions).includes("persistent") || !String(FIELD_LANE_CONTRACT.wire.formulaConfig).includes("resultType"))
|
|
205
|
+
throw new Error("field contract must carry the FORMULA formulaConfig wire facts");
|
|
206
|
+
if (!String(FIELD_LANE_CONTRACT.wire.relevanceDataOptions).includes("relevanceField"))
|
|
207
|
+
throw new Error("field contract must carry the RELEVANCE_DATA referenceField wire facts");
|
|
208
|
+
if (!String(FIELD_LANE_CONTRACT.wire.controlEmissionPolicy).includes("BizPropertyType.java:27-54"))
|
|
209
|
+
throw new Error("field contract must carry the ticket-101 control-emission policy with its enum evidence");
|
|
210
|
+
if (!String(FIELD_LANE_CONTRACT.wire.fieldRowDefaultPolicy).includes("MUST-FIXED"))
|
|
211
|
+
throw new Error("field contract must carry the ticket-108 field-row default determination");
|
|
212
|
+
if (!String(FIELD_LANE_CONTRACT.wire.acceptedFamilies).includes("SHORT_TEXT") || !String(FIELD_LANE_CONTRACT.wire.acceptedFamilies).includes("FORMULA"))
|
|
213
|
+
throw new Error("field contract must carry the accepted family list");
|
|
214
|
+
if (!String(FIELD_LANE_CONTRACT.wire.blockedFamilies).includes("OCR"))
|
|
215
|
+
throw new Error("field contract must carry the blocked families");
|
|
216
|
+
if (FIELD_LANE_CONTRACT.wire.publishScope !== "model")
|
|
217
|
+
throw new Error("field contract pins the publish scope to model");
|
|
218
|
+
assertDescriptionCarries(FIELD_LANE_CONTRACT, "field.create", ["bizproperty/create", "OCR/ELECTRONIC_SIGN", "`choices`", "options.optionsSet", "`relativeCode`", "searchFormula", "`options.formulaConfig`", "`options.relevanceField`", "code_reserved", "WORK_SHEET"]);
|
|
219
|
+
assertDescriptionCarries(FIELD_LANE_CONTRACT, "field.update", ["bizproperty/update", "`options`", "field.publish"]);
|
|
220
|
+
assertDescriptionCarries(FIELD_LANE_CONTRACT, "field.publish", ["bizproperty/publish", "published", "Model-scoped", "publishedCodes"]);
|
|
221
|
+
assertDescriptionCarries(FIELD_LANE_CONTRACT, "field.delete", ["bizproperty/force_delete", "absence"]);
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=field-contract.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { claim, declareLaneCoverage } from "./coverage-declaration.js";
|
|
2
|
+
import { FIELD_LANE_CONTRACT } from "./field-contract.js";
|
|
3
|
+
const T = FIELD_LANE_CONTRACT.tools;
|
|
4
|
+
export const FIELD_COVERAGE = declareLaneCoverage(FIELD_LANE_CONTRACT.lane, [
|
|
5
|
+
{
|
|
6
|
+
capability: "Field family full chain: create→publish→form draft→form publish→control binding readback (seven live-accepted families)",
|
|
7
|
+
evidence: ["src/families/registry.ts", ".scratch/omc-field-type-ladder/research/formula-contract.md"],
|
|
8
|
+
tools: [
|
|
9
|
+
// Every claim reads its scope from the contract, so the registration (which
|
|
10
|
+
// also reads the contract) and the coverage declaration cannot drift. A
|
|
11
|
+
// locally-authored scope string here would only be held equal by
|
|
12
|
+
// assertToolSurfaceConsistent — exactly the duplicate that guard exists to
|
|
13
|
+
// catch, so don't introduce one.
|
|
14
|
+
claim("field.list", T["field.list"].scope),
|
|
15
|
+
claim("field.create", T["field.create"].scope),
|
|
16
|
+
claim("field.update", T["field.update"].scope),
|
|
17
|
+
claim("field.publish", T["field.publish"].scope),
|
|
18
|
+
claim("field.delete", T["field.delete"].scope),
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
capability: "Numeric-logical and date-time field families full chain",
|
|
23
|
+
evidence: ["src/families/registry.ts", ".scratch/omc-field-type-ladder/issues/02-numeric-logical-family.md"],
|
|
24
|
+
tools: [],
|
|
25
|
+
},
|
|
26
|
+
]);
|
|
27
|
+
//# sourceMappingURL=field-coverage.js.map
|