@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 { z } from "zod";
|
|
2
|
+
import { assertDescriptionCarries, assertLaneContract, behaviorBinding, CONTRACT_FAMILY, CONTRACT_REFERENCE_VERSION, emitterBinding } from "./contract-support.js";
|
|
3
|
+
import { LANES } from "./lane-ids.js";
|
|
4
|
+
/**
|
|
5
|
+
* W7 greenfield workflow authoring + the runtime work-item query face
|
|
6
|
+
* (live-proven). The template head/bind points and the search_workitems
|
|
7
|
+
* decoding are the single source for the handler descriptions, the arg schema,
|
|
8
|
+
* and the coverage declarations.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The four WorkflowTemplateModel event handlers keyed by the `handler` value
|
|
12
|
+
* workflow.bindRule accepts. All four are the same ActivityEventHandler DTO
|
|
13
|
+
* carrying `bizActions:[<ruleCode>]` + `bizActionType:"BIZ_RULE"`.
|
|
14
|
+
*/
|
|
15
|
+
export const WORKFLOW_EVENT_HANDLER_FIELDS = Object.freeze({
|
|
16
|
+
start: "startEventHandler",
|
|
17
|
+
cancel: "cancelEventHandler",
|
|
18
|
+
activate: "activateEventHandler",
|
|
19
|
+
end: "endEventHandler",
|
|
20
|
+
});
|
|
21
|
+
export const WORKFLOW_WIRE = Object.freeze({
|
|
22
|
+
templateShape: '{"workflowCode":"<code>","activities":[{"id":"start","type":"START"},{"id":"approve","type":"PARTICIPANT","participant":"<user>"},{"id":"end","type":"END"}],"routes":[{"preNode":"start","postNode":"approve"}]}(ticket 112:routes 会被工具映射为平台 DTO 的 rules[preActivityCode/postActivityCode];templateType 勿传 "BusinessProcess"——非 WorkflowTemplateStatus 枚举成员,转换被吞成残缺模型后 50000;工具会把模板合并到 get_draft 全量行再上送,未给字段回显草稿)。条件分支连线见 routeBranch。',
|
|
23
|
+
/**
|
|
24
|
+
* Conditional branch lines. The platform's `Rule` DTO (Rule.java:28-59) — the
|
|
25
|
+
* wire element `routes[]` maps to — carries `ruleConditionGroup`
|
|
26
|
+
* (List<List<RuleConditionItem>>): outer list OR, inner list AND. Evaluation
|
|
27
|
+
* (ActivityContext.getNextFormulaActivities:82-99 + ConditionVerification
|
|
28
|
+
* .verify:82-154): a rule fires when popupType is EXPRESSION (default) and
|
|
29
|
+
* verify(bizObj, ruleConditionGroup, childMatchType) is true, else it falls
|
|
30
|
+
* back to `formula`. A rule with utilizeElse=true is the else/fallback line.
|
|
31
|
+
*/
|
|
32
|
+
routeBranch: '条件分支连线(平台 Rule.java:28-59,routes[] 映射的目标 DTO):routes[] 条目可带 ruleConditionGroup = List<List<RuleConditionItem>>,外层 OR、内层 AND,满足才走该连线。RuleConditionItem = {"currentDataItem":"<fieldCode 或 childSchemaCode.fieldCode>","bizPropertyType":<BizPropertyType 的数字索引>,"conditionType":"<ConditionType 枚举名>","value":<任意>};**bizPropertyType 必须用数字索引**(平台 BizPropertyTypeDeserializer 读的是 int:SHORT_TEXT=0/NUMERICAL=2/DATE=3/LOGICAL=4/RADIO=12/DROPDOWN_BOX=14/STAFF_SELECTOR=50/DEPARTMENT_SELECTOR=60/WORK_SHEET=9/CHILD_TABLE=8…),写枚举名会被 castToInt 吞成 0 并让模板转换失败(真机报误导性的「流程名称为空!」);工具接受枚举名并自动转索引。**RuleConditionItem 只接受这 4 个键;多一个未知键(如照抄业务规则的 ruleValueType/targetDataItem)会让平台 workflow/update 返回误导性的 `401001 流程不存在!`**(真机 2026-09-25),工具写前拒绝未知键。conditionType 取值 EQ/NEQ/GT/LT/GTEQ/LTEQ/CT(包含)/NCT/EP(为空)/NEP(非空)/BETWEEN/NOTBETWEEN/OF/NOF/CT_ALL/NCT_ALL/CT_ANY/NCT_ANY/EQ_ANY/NEQ_ANY。子表字段(currentDataItem 含 ".")的行匹配由同级 childMatchType 决定:ALL=每行都满足,ANY=任一行满足(缺省 ANY)。连线另可带 text(显示名)、utilizeElse:true(else/兜底连线:其余条件不满足时走)、alternativeFlag:true(审批人可选分支)、formula(字符串表达式,与 ruleConditionGroup 二选一;两者都存在时结构化组先判,未命中再判 formula)。',
|
|
33
|
+
authoringChain: "workflow.create (header) → workflow.update (write draft template) → workflow.publish",
|
|
34
|
+
bindPoint: "startEventHandler|cancelEventHandler|activateEventHandler|endEventHandler{bizActions:[<ruleCode>], bizActionType:\"BIZ_RULE\"}",
|
|
35
|
+
bindRuleChain: "workflow.bindRule reads the draft, merges the handler selected by `handler` (start|cancel|activate|end, default end), workflow/update, then workflow/publish + published-face readback",
|
|
36
|
+
renderCompat: "workflow.update/publish/bindRule fail closed on 8.6.26 ActivityType values, unique non-empty activityCode values, rules references, and non-empty `x, y` points; missing points are derived from activity geometry and every write readback carries workflowRenderCompat with activities, rules, START/END, points, and danglingViolations",
|
|
37
|
+
bindRuleScope: "all four WorkflowTemplateModel event handlers (startEventHandler/cancelEventHandler/activateEventHandler/endEventHandler), each an ActivityEventHandler carrying bizActions + bizActionType=BIZ_RULE; `handler` defaults to end",
|
|
38
|
+
boundRuleMustBeEnabled: "流程事件绑定的规则**必须启用**:禁用/未发布的规则(rule.save 落 DRAFT/DISABLED 态)绑到事件处理器后设计器显示「失效·未启用」且事件不会执行它(真机 2026-10-08 SCM 沙盒)。workflow.bindRule 会先把绑定的自定义规则 publish+enable(rule.enable 链,回读 enabledRuleCodes/alreadyEnabledRuleCodes),并对不存在的 code 报 workflow-bind-rule-absent",
|
|
39
|
+
deleteAbsence: "workflow.delete posts /workflow/delete then confirms absence via workflow/get_header",
|
|
40
|
+
workItemPage: "GET /api/api/runtime/workflow/search_workitems returns PageVO<WorkItemVO> { totalPages, totalElements, content } directly (a page/data wrapper is tolerated)",
|
|
41
|
+
workItemIdentity: "item.id=workItemId, item.instanceId=workflowInstanceId, item.activityName, item.state",
|
|
42
|
+
workItemFilter: "WorkItemSearchVO.filterWorkflowInstanceId is a NOT-equal exclusion (BizWorkitemServiceImpl.toSearchWorkItemsCriterion:400-402), so exact instance filtering is client-side",
|
|
43
|
+
bizObjectResolution: "GET /api/api/runtime/workflow/getBizObjectByWfInstanceId resolves bizObjectId/schemaCode; a failed lookup leaves the identity null and never drops the todo",
|
|
44
|
+
mutuallyExclusiveBinding: "同一处理器绑定多条规则时它们**全部执行、无互斥**:审批通过/驳回这类互斥结果不要用两条各自 FIXED 赋值都绑 end(bench22 病灶)——通过绑 end(endEventHandler)或规则 Available,驳回绑 cancel(cancelEventHandler)或规则 Cancel,或用一条多分支图(生产 case_info_update 只在 endEventHandler 绑一条 updateData 多分支图);workflow.bindRule 回读在 bizActions.length>1 时给 advisory",
|
|
45
|
+
userSearch: "POST /api/api/organization/user/search,@RequestBody {wd (关键字,必填), page, size, filterType?} → PageVO<UserVO>{totalElements,totalPages,content[{id,name,username,userId,departmentId,corpId,status}]}(UserController.search:337-341;缺 wd 报 10005 关键字不能为空)。用于把姓名解析成真实用户,构造参与者对象 type 3=用户(type 2=角色)",
|
|
46
|
+
});
|
|
47
|
+
/** Workflow template object (workflow/update|publish raw body). */
|
|
48
|
+
export const workflowTemplateArg = z
|
|
49
|
+
.record(z.string(), z.unknown())
|
|
50
|
+
.describe(`workflow template object. Minimal valid shape (create via workflow.create first, then workflow.update with this, then workflow.publish): ${WORKFLOW_WIRE.templateShape}. Add approval activities between start/end (each with id/type/participant) and routes[] as needed. **参与人解析陷阱(r5-crm 实证 2026-10-10)**:内置 FindUserByRole({Originator.OU},code,...) 按部门范围找人——目标角色**不挂部门**(如全公司唯一的总监)时 ParticipantActivityRuntime.initParticipants 抛 EngineRuntimeException、流程卡 PROCESSING 无待办;跨部门/全局角色用不依赖 OU 的解析(二开 FindUsersSpecByRoleFunction(code) 全局找人,或参与人挂 OU 树可覆盖的部门)。 **START 之后必须保留发起节点**(如「填写申请单」participant={Originator},删掉/缺失则 publish 401035——r5-crm 实证 2026-10-09);流程模型的数据入口=直接 data.submit(创建+启流程+单据号生成,勿用 save+submit 两步)。 A route entry MAY carry the platform's structured branch condition ruleConditionGroup (outer OR / inner AND) plus childMatchType/utilizeElse/alternativeFlag/text — see the workflow contract's routeBranch: ${WORKFLOW_WIRE.routeBranch}. endEventHandler{bizActions,bizActionType} binds business rules — prefer workflow.bindRule instead of replacing the whole template.`);
|
|
51
|
+
const WORKFLOW_SCOPE = "greenfield workflow authoring";
|
|
52
|
+
export const WORKFLOW_LANE_CONTRACT = Object.freeze({
|
|
53
|
+
lane: LANES.workflow,
|
|
54
|
+
family: CONTRACT_FAMILY,
|
|
55
|
+
referenceVersion: CONTRACT_REFERENCE_VERSION,
|
|
56
|
+
endpoints: Object.freeze({
|
|
57
|
+
create: "workflowCreate",
|
|
58
|
+
getHeader: "workflowGetHeader",
|
|
59
|
+
getDraft: "workflowGetDraft",
|
|
60
|
+
getPublished: "workflowGetPublished",
|
|
61
|
+
update: "workflowUpdate",
|
|
62
|
+
publish: "workflowPublish",
|
|
63
|
+
delete: "workflowDelete",
|
|
64
|
+
searchWorkItems: "workflowSearchWorkItems",
|
|
65
|
+
getBizObjectByWfInstanceId: "workflowGetBizObjectByWfInstanceId",
|
|
66
|
+
}),
|
|
67
|
+
wire: Object.freeze({
|
|
68
|
+
templateShape: WORKFLOW_WIRE.templateShape,
|
|
69
|
+
routeBranch: WORKFLOW_WIRE.routeBranch,
|
|
70
|
+
authoringChain: WORKFLOW_WIRE.authoringChain,
|
|
71
|
+
bindPoint: WORKFLOW_WIRE.bindPoint,
|
|
72
|
+
bindRuleChain: WORKFLOW_WIRE.bindRuleChain,
|
|
73
|
+
renderCompat: WORKFLOW_WIRE.renderCompat,
|
|
74
|
+
bindRuleScope: WORKFLOW_WIRE.bindRuleScope,
|
|
75
|
+
boundRuleMustBeEnabled: WORKFLOW_WIRE.boundRuleMustBeEnabled,
|
|
76
|
+
eventHandlerFields: "handler start→startEventHandler, cancel→cancelEventHandler, activate→activateEventHandler, end→endEventHandler (WorkflowTemplateModel.java:48-55)",
|
|
77
|
+
deleteAbsence: WORKFLOW_WIRE.deleteAbsence,
|
|
78
|
+
workItemPage: WORKFLOW_WIRE.workItemPage,
|
|
79
|
+
workItemIdentity: WORKFLOW_WIRE.workItemIdentity,
|
|
80
|
+
workItemFilter: WORKFLOW_WIRE.workItemFilter,
|
|
81
|
+
bizObjectResolution: WORKFLOW_WIRE.bizObjectResolution,
|
|
82
|
+
mutuallyExclusiveBinding: WORKFLOW_WIRE.mutuallyExclusiveBinding,
|
|
83
|
+
userSearch: WORKFLOW_WIRE.userSearch,
|
|
84
|
+
}),
|
|
85
|
+
wireBindings: Object.freeze({
|
|
86
|
+
templateShape: Object.freeze([behaviorBinding("test/ticket-112-workflow-template-merge.test.ts#workflow.update merges onto the draft", assertWorkflowContract)]),
|
|
87
|
+
routeBranch: Object.freeze([behaviorBinding("test/round7-workflow-branch-conditions.test.ts#workflow route ruleConditionGroup rides the rules wire and reads back", assertWorkflowContract)]),
|
|
88
|
+
authoringChain: Object.freeze([behaviorBinding("test/ticket-112-workflow-template-merge.test.ts#workflow.publish also merges onto the draft", assertWorkflowContract)]),
|
|
89
|
+
bindPoint: Object.freeze([emitterBinding("lanes/workflow-contract.WORKFLOW_EVENT_HANDLER_FIELDS", assertWorkflowContract)]),
|
|
90
|
+
bindRuleChain: Object.freeze([behaviorBinding("test/issue-14-workflow-bind-rule.test.ts#workflow.bindRule merges endEventHandler", assertWorkflowContract)]),
|
|
91
|
+
renderCompat: Object.freeze([behaviorBinding("test/ticket-112-workflow-template-merge.test.ts#workflow shorthand maps legal activities and derives points into workflowRenderCompat", assertWorkflowContract)]),
|
|
92
|
+
bindRuleScope: Object.freeze([behaviorBinding("test/issue-14-workflow-bind-rule.test.ts#workflow.bindRule binds start/cancel/end handlers independently", assertWorkflowContract)]),
|
|
93
|
+
boundRuleMustBeEnabled: Object.freeze([behaviorBinding("test/issue-14-workflow-bind-rule.test.ts#workflow.bindRule ENABLES a bound custom rule", assertWorkflowContract)]),
|
|
94
|
+
eventHandlerFields: Object.freeze([emitterBinding("lanes/workflow-contract.WORKFLOW_EVENT_HANDLER_FIELDS", assertWorkflowContract)]),
|
|
95
|
+
deleteAbsence: Object.freeze([behaviorBinding("test/round2-bug05-workflow-absent.test.ts#workflow.get_published on a missing workflow answers exists:false", assertWorkflowContract)]),
|
|
96
|
+
workItemPage: Object.freeze([emitterBinding("workflow-support.decodeWorkItemPage", assertWorkflowContract)]),
|
|
97
|
+
workItemIdentity: Object.freeze([emitterBinding("workflow-support.decodeWorkItemPage", assertWorkflowContract)]),
|
|
98
|
+
workItemFilter: Object.freeze([emitterBinding("workflow-support.searchWorkItems", assertWorkflowContract)]),
|
|
99
|
+
bizObjectResolution: Object.freeze([emitterBinding("workflow-support.resolveBizObjectIdByInstance", assertWorkflowContract)]),
|
|
100
|
+
mutuallyExclusiveBinding: Object.freeze([behaviorBinding("test/issue-14-workflow-bind-rule.test.ts#workflow.bindRule merges endEventHandler", assertWorkflowContract)]),
|
|
101
|
+
userSearch: Object.freeze([behaviorBinding("test/round4-org-user-search.test.ts#org.user.search resolves a user by name into participant fields", assertWorkflowContract)]),
|
|
102
|
+
}),
|
|
103
|
+
evidence: Object.freeze([
|
|
104
|
+
".scratch/omc-approval-workflow/acceptance/s29-probe-20260910012330184.md",
|
|
105
|
+
"packages/omc-cli/src/lanes/workflow.ts",
|
|
106
|
+
".scratch/omc-app-management/issues/06-workitem-list-capability.md",
|
|
107
|
+
]),
|
|
108
|
+
tools: Object.freeze({
|
|
109
|
+
"workflow.get_draft": Object.freeze({
|
|
110
|
+
scope: WORKFLOW_SCOPE,
|
|
111
|
+
description: "Read the current DRAFT workflow template (`/api/api/workflow/get_draft`). **默认返回 workflowSummary(activities 节点清单 code/type/name/participant + edges 连线 + ruleBindings),不是整份 30–75KB 正文**——**改流程或复核更新结果都用这个默认面即可(activities+edges 足够传给 workflow.update);只有要看通知/字段权限等完整节点正文时才加 --full**。用于确认绑定点(如 endEventHandler)而无需猜其它字段。",
|
|
112
|
+
}),
|
|
113
|
+
"workflow.get_published": Object.freeze({
|
|
114
|
+
scope: WORKFLOW_SCOPE,
|
|
115
|
+
description: "Read the current PUBLISHED workflow template (`/api/api/workflow/get_published`). **默认返回 workflowSummary(activities + ruleBindings),不是整份正文**;完整正文加 --full 或用 `artifact get --summary/--keys/--jq`。在 workflow.publish / workflow.bindRule 之后用它确认发布后的绑定点。",
|
|
116
|
+
}),
|
|
117
|
+
"workflow.create": Object.freeze({
|
|
118
|
+
scope: WORKFLOW_SCOPE,
|
|
119
|
+
description: "创建工作流模板头(`/api/api/workflow/create`)。随后用 `workflow.update` 写入模板 JSON,再 `workflow.publish` 发布。**平台会自动生成含发起节点的草稿**(START → PARTICIPANT「填写申请单」participant={Originator} → PARTICIPANT「审批」participant 空 → END)——审批参与人必须显式补平台关键字(如 `{Originator}`=发起人),留空行为未知;get_draft 可核对自动草稿形状。",
|
|
120
|
+
}),
|
|
121
|
+
"workflow.update": Object.freeze({
|
|
122
|
+
scope: WORKFLOW_SCOPE,
|
|
123
|
+
description: "写入工作流模板草稿(`/api/api/workflow/update`,raw template JSON body)。cli 以当前草稿为基线做 merge,未列出的既有节点保留:**模板缺 START 或 END 时自动按增量 merge(部分模板),给全 START..END 才整模板替换**;也可显式 `merge:true/false`。**节点字段权限也走这里**:不必读 `get_draft --full`——直接发 `activities:[{activityCode, activityType:\"PARTICIPANT\", propertyPermissions:[{propertyCode, visible, editable, required, summary, subPropertyPermissions}]}]`,工具按 propertyCode 合并到草稿对应节点(未列的字段权限保留;`merge:true` 也可同用)——没有单独的权限工具,别把「找不到入口」当成不支持(dogfood 实测该误判会假阻塞)。**`summary:true` 才会进运行时的 `activitySummaries`**,否则 `form/load` 的 `formPermission.dataPermissions` 会回退默认(编辑权读不到你的 `editable:false`);子表字段用 `subPropertyPermissions`。用 `npm run test:live-permission`(非管理员参与者)验收,管理员会被后端强制 `e:true` 掩盖。",
|
|
124
|
+
}),
|
|
125
|
+
"workflow.publish": Object.freeze({
|
|
126
|
+
scope: WORKFLOW_SCOPE,
|
|
127
|
+
description: "发布工作流模板(`/api/api/workflow/publish`,raw template JSON body)。`template` **必填**(2026-09-22 实测:省略被拒 tool-input-invalid: template Required;早期'可省'的说法不对)。",
|
|
128
|
+
}),
|
|
129
|
+
"workflow.bindRule": Object.freeze({
|
|
130
|
+
scope: WORKFLOW_SCOPE,
|
|
131
|
+
description: "Bind a business rule to one of a workflow's event handlers (BIZ_RULE). `handler` selects the target: `start`→startEventHandler, `cancel`→cancelEventHandler, `activate`→activateEventHandler, `end`→endEventHandler (default `end`). Reads the current draft, merges `{ bizActions:[<ruleCode>], bizActionType:\"BIZ_RULE\" }` into the selected handler, writes via `/api/api/workflow/update`, then publishes the template and reads back the published face to confirm the binding without overwriting the rest of the template. **A workflow-bound rule MUST be enabled**(真机 2026-10-08):禁用/未发布(rule.save 落 DRAFT/DISABLED)的规则绑上后设计器显示「失效·未启用」且事件不执行它;本工具先把绑定的自定义规则 publish+enable(回读 `enabledRuleCodes`/`alreadyEnabledRuleCodes`),不存在的 code 报 `workflow-bind-rule-absent`。The four handlers are isomorphic ActivityEventHandler fields on WorkflowTemplateModel, so when `handler` is omitted the behaviour is identical to the original endEventHandler binding. Pass `publish:false` to leave the template draft-only.",
|
|
132
|
+
}),
|
|
133
|
+
"workflow.delete": Object.freeze({
|
|
134
|
+
scope: WORKFLOW_SCOPE,
|
|
135
|
+
description: "删除工作流模板(`/api/api/workflow/delete`),回读确认缺失。",
|
|
136
|
+
}),
|
|
137
|
+
"workflow.validate": Object.freeze({
|
|
138
|
+
scope: WORKFLOW_SCOPE,
|
|
139
|
+
description: "只读预检(`POST /api/api/workflow/validate`):合成草稿模板(或可选 `template` 按 merge 语义)后返回 ValidateMessage[],拆出 errors/warnings,`valid = 无 ERROR`。用于 publish 前先看平台会不会拒——平台对 publish 常回 errcode:0 但 ValidateMessage[] 里带 ERROR,本工具把它显式暴露,避免「publish 看似成功却没落库」。不写任何状态。",
|
|
140
|
+
}),
|
|
141
|
+
configure_workflow: Object.freeze({
|
|
142
|
+
scope: WORKFLOW_SCOPE,
|
|
143
|
+
description: "High-level greenfield:一次走完 `workflow.create → workflow.update(template) → workflow.publish`,可选 `bindRules:[{handler?,ruleCodes[]}]` 在发布后经 `workflow.bindRule` 绑定业务规则。复用各原子工具自身的写执行,因此门禁与权威读回与逐条调用完全一致;首败即停并返回已完成步骤与失败点。每条 bindRules 的 handler 取 start|cancel|activate|end(缺省 end)。",
|
|
144
|
+
}),
|
|
145
|
+
"org.role.list": Object.freeze({
|
|
146
|
+
scope: "workflow participant resolution",
|
|
147
|
+
description: "列出组织角色(`GET /api/api/organization/role/list`),扁平化为 {id,name,code,roleType,corpId}。用于把审批节点的参与者解析成平台认识的引用。**真实参与者语法**(2026-09-23 生产观察):`participant` 只能是 (a) 关键字 `{Originator}`;(b) 参与者对象数组 JSON `[{\"code\":\"<roleCode>\",\"corpId\":\"<corpId|other>\",\"id\":\"<roleId>\",\"name\":\"<角色名>\",\"type\":2}]`(type 2=角色,3=用户;多个用 `+` 连接);(c) 函数表达式如 `FindUserByRole({Originator.OU},\"<roleCode>\",\"random\")`。**自由文本角色名(如 `部门负责人`)能 publish 但解析不到人、不生成待办**——先用本工具拿到 `code`/`id` 再构造对象数组。",
|
|
148
|
+
}),
|
|
149
|
+
"org.department.list": Object.freeze({
|
|
150
|
+
scope: "workflow participant resolution",
|
|
151
|
+
description: "列出组织结构(`GET /api/api/organization/department/tree`),扁平化为 {id,name,code,corpId,parentId}。用于需要按部门解析审批人(配合 `FindUserByRole({Originator.OU},\"<roleCode>\",\"random\")` 或部门引用)时取得真实 code/id。",
|
|
152
|
+
}),
|
|
153
|
+
"org.user.search": Object.freeze({
|
|
154
|
+
scope: "workflow participant resolution",
|
|
155
|
+
description: "按关键字搜索用户(`POST /api/api/organization/user/search`,body `{wd,page,size,filterType?}`;`wd` 必填,缺失报 10005 关键字不能为空),返回 {id,name,username,userId,departmentId,corpId,status}。用于把「张三」这类姓名解析成真实用户 id/username 再构造参与者对象(`[{\"code\":\"<username|userId>\",\"corpId\":\"<corpId|other>\",\"id\":\"<userId>\",\"name\":\"<姓名>\",\"type\":3}]`,type 3=用户 / 2=角色 / 多个用 `+` 连接);角色用 org.role.list、部门用 org.department.list。",
|
|
156
|
+
}),
|
|
157
|
+
"workitem.list": Object.freeze({
|
|
158
|
+
scope: "runtime workflow work-item query",
|
|
159
|
+
description: "查询当前登录人的待办(`GET /api/api/runtime/workflow/search_workitems`)。WorkItemSearchVO 经 @ModelAttribute 传参,服务端以登录态注入 userId,故无需传处理人——结果天然是「我的待办」。返回每项 workItemId(id) + workflowInstanceId(instanceId) + activityName + state;并尽力经 `GET /api/api/runtime/workflow/getBizObjectByWfInstanceId` 解析 bizObjectId/schemaCode 供 data.submit 审批。`workflowInstanceId` 为客户端精确过滤(服务端 WorkItemSearchVO.filterWorkflowInstanceId 实为 notEqualsTo 排除,不能用于命中实例)。",
|
|
160
|
+
}),
|
|
161
|
+
}),
|
|
162
|
+
});
|
|
163
|
+
export function assertWorkflowContract() {
|
|
164
|
+
assertLaneContract(WORKFLOW_LANE_CONTRACT);
|
|
165
|
+
if (!WORKFLOW_WIRE.templateShape.includes("routes"))
|
|
166
|
+
throw new Error("workflow contract must document the routes->rules mapping in the template shape (ticket 112)");
|
|
167
|
+
if (!WORKFLOW_WIRE.routeBranch.includes("ruleConditionGroup") || !WORKFLOW_WIRE.routeBranch.includes("childMatchType"))
|
|
168
|
+
throw new Error("workflow contract must document the ruleConditionGroup branch shape (round7)");
|
|
169
|
+
if (!WORKFLOW_WIRE.templateShape.includes("routeBranch"))
|
|
170
|
+
throw new Error("workflow template shape must point at routeBranch for conditional lines");
|
|
171
|
+
if (!WORKFLOW_WIRE.bindPoint.includes("BIZ_RULE"))
|
|
172
|
+
throw new Error("workflow contract pins the rule bind point to bizActionType BIZ_RULE");
|
|
173
|
+
if (!WORKFLOW_WIRE.renderCompat.includes("workflowRenderCompat"))
|
|
174
|
+
throw new Error("workflow contract must pin workflow render compatibility readback");
|
|
175
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.get_draft", ["get_draft", "endEventHandler"]);
|
|
176
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.get_published", ["get_published", "workflow.publish"]);
|
|
177
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.create", ["workflow/create", "workflow.update", "workflow.publish"]);
|
|
178
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.update", ["workflow/update", "template"]);
|
|
179
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.publish", ["workflow/publish", "template"]);
|
|
180
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.bindRule", ["startEventHandler", "cancelEventHandler", "activateEventHandler", "endEventHandler", "bizActions", "bizActionType", "BIZ_RULE", "publish:false", "enabledRuleCodes", "workflow-bind-rule-absent"]);
|
|
181
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "org.role.list", ["organization/role/list", "type", "Originator"]);
|
|
182
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "org.department.list", ["organization/department/tree", "parentId"]);
|
|
183
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "org.user.search", ["organization/user/search", "wd", "type 3"]);
|
|
184
|
+
for (const [key, field] of Object.entries(WORKFLOW_EVENT_HANDLER_FIELDS)) {
|
|
185
|
+
if (!WORKFLOW_WIRE.bindRuleChain.includes(key))
|
|
186
|
+
throw new Error(`workflow contract bind-rule chain must mention the ${key} handler key`);
|
|
187
|
+
if (!(field.length > 0))
|
|
188
|
+
throw new Error("workflow event handler field names must be non-empty");
|
|
189
|
+
}
|
|
190
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.delete", ["workflow/delete", "缺失"]);
|
|
191
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workflow.validate", ["workflow/validate", "ValidateMessage", "valid"]);
|
|
192
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "configure_workflow", ["workflow.create", "workflow.update", "workflow.publish", "workflow.bindRule", "bindRules"]);
|
|
193
|
+
assertDescriptionCarries(WORKFLOW_LANE_CONTRACT, "workitem.list", ["search_workitems", "workItemId", "workflowInstanceId", "bizObjectId", "getBizObjectByWfInstanceId", "filterWorkflowInstanceId"]);
|
|
194
|
+
if (!workflowTemplateArg.description?.includes("routes"))
|
|
195
|
+
throw new Error("workflow template arg must document the routes->rules mapping");
|
|
196
|
+
if (workflowTemplateArg.description?.includes('\\"templateType\\":\\"BusinessProcess\\"') || workflowTemplateArg.description?.includes('"templateType":"BusinessProcess"'))
|
|
197
|
+
throw new Error("workflow template arg must not teach the illegal templateType BusinessProcess as a shape to send (ticket 112)");
|
|
198
|
+
if (!WORKFLOW_WIRE.templateShape.includes("rules[preActivityCode/postActivityCode]"))
|
|
199
|
+
throw new Error("workflow contract must pin the routes->rules mapping");
|
|
200
|
+
if (!WORKFLOW_WIRE.authoringChain.includes("workflow.publish"))
|
|
201
|
+
throw new Error("workflow contract must pin the authoring chain ending in publish");
|
|
202
|
+
if (!WORKFLOW_WIRE.bindRuleChain.includes("workflow/update"))
|
|
203
|
+
throw new Error("workflow contract must pin the bind-rule write step");
|
|
204
|
+
if (!WORKFLOW_WIRE.bindRuleScope.includes("startEventHandler") || !WORKFLOW_WIRE.bindRuleScope.includes("endEventHandler"))
|
|
205
|
+
throw new Error("workflow contract must pin the full event-handler scope");
|
|
206
|
+
if (!WORKFLOW_WIRE.boundRuleMustBeEnabled.includes("必须启用") || !WORKFLOW_WIRE.boundRuleMustBeEnabled.includes("rule.enable"))
|
|
207
|
+
throw new Error("workflow contract must pin that a workflow-bound rule is enabled");
|
|
208
|
+
if (WORKFLOW_EVENT_HANDLER_FIELDS.start !== "startEventHandler" || WORKFLOW_EVENT_HANDLER_FIELDS.end !== "endEventHandler")
|
|
209
|
+
throw new Error("workflow contract must pin the handler field names");
|
|
210
|
+
if (!WORKFLOW_WIRE.deleteAbsence.includes("workflow/delete") || !WORKFLOW_WIRE.deleteAbsence.includes("get_header"))
|
|
211
|
+
throw new Error("workflow contract must pin the delete absence readback");
|
|
212
|
+
if (!WORKFLOW_WIRE.workItemPage.includes("search_workitems"))
|
|
213
|
+
throw new Error("workflow contract must pin the work-item query endpoint");
|
|
214
|
+
if (!WORKFLOW_WIRE.workItemIdentity.includes("workItemId"))
|
|
215
|
+
throw new Error("workflow contract must pin the work-item identity mapping");
|
|
216
|
+
if (!WORKFLOW_WIRE.workItemFilter.includes("toSearchWorkItemsCriterion"))
|
|
217
|
+
throw new Error("workflow contract must pin the server-side work-item filter semantics");
|
|
218
|
+
if (!WORKFLOW_WIRE.bizObjectResolution.includes("getBizObjectByWfInstanceId"))
|
|
219
|
+
throw new Error("workflow contract must pin the work-item bizObject resolution");
|
|
220
|
+
if (!WORKFLOW_WIRE.mutuallyExclusiveBinding.includes("endEventHandler") || !WORKFLOW_WIRE.mutuallyExclusiveBinding.includes("cancelEventHandler"))
|
|
221
|
+
throw new Error("workflow contract must pin the mutually-exclusive end/cancel binding guidance");
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=workflow-contract.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { claim, declareLaneCoverage } from "./coverage-declaration.js";
|
|
2
|
+
import { WORKFLOW_LANE_CONTRACT } from "./workflow-contract.js";
|
|
3
|
+
const T = WORKFLOW_LANE_CONTRACT.tools;
|
|
4
|
+
export const WORKFLOW_COVERAGE = declareLaneCoverage(WORKFLOW_LANE_CONTRACT.lane, [
|
|
5
|
+
{
|
|
6
|
+
capability: "W7 S29 greenfield workflow authoring",
|
|
7
|
+
evidence: [
|
|
8
|
+
".scratch/omc-approval-workflow/acceptance/s29-probe-20260910012330184.md",
|
|
9
|
+
"packages/omc-cli/src/lanes/workflow.ts",
|
|
10
|
+
],
|
|
11
|
+
tools: [
|
|
12
|
+
claim("workflow.get_draft", T["workflow.get_draft"].scope),
|
|
13
|
+
claim("workflow.get_published", T["workflow.get_published"].scope),
|
|
14
|
+
claim("workflow.create", T["workflow.create"].scope),
|
|
15
|
+
claim("workflow.update", T["workflow.update"].scope),
|
|
16
|
+
claim("workflow.publish", T["workflow.publish"].scope),
|
|
17
|
+
claim("workflow.bindRule", T["workflow.bindRule"].scope),
|
|
18
|
+
claim("workflow.delete", T["workflow.delete"].scope),
|
|
19
|
+
claim("configure_workflow", T["configure_workflow"].scope),
|
|
20
|
+
claim("workflow.validate", T["workflow.validate"].scope),
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
capability: "W7 S29 runtime workflow work-item query (search_workitems)",
|
|
25
|
+
evidence: [
|
|
26
|
+
"packages/omc-cli/src/lanes/workflow.ts",
|
|
27
|
+
".scratch/omc-app-management/issues/06-workitem-list-capability.md",
|
|
28
|
+
],
|
|
29
|
+
tools: [claim("workitem.list", T["workitem.list"].scope)],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
capability: "workflow participant resolution (org roles/departments)",
|
|
33
|
+
evidence: [
|
|
34
|
+
".scratch/omc-context-cost-round4/evidence/real-env-observation.md",
|
|
35
|
+
"packages/omc-cli/src/lanes/workflow.ts",
|
|
36
|
+
],
|
|
37
|
+
tools: [claim("org.role.list", T["org.role.list"].scope), claim("org.department.list", T["org.department.list"].scope), claim("org.user.search", T["org.user.search"].scope)],
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
//# sourceMappingURL=workflow-coverage.js.map
|