@g1cloud/bpmn-modeler-next 5.0.0-alpha.5 → 5.0.0-alpha.8

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.
@@ -1,6 +1,6 @@
1
1
  import { BpmnDocumentModelerLike } from '../core/modelerLike';
2
2
  import { SymbolicOp } from './symbolicOp';
3
- import { ResolveIssue } from './resolver';
3
+ import { ApplyBpmnOpsResult, ResolveIssue } from './resolver';
4
4
  import { GeometryFinding } from './geometryAudit';
5
5
  /** op 출처 — 감사·정책 분기용. `gui` = 호스트 채팅 패널, `rest` = 외부 브리지. */
6
6
  export type BpmnOpOrigin = 'agent' | 'gui' | 'rest';
@@ -41,6 +41,8 @@ export type ApplyBatchOutcome =
41
41
  version: number;
42
42
  xml: string;
43
43
  findings: GeometryFinding[];
44
+ /** 간선 교차 계측(B-14 ⓐ) — 문서 전체, 하강 전/후. finding 이 아니다. */
45
+ stats: ApplyBpmnOpsResult['stats'];
44
46
  } | {
45
47
  status: 'conflict';
46
48
  baseVersion: number;
@@ -16,6 +16,19 @@ export interface GeometryShape {
16
16
  container: boolean;
17
17
  /** 경계 이벤트처럼 **호스트에 붙는 것이 정상**인 도형 — 겹침 판정에서 제외된다. */
18
18
  attached: boolean;
19
+ /**
20
+ * 이 도형을 **의미론적으로** 담는 컨테이너 id(참여자 또는 확장 서브프로세스) — 없으면 루트.
21
+ * 좌표가 아니라 모델에서 온다(DI 는 프로세스 소속을 말하지 않는다). `shape-outside-container`
22
+ * 판정의 근거: 노드가 자기 풀 밖에 그려져 있으면 좌표만 보는 사람은 **남의 풀 노드로 읽는다.**
23
+ */
24
+ parent?: string;
25
+ }
26
+ /** 간선 외부 라벨의 bounds — 라벨은 판정 대상 도형이 아니지만 **어느 간선의 것으로 읽히는가**는 판정한다(B-15). */
27
+ export interface GeometryLabel {
28
+ x: number;
29
+ y: number;
30
+ width: number;
31
+ height: number;
19
32
  }
20
33
  export interface GeometryEdge {
21
34
  id: string;
@@ -23,6 +36,8 @@ export interface GeometryEdge {
23
36
  waypoints: GeometryPoint[];
24
37
  /** 이 간선이 자기 끝점으로 삼는 도형 id 들 — 그 도형과의 교차는 도킹이라 관통이 아니다. */
25
38
  endpoints: readonly string[];
39
+ /** 이름이 있는 간선의 외부 라벨 bounds(있을 때만). `label-on-shared-segment` 의 입력. */
40
+ label?: GeometryLabel;
26
41
  }
27
42
  /** 판정기가 대면하는 최소 입력 — 좌표만 담는다(의미론 없음). */
28
43
  export interface GeometryScene {
@@ -47,9 +62,89 @@ export type GeometryFinding =
47
62
  kind: 'shape-overlap';
48
63
  shapes: [string, string];
49
64
  identical: boolean;
65
+ }
66
+ /**
67
+ * 도형이 자기 컨테이너(풀·확장 서브프로세스) 경계 밖으로 나가 있다. 원인은 컨테이너 크기가
68
+ * 내용물을 따라 늘지 않은 것(B-12 실측: 풀 높이가 band 수를 몰라 band 2 노드가 아래 풀 안에
69
+ * 놓였다). 작은 도형(이벤트)은 아무것과도 겹치지 않아 **관통·겹침 축은 침묵**하는데, 사람은
70
+ * 그 노드를 다른 풀의 것으로 읽는다 — 의미론이 조용히 뒤바뀌는 클래스라 따로 잡는다.
71
+ */
72
+ | {
73
+ kind: 'shape-outside-container';
74
+ shape: string;
75
+ container: string;
76
+ }
77
+ /**
78
+ * 두 간선의 축 정렬 구간이 **같은 선 위에 겹치는데 진행 방향이 반대**다 — 한 선처럼 보이는데
79
+ * 화살표가 양쪽 끝에 달려 어디서 어디로 가는지 읽을 수 없다(확정 6 네 번째 표본에서 사용자가
80
+ * 지목한 "문제가 되는 겹침" — 같은 방향으로 합류·팬아웃하는 겹침은 문제가 아니라 제외한다).
81
+ * 전형 = 되돌아가는 간선이 주 줄의 정방향 간선 위를 거꾸로 달리는 것, 같은 열을 반대로 오르내리는
82
+ * 메시지플로우 둘. `length` = 겹친 길이(px).
83
+ */
84
+ | {
85
+ kind: 'edge-overlap-opposite';
86
+ edges: [string, string];
87
+ axis: 'h' | 'v';
88
+ length: number;
89
+ }
90
+ /**
91
+ * 간선의 **라벨이 다른 간선과 공유하는 구간 위**에 놓여 어느 간선의 라벨인지 읽을 수 없다(확정 6
92
+ * 다섯 번째 표본에서 사용자가 지목: "겹치는 선상에 있는 분기 문구가 어느 선에 해당하는지 애매").
93
+ * 전형 = 게이트웨이 팬아웃의 3점 경로(세로 → 가로)는 첫 세로 구간을 갈래끼리 공선 공유하는데,
94
+ * bpmn-js 기본 라벨 위치(중간 구간 중점 = 3점이면 첫 구간)가 정확히 그 공유 구간이라 '승인'·
95
+ * '보완 요청' 이 한 선 위에 나란히 선다. 같은 방향 공선 중첩은 선으로서는 문제가 아니지만
96
+ * (`edge-overlap-opposite` 가 제외한 이유) **라벨 귀속** 축에서는 문제다. `other` = 그 구간을
97
+ * 함께 쓰는 간선(여럿이면 id 최소).
98
+ */
99
+ | {
100
+ kind: 'label-on-shared-segment';
101
+ edge: string;
102
+ other: string;
103
+ axis: 'h' | 'v';
50
104
  };
51
105
  /** 발견을 전후 비교(배치가 새로 만든 것 가려내기)할 수 있게 하는 안정 키. */
52
106
  export declare function geometryFindingKey(finding: GeometryFinding): string;
107
+ export interface AxisSegment {
108
+ axis: 'h' | 'v';
109
+ /** 고정 좌표(h 면 y, v 면 x). */
110
+ at: number;
111
+ lo: number;
112
+ hi: number;
113
+ /** 진행 방향 부호(+ = 오른쪽/아래). */
114
+ dir: 1 | -1;
115
+ }
116
+ /** 간선의 축 정렬 구간들(웨이포인트 순서). 사선 구간은 뺀다. */
117
+ export declare function axisSegmentsOf(edge: GeometryEdge): AxisSegment[];
118
+ /**
119
+ * 두 간선의 **반대 방향** 공선 중첩 — 가장 긴 겹침의 (축, 길이). 없으면 `null`.
120
+ * 같은 방향 겹침(합류·팬아웃)은 세지 않는다.
121
+ */
122
+ export declare function oppositeOverlapOf(a: GeometryEdge, b: GeometryEdge): {
123
+ axis: 'h' | 'v';
124
+ length: number;
125
+ } | null;
126
+ /** 한 간선(후보 경로)이 다른 간선들과 만드는 반대 방향 중첩 수. */
127
+ export declare function oppositeOverlapCount(edge: GeometryEdge, others: readonly GeometryEdge[]): number;
128
+ /** bpmn-js `LabelUtil.FLOW_LABEL_INDENT` — 라벨 중심이 선에서 떨어지는 거리(가로 구간은 위, 세로 구간은 오른쪽). */
129
+ export declare const FLOW_LABEL_INDENT = 15;
130
+ /**
131
+ * 갈림점 바로 옆에 붙은 라벨도 모호하다(다섯 번째 표본: 갈림 16px 아래의 '보완 요청' 을 사용자가 더
132
+ * 내렸다) — 공유 구간을 양쪽으로 이만큼 넓혀 본다. 배치(`planLabelPlacement`)도 같은 폭을 뺀다.
133
+ */
134
+ export declare const LABEL_FORK_MARGIN = 20;
135
+ /**
136
+ * `seg` 가 다른 간선의 구간과 공선 공유하는 부분들(≥ `OVERLAP_MIN_LENGTH`, 방향 무관) — 갈림 여백을
137
+ * 더해 돌려준다. 판정과 배치가 **같은 목록**을 써야 "옮겼는데 여전히 잡힌다"가 나지 않는다.
138
+ */
139
+ export declare function sharedSpansOf(seg: AxisSegment, otherSegments: readonly AxisSegment[]): Array<[number, number]>;
140
+ /**
141
+ * 이 간선의 라벨이 다른 간선과 **공선 공유하는 구간**(방향 무관, ≥ `OVERLAP_MIN_LENGTH`, 갈림 여백 포함)
142
+ * 위에 놓여 있으면 그 상대(id 최소)와 축을 돌려준다. 라벨이 없거나 고유 구간에 있으면 `null`.
143
+ */
144
+ export declare function sharedSegmentUnderLabel(edge: GeometryEdge, others: readonly GeometryEdge[]): {
145
+ other: string;
146
+ axis: 'h' | 'v';
147
+ } | null;
53
148
  /**
54
149
  * 이 간선이 관통하는 도형들(자기 끝점 제외). 판정과 **우회 보정**(routeRepair)이 같은
55
150
  * 술어를 써야 "고쳤다는데 판정은 그대로"가 나지 않는다.
@@ -57,6 +152,13 @@ export declare function geometryFindingKey(finding: GeometryFinding): string;
57
152
  * `targets` 는 컨테이너를 제외한 도형 목록 — 호출자가 한 번 걸러 넘긴다(반복 호출 비용).
58
153
  */
59
154
  export declare function crossedShapesOf(edge: GeometryEdge, targets: readonly GeometryShape[]): GeometryShape[];
155
+ /**
156
+ * 한 간선(또는 그 후보 경로)이 다른 간선들과 교차하는 수. **끝점을 공유하는 간선은 제외**한다 —
157
+ * 같은 노드에서 나가는 팬아웃·같은 노드로 드는 합류는 꺾이는 자리가 겹쳐 보여도 교차가 아니다.
158
+ */
159
+ export declare function edgeCrossCount(edge: GeometryEdge, others: readonly GeometryEdge[]): number;
160
+ /** 장면 전체의 교차 쌍(id 오름차순 정렬, 결정론적). 길이가 곧 교차 수다. */
161
+ export declare function edgeCrossingPairsOf(scene: GeometryScene): Array<[string, string]>;
60
162
  /** 컨테이너를 뺀 판정 대상 도형 — 관통·겹침 양쪽의 공통 모집단. */
61
163
  export declare const auditTargetsOf: (scene: GeometryScene) => GeometryShape[];
62
164
  /**
@@ -67,10 +169,6 @@ export declare const auditTargetsOf: (scene: GeometryScene) => GeometryShape[];
67
169
  * 에서 무시할 수준이고, 색인은 실제로 큰 문서가 관찰될 때 넣는다(조기 최적화 회피).
68
170
  */
69
171
  export declare function auditGeometry(scene: GeometryScene): GeometryFinding[];
70
- /**
71
- * moddle `definitions` → 장면. 입력은 `describeProcess` 와 같은 트리라 캔버스·헤드리스 양쪽
72
- * 에서 같은 것을 준다(A-6 입력 계약 동형).
73
- */
74
172
  export declare function sceneFromDefinitions(definitions: ModdleElement): GeometryScene;
75
173
  /** 저장 진실 기준 전수 판정 — 그 문서에 있는 **전부**(선재 결함 포함). */
76
174
  export declare function auditBpmnGeometry(definitions: ModdleElement): GeometryFinding[];
@@ -8,7 +8,7 @@ export type { DocumentIndex, ElementCategory } from './documentIndex';
8
8
  export { buildRegistryIndex } from './documentIndex';
9
9
  export { validateOps } from './validate';
10
10
  export { lowerOps, resolverServicesOf, type ResolverServices } from './lower';
11
- export { planEdgeRepair, planSegmentDetours, repairIntroducedCrossings } from './routeRepair';
11
+ export { planCrossPoolRoute, planEdgeRepair, planLabelPlacement, planMiddleSegmentShifts, planOppositeOverlapRepair, planSegmentDetours, repairIntroducedCrossings, repairIntroducedOppositeOverlaps, repairIntroducedSharedSegmentLabels, rerouteIntroducedCrossPoolEdges, } from './routeRepair';
12
12
  export interface ApplyBpmnOpsResult {
13
13
  ok: boolean;
14
14
  issues: ResolveIssue[];
@@ -21,5 +21,16 @@ export interface ApplyBpmnOpsResult {
21
21
  * 자기 배치 탓으로 읽고 무한 교정에 빠진다. 문서 전체 감사는 `auditBpmnGeometry`.
22
22
  */
23
23
  findings: GeometryFinding[];
24
+ /**
25
+ * 계측(B-14 ⓐ) — finding 이 아니다. 문서 **전체**의 간선 교차 수를 하강 전/후로 준다. 사람
26
+ * 마무리의 실체가 이 축이었다(확정 6 세 번째 표본: 교차 7 → 1)는 것이 드러난 뒤 도구가 그것을
27
+ * 볼 수 있게 한 채널. 배치가 교차를 얼마나 만들었는지 = `after - before`.
28
+ */
29
+ stats: {
30
+ edgeCrossings: {
31
+ before: number;
32
+ after: number;
33
+ };
34
+ };
24
35
  }
25
36
  export declare function applyBpmnOps(modeler: BpmnModelerLike, ops: readonly SymbolicOp[], lower?: typeof lowerOps): ApplyBpmnOpsResult;
@@ -1,4 +1,4 @@
1
- import { GeometryEdge, GeometryPoint, GeometryShape } from '../geometryAudit';
1
+ import { GeometryEdge, GeometryLabel, GeometryPoint, GeometryScene, GeometryShape } from '../geometryAudit';
2
2
  import { ResolverServices } from './lower';
3
3
  /**
4
4
  * 축 정렬 구간이 장애물을 **완전히 가로지를 때** 그것을 우회하는 4점을 만든다(순수).
@@ -11,6 +11,18 @@ import { ResolverServices } from './lower';
11
11
  * - 장애물이 구간 끝에 걸쳐 있음 — 끝점 도킹과 얽혀 잘못 건드리면 연결이 떨어져 보인다
12
12
  */
13
13
  export declare function planSegmentDetours(a: GeometryPoint, b: GeometryPoint, rect: GeometryShape, margin?: number): [GeometryPoint[], GeometryPoint[]] | null;
14
+ /**
15
+ * 꺾임점이 장애물 **안**에 있는 형상 — 구간 우회로는 못 푼다(B-13 ②, 두 번째 표본 잔존 1건).
16
+ *
17
+ * bpmn-js 의 직각 경로는 대개 h-v-h(또는 v-h-v) 3구간이고, **중간 구간의 좌표**는 양 끝점의
18
+ * 중점이다. 그 중점이 어떤 도형의 폭 안에 떨어지면 세로 구간이 그 도형을 관통하고 꺾임점도
19
+ * 그 안에 있어 `planSegmentDetours` 가 거부한다(실측: 되돌아가는 간선의 중간 x 가 게이트웨이
20
+ * 폭 안). 해법은 우회가 아니라 **중간 구간을 장애물 옆으로 옮기는 것** — 점 수는 그대로 4 다.
21
+ * 두 후보(장애물 왼쪽/오른쪽 또는 위/아래)를 돌려주고 채택은 호출자가 판정기로 한다.
22
+ *
23
+ * `null` = 4점 직각 경로가 아니다.
24
+ */
25
+ export declare function planMiddleSegmentShifts(waypoints: readonly GeometryPoint[], rect: GeometryShape, margin?: number): [GeometryPoint[], GeometryPoint[]] | null;
14
26
  /**
15
27
  * 한 간선의 관통을 없애는 웨이포인트를 찾는다(순수). 못 찾으면 `null`.
16
28
  *
@@ -32,3 +44,33 @@ export declare function planEdgeRepair(edge: GeometryEdge, targets: readonly Geo
32
44
  * "고쳤는데 여전히 깨져 있다"가 되어 보고와 실물이 어긋난다.
33
45
  */
34
46
  export declare function repairIntroducedCrossings(services: Pick<ResolverServices, 'elementRegistry' | 'modeling'>, beforeKeys: ReadonlySet<string>): void;
47
+ /**
48
+ * 풀 횡단 메시지플로우의 6점 경로 계획(순수). `null` = 이 간선은 대상이 아니거나(중간 풀 없음 ·
49
+ * 끝점 해소 불가) 더 나은 열이 없다.
50
+ */
51
+ export declare function planCrossPoolRoute(edge: GeometryEdge, scene: GeometryScene): GeometryPoint[] | null;
52
+ /**
53
+ * 이 배치가 **새로 만든** 메시지플로우 중 풀을 횡단하는 것을 재경로한다(하강 직후, undo 에피소드
54
+ * 안). `beforeEdgeIds` = 하강 전 간선 id — 그 밖의 것만 대상(안전 성질 2: 선재 경로 불가침).
55
+ */
56
+ export declare function rerouteIntroducedCrossPoolEdges(services: Pick<ResolverServices, 'elementRegistry' | 'modeling'>, beforeEdgeIds: ReadonlySet<string>): void;
57
+ /** 한 간선의 반대 방향 중첩을 없애거나 줄이는 경로(순수). 못 찾으면 `null`. */
58
+ export declare function planOppositeOverlapRepair(edge: GeometryEdge, scene: GeometryScene): GeometryPoint[] | null;
59
+ /**
60
+ * 이 배치가 **새로 만든** 반대 방향 중첩을 고친다(하강 직후, undo 에피소드 안). 짝 중 새 간선만
61
+ * 손댄다(안전 성질 2) — 둘 다 새 것이면 되돌아가는 간선(A 후보가 있는 쪽)부터.
62
+ */
63
+ export declare function repairIntroducedOppositeOverlaps(services: Pick<ResolverServices, 'elementRegistry' | 'modeling'>, beforeKeys: ReadonlySet<string>, beforeEdgeIds: ReadonlySet<string>): void;
64
+ /**
65
+ * 라벨의 새 bounds(순수). 라벨이 공유 구간 위에 없으면 `null`(옮길 이유가 없다). 고유 구간을 못
66
+ * 찾거나 옮긴 자리가 도형과 겹치면 `null`(손대지 않고 보고에 맡긴다).
67
+ *
68
+ * 구간마다 다른 간선과 공선 공유하는 부분(≥ 20px)을 빼고 남은 **첫 자유 부분** 중 라벨이 들어가는
69
+ * 곳을 고른다 — 부분 공유 구간(갈림점 아래로 이어지는 세로 구간)도 그 아래쪽이 자유 부분이다.
70
+ */
71
+ export declare function planLabelPlacement(edge: GeometryEdge, scene: GeometryScene): GeometryLabel | null;
72
+ /**
73
+ * 이 배치가 **새로 만든** 간선의 라벨 귀속 문제를 고친다(하강 직후, undo 에피소드 안, 경로 보정들 뒤).
74
+ * 선재 간선의 라벨은 사람이 놓았을 수 있어 손대지 않는다(안전 성질 2).
75
+ */
76
+ export declare function repairIntroducedSharedSegmentLabels(services: Pick<ResolverServices, 'elementRegistry' | 'modeling'>, beforeKeys: ReadonlySet<string>, beforeEdgeIds: ReadonlySet<string>): void;