@g1cloud/bpmn-modeler-next 5.0.0-beta.2 → 5.0.0-beta.21

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,9 +1,41 @@
1
+ export declare const I18N_NS = "http://www.omg.org/spec/BPMN/non-normative/extensions/i18n/1.0";
2
+ export declare const I18N_PREFIX = "i18n";
3
+ /** 번역 칸 moddle 타입. */
4
+ export declare const I18N_TRANSLATION_TYPE = "i18n:Translation";
5
+ type Any = any;
6
+ /**
7
+ * 라벨 문구가 실제로 사는 (객체, 키) — bpmn-js `LabelUtil.getLabelAttr` 와 같은 판정.
8
+ * 주석은 `text`, 그룹은 `categoryValueRef.value`, 나머지는 `name`.
9
+ */
10
+ export declare function labelSlot(bo: Any): {
11
+ target: Any;
12
+ key: string;
13
+ } | undefined;
14
+ /** 요소의 번역 칸 전부(`extensionElements` 안의 `i18n:Translation`). */
15
+ export declare function translationsOf(bo: Any): Any[];
16
+ /** 번역 칸의 로케일. */
17
+ export declare function translationLocale(t: Any): string | undefined;
18
+ /** 요소의 확인 요청 표식 전부(`bwl:ReviewRequest` — 상태 표식 · C-1). */
19
+ export declare function reviewRequestsOf(bo: Any): Any[];
1
20
  /**
2
- * 레거시 bpmn-i18n-moddle 호환 (백로그 B-4).
21
+ * 문서 언어 설정(B-4) — 설계 언어(고객에게 전달하는 설계 문서의 언어 · `name` 이 따른다) + 병기 언어(함께 최신으로
22
+ * 유지할 언어들). 호스트 그룹 설정(`designLocale` · `companionLocales`)과 같은 이름이라 그대로 넘긴다.
23
+ * 미설정(`undefined`) = 기능 끔.
24
+ */
25
+ export interface BpmnDocumentLocales {
26
+ designLocale: string;
27
+ companionLocales: string[];
28
+ }
29
+ /** 문서 언어 목록 — 설계 언어가 맨 앞 · 병기 언어에서 설계 언어와 중복은 뺀다. */
30
+ export declare function documentLocalesOf(config: BpmnDocumentLocales): string[];
31
+ /** 루트 `<bpmn:definitions xml:lang>` — 번역 칸으로 판정되지 않는 `name` 의 언어. */
32
+ export declare function rootLangOf(definitions: Any): string | undefined;
33
+ /**
34
+ * 요소 라벨의 문서 언어별 문구(B-4 ④) — 표시 판정(`view/i18nDisplay` `resolve`)과 **같은 규칙**이다:
35
+ * `name` 의 언어가 그 언어면 `name` → 아니면 그 언어의 번역 칸(`xml:lang` 있는 칸 · 문구 있음) → 없으면 빠진다
36
+ * (= 미번역). `name` 의 언어 = 같은 문구의 번역 칸 로케일 → 없으면 루트 `xml:lang` → 설계 언어.
3
37
  *
4
- * 스키마 자체는 유지한다 — 기존 운영 문서(실측 112곳 확장)와의 호환 필수.
5
- * 재설계 대상은 스키마가 아니라 적용 방식: 레거시 bpmnTranslationService 의
6
- * commandStack 우회 변조를 표시용/저장용 라벨 분리로 대체한다.
38
+ * 에이전트 대면 read(`describeProcess` 의 `names`/`texts`)와 에이전트 쓰기의 「바뀌었나」 판정이 같이 쓴다.
7
39
  */
8
- export declare const I18N_NS = "http://www.omg.org/spec/BPMN/non-normative/extensions/i18n/1.0";
9
- export declare const I18N_PREFIX = "i18n";
40
+ export declare function localeTextsOf(bo: Any, config: BpmnDocumentLocales, rootLang?: string): Record<string, string>;
41
+ export {};
@@ -0,0 +1,64 @@
1
+ type Any = any;
2
+ /** 문자 체계 — 판정에 쓰는 것은 한글 · 가나뿐이다. */
3
+ export type ScriptKind = 'hangul' | 'kana' | 'mixed' | 'han' | 'other';
4
+ export interface ScriptInference {
5
+ script: ScriptKind;
6
+ /** 문자 체계로 정해지는 언어 — 한글 = ko · 가나 = ja · 그 밖 = 없음. */
7
+ locale?: 'ko' | 'ja';
8
+ }
9
+ /** 문구의 문자 체계 판정. 한글과 가나가 함께 있으면 `mixed`(판정 불가). */
10
+ export declare function inferScriptLocale(text: string): ScriptInference;
11
+ /**
12
+ * 루트 판정의 근거.
13
+ * `kept` 이미 있다 · `matched` 번역 칸과 같은 이름들의 공통 언어 · `script` 문자 체계가 한 언어로 모인다 ·
14
+ * `ambiguous` 공통 언어가 여럿이고 문자 체계로도 못 고른다 · `mixed` 근거가 서로 다른 언어 · `no-evidence` 근거 없음
15
+ */
16
+ export type RootLocaleReason = 'kept' | 'matched' | 'script' | 'ambiguous' | 'mixed' | 'no-evidence';
17
+ /** 계획 항목이 가리키는 요소 — 미리보기 화면이 사람에게 보여 줄 최소 정보. */
18
+ export interface LocaleBackfillElement {
19
+ id: string;
20
+ /** moddle 타입(`bpmn:Task` 등). */
21
+ type: string;
22
+ /** 계획 시점의 라벨 문구. 적용은 이 문구가 그대로일 때만 쓴다. */
23
+ name: string;
24
+ }
25
+ export interface LocaleBackfillPlan {
26
+ root: {
27
+ /** 지금 루트 `xml:lang`. */
28
+ current?: string;
29
+ /** 새로 쓸 값 — `current` 가 있거나 판정 불가면 없다. */
30
+ proposed?: string;
31
+ reason: RootLocaleReason;
32
+ };
33
+ /** 더할 번역 칸(본문 = 그 요소의 `name`). */
34
+ additions: Array<LocaleBackfillElement & {
35
+ locale: string;
36
+ }>;
37
+ /** 언어 기록이 없고 문자 체계로도 못 가르는 이름 — 루트를 따른다 · 사람 확인 대상. */
38
+ undecided: Array<LocaleBackfillElement & {
39
+ script: ScriptKind;
40
+ }>;
41
+ /** 이름이 언어 있는 칸 어느 것과도 다르다(칸은 있다) — 백필 대상 아님(별도 정리). */
42
+ drift: LocaleBackfillElement[];
43
+ /**
44
+ * 이름이 언어 있는 칸과 같은 요소의 분포 — 키 = 일치한 로케일(정렬 · `+` 연결, 예 `ja` · `ja+ko`).
45
+ * 루트 판정의 근거이고, 판정 불가 문서에서 사람이 루트를 고를 근거다.
46
+ */
47
+ matchedBy: Record<string, number>;
48
+ /**
49
+ * 칸 언어 ↔ 문자 체계 불일치(레거시 복사본 번역 흔적 · F8) — **기록 대상 아님**(별도 정리).
50
+ * `script` = `kana` · `hangul` 은 그 칸 언어가 아닌 문자 · `han` 은 ko 칸이 한자만이고 다른 칸과 같은 문구(참고값 · 사람 판단).
51
+ */
52
+ scriptMismatch: Array<LocaleBackfillElement & {
53
+ locale: string;
54
+ script: ScriptKind;
55
+ }>;
56
+ }
57
+ /** 언어 백필 계획 — 문서를 바꾸지 않는다. */
58
+ export declare function planLocaleBackfill(definitions: Any): LocaleBackfillPlan;
59
+ /**
60
+ * 계획을 문서에 쓴다 — 바꾼 곳 수를 돌려준다. **멱등**이고 계획 뒤 문서가 바뀌었어도 덮지 않는다:
61
+ * 루트가 이미 있으면 루트를 건너뛰고, 요소는 지금도 「언어 기록 없음 + 이름이 계획 때 그대로」일 때만 쓴다.
62
+ */
63
+ export declare function applyLocaleBackfill(definitions: Any, plan: LocaleBackfillPlan): number;
64
+ export {};
@@ -2,6 +2,7 @@ import { BpmnDocumentModelerLike } from '../core/modelerLike';
2
2
  import { SymbolicOp } from './symbolicOp';
3
3
  import { ApplyBpmnOpsResult, ResolveIssue } from './resolver';
4
4
  import { GeometryFinding } from './geometryAudit';
5
+ import { BpmnDocumentLocales } from '../adapter/i18n';
5
6
  /** op 출처 — 감사·정책 분기용. `gui` = 호스트 채팅 패널, `rest` = 외부 브리지. */
6
7
  export type BpmnOpOrigin = 'agent' | 'gui' | 'rest';
7
8
  export interface BpmnOpBatch {
@@ -54,6 +55,11 @@ export type ApplyBatchOutcome =
54
55
  export interface ApplyBpmnOpBatchOptions {
55
56
  /** 적용 시점의 권위 버전 — 호스트(영속 소유자)가 공급한다. */
56
57
  currentVersion: number;
58
+ /**
59
+ * 그 문서가 속한 그룹의 문서 언어 설정(B-4 ④) — 호스트가 공급한다(문서에 없다). 있으면 문구는 `names`/`texts`
60
+ * 로 문서 언어 전부를 받고, 없으면 평문만 받는다(`applyBpmnOps` 의 같은 옵션).
61
+ */
62
+ i18n?: BpmnDocumentLocales;
57
63
  }
58
64
  /**
59
65
  * 배치를 캔버스에 적용하고 영속 페이로드를 낸다.
@@ -64,4 +70,4 @@ export interface ApplyBpmnOpBatchOptions {
64
70
  * 적용은 단일 undo 에피소드다(`applyBpmnOps` → `command/undoEpisode`) — 배치 수십 op 가
65
71
  * 사용자 undo 1회로 되감긴다.
66
72
  */
67
- export declare function applyBpmnOpBatch(modeler: BpmnDocumentModelerLike, batch: BpmnOpBatch, { currentVersion }: ApplyBpmnOpBatchOptions): Promise<ApplyBatchOutcome>;
73
+ export declare function applyBpmnOpBatch(modeler: BpmnDocumentModelerLike, batch: BpmnOpBatch, { currentVersion, i18n }: ApplyBpmnOpBatchOptions): Promise<ApplyBatchOutcome>;
@@ -1,4 +1,6 @@
1
1
  import { ModdleElement, ParseWarning } from '../adapter/xml';
2
+ import { BpmnDocumentLocales } from '../adapter/i18n';
3
+ import { ReviewRequestValue } from '../command/setTranslations';
2
4
  import { BwlAfterColumn, BwlBand, BwlPlacement, BwlPoolOrder } from '../core/hints';
3
5
  import { IrDefinition } from '../core/ir';
4
6
  /** 파생 뷰가 표현하지 못한 요소 — 침묵 폐기 금지(에이전트가 미표현 존재를 알아야 안전). */
@@ -41,15 +43,40 @@ export interface BwlHintView {
41
43
  /** 주석 id → 앵커 기준 방위 (앵커 부재분은 필터됨) */
42
44
  placements: Record<string, BwlPlacement>;
43
45
  }
46
+ /** 확인 요청 표식 한 건(B-4 ④) — `id` 요소의 `locale` 칸에 걸렸다. `sourceLocale` 이 `previous` → 지금 문구로 고쳐졌다. */
47
+ export interface ReviewRequestView extends ReviewRequestValue {
48
+ id: string;
49
+ }
50
+ /**
51
+ * 다국어 판독 결과(B-4 ④) — 문서 언어 설정이 있을 때만 낸다. IR 밖 채널(위 헤더 「다국어」).
52
+ * 에이전트는 이 값이 있으면 문구를 `names`/`texts` 로 문서 언어 전부를 써야 한다.
53
+ */
54
+ export interface I18nView {
55
+ designLocale: string;
56
+ /** 병기 언어(설계 언어 제외 · 중복 제거). */
57
+ companionLocales: string[];
58
+ /**
59
+ * 정리할 확인 요청 — 문서 언어 칸에 걸린 것만. `previous`(고치기 전 원문) → 지금 `names[sourceLocale]` 를 대조해
60
+ * 오타 수준이면 `translation.confirm`, 내용이 바뀌었으면 그 요소 update 에 `names` 로 번역을 고친다.
61
+ */
62
+ reviewRequests: ReviewRequestView[];
63
+ }
44
64
  export interface DescribeProcessResult {
45
65
  definition: IrDefinition;
46
66
  hints: BwlHintView;
47
67
  omitted: IrOmission[];
68
+ /** 문서 언어 설정이 있을 때만 있다(B-4 ④). */
69
+ i18n?: I18nView;
70
+ }
71
+ /** 판독 옵션 — 문서 밖에서만 알 수 있는 입력. */
72
+ export interface DescribeProcessOptions {
73
+ /** 그룹의 문서 언어 설정(B-4 ④) — 문서에 없어 호스트가 공급한다. 없으면 다국어 판독을 하지 않는다. */
74
+ i18n?: BpmnDocumentLocales;
48
75
  }
49
76
  export interface DescribeProcessXmlResult extends DescribeProcessResult {
50
77
  /** 입력 XML 파싱 경고 — 실운영 문서는 빈 배열이어야 한다(M1 수용 기준 1). */
51
78
  warnings: ParseWarning[];
52
79
  }
53
- export declare function describeProcess(definitions: ModdleElement): DescribeProcessResult;
80
+ export declare function describeProcess(definitions: ModdleElement, options?: DescribeProcessOptions): DescribeProcessResult;
54
81
  /** XML 문자열 입력 래퍼 — 헤드리스 read 경로(호스트 `describeProcess` API·테스트). */
55
- export declare function describeProcessXml(xml: string): Promise<DescribeProcessXmlResult>;
82
+ export declare function describeProcessXml(xml: string, options?: DescribeProcessOptions): Promise<DescribeProcessXmlResult>;
@@ -613,6 +613,8 @@ export declare function segmentShapeClearance(a: GeometryPoint, b: GeometryPoint
613
613
  /**
614
614
  * 한 간선(또는 그 후보 경로)이 다른 간선들과 교차하는 수. **끝점을 공유하는 간선은 제외**한다 —
615
615
  * 같은 노드에서 나가는 팬아웃·같은 노드로 드는 합류는 꺾이는 자리가 겹쳐 보여도 교차가 아니다.
616
+ * ⚠ `segmentsCross` 가 이미 접촉을 안 세므로 이 제외가 실제로 막는 것은 **내부 진성 교차**뿐이다(B-146) —
617
+ * 그쪽은 `sharedEndpointCrossingPairsOf` 가 따로 센다. 이 제외를 풀지 말 것: 위에 라우팅 채택 게이트가 선다.
616
618
  */
617
619
  export declare function edgeCrossCount(edge: GeometryEdge, others: readonly GeometryEdge[]): number;
618
620
  /**
@@ -625,6 +627,18 @@ export declare function crossingCost(edge: GeometryEdge, others: readonly Geomet
625
627
  export declare function sceneCrossingCost(scene: GeometryScene): number;
626
628
  /** 장면 전체의 교차 쌍(id 오름차순 정렬, 결정론적). 길이가 곧 교차 수다. */
627
629
  export declare function edgeCrossingPairsOf(scene: GeometryScene): Array<[string, string]>;
630
+ /**
631
+ * **끝점을 공유하는** 쌍의 진성 교차(B-146 ⓐ′ · 관측 전용) — `edgeCrossingPairsOf` 가 통째로 빼는 쌍 중
632
+ * 간선 **내부**에서 가로지르는 것. 둘을 합치면 장면의 진성 교차 전량이고 겹치는 쌍은 없다.
633
+ *
634
+ * 표본 98 에서 사람이 고친 교차가 이것이었다 — 게이트웨이 → 오류 노드 갈래와 오류 노드 → 상류 되돌아감이
635
+ * 오류 노드를 함께 끝점으로 가져 판정·계수가 모두 침묵했다(사람은 두 간선의 출입 변을 맞바꿨다).
636
+ * 🔴 **라우팅·채택 게이트의 입력이 아니다** — `edgeCrossCount` 의 제외를 바꾸면 그 위의 우회 채택·교차 보정과
637
+ * `--check` 기대값이 함께 움직인다. 이 함수는 보이게만 한다.
638
+ * ⚠ 「공유」는 각 어댑터의 `endpoints` 를 따른다 — 데이터 연관은 두 어댑터가 다르게 담는다(저장본 = 저장소만 ·
639
+ * 캔버스 = 활동 + 저장소).
640
+ */
641
+ export declare function sharedEndpointCrossingPairsOf(scene: GeometryScene): Array<[string, string]>;
628
642
  /**
629
643
  * 교차 쌍을 **에이전트가 판단할 수 있는 재료로 분해**한다(B-43). 개수만으로는 "이 정도가 정상인가" 를
630
644
  * 가릴 수 없고, 지금까지 세 회차에서 같은 마찰이 났다(표본 34·36 은 재료 없이도 결론이 맞았으나
@@ -26,6 +26,11 @@ export interface DocumentIndex {
26
26
  * 어휘 밖 정의면 undefined.
27
27
  */
28
28
  eventDefinitionOf(nodeId: string): IrEventDefinition | undefined;
29
+ /**
30
+ * 요소에 확인 요청 표식(`bwl:reviewRequest`)이 걸린 언어들 (B-4 ④) — `translation.confirm` 이 없는 표식을
31
+ * 지목하면 거부한다(읽은 뒤 사람이 이미 정리했을 수 있다). 없으면 빈 배열.
32
+ */
33
+ reviewRequestLocalesOf(id: string): readonly string[];
29
34
  }
30
35
  /** elementRegistry 어댑터 — 하강 직전 실문서 상태를 대변한다. */
31
36
  export declare function buildRegistryIndex(registry: ElementRegistry): DocumentIndex;
@@ -2,11 +2,12 @@ import { BpmnModelerLike } from '../../core/modelerLike';
2
2
  import { SymbolicOp } from '../symbolicOp';
3
3
  import { ResolveIssue } from './issues';
4
4
  import { GeometryFinding } from '../geometryAudit';
5
+ import { BpmnDocumentLocales } from '../../adapter/i18n';
5
6
  import { lowerOps } from './lower';
6
7
  export type { ResolveIssue } from './issues';
7
8
  export type { DocumentIndex, ElementCategory } from './documentIndex';
8
9
  export { buildRegistryIndex } from './documentIndex';
9
- export { validateOps } from './validate';
10
+ export { validateOps, type ValidateOpsOptions } from './validate';
10
11
  export { lowerOps, resolverServicesOf, type ResolverServices } from './lower';
11
12
  export { forwardThreePointCandidates, planCrossPoolRoute, planEdgeRepair, planLabelLineClearance, planLabelPlacement, planMiddleSegmentShifts, planOppositeOverlapRepair, planSegmentDetours, planBackEdgeBoundaryClearance, repairIntroducedBoundaryHugging, repairIntroducedCrossings, repairIntroducedEdgeCrossings, repairIntroducedFakeMerges, repairIntroducedOppositeOverlaps, repairIntroducedSharedSegmentLabels, followMovedEdgeLabels, redockIntroducedDetachedEndpoints, repairIntroducedLabelLines, repairIntroducedShapeLabelLines, planShapeLabelClearance, rerouteIntroducedCrossPoolEdges, } from './routeRepair';
12
13
  export interface ApplyBpmnOpsResult {
@@ -57,6 +58,28 @@ export interface ApplyBpmnOpsResult {
57
58
  */
58
59
  crossPoolMessages: number;
59
60
  };
61
+ /**
62
+ * **끝점을 공유하는** 간선끼리의 내부 진성 교차(B-146 ⓐ′) — 위 `edgeCrossings` 가 세지 않는 쌍이다(둘을 합치면
63
+ * 진성 교차 전량 · 겹치는 쌍 없음). 표본 98 에서 사람이 고친 교차가 이것이었다(게이트웨이 → 오류 노드 갈래 ×
64
+ * 오류 노드 → 상류 되돌아감). **관측 전용** — 보정 단계의 채택 게이트는 이 값을 보지 않는다.
65
+ */
66
+ sharedEndpointCrossings: {
67
+ before: number;
68
+ after: number;
69
+ /** 하강 뒤 남은 쌍(간선 id, 오름차순). */
70
+ pairs: Array<[string, string]>;
71
+ };
60
72
  };
61
73
  }
62
- export declare function applyBpmnOps(modeler: BpmnModelerLike, ops: readonly SymbolicOp[], lower?: typeof lowerOps): ApplyBpmnOpsResult;
74
+ /** 배치 적용 옵션 — 문서 밖에서만 알 수 있는 입력. */
75
+ export interface ApplyBpmnOpsOptions {
76
+ /**
77
+ * 그룹의 문서 언어 설정(B-4 ④). 있으면 다국어 그룹이다 — 문구는 `names`/`texts` 로 문서 언어 전부를 받고
78
+ * (평문 거부) 하강 뒤 번역 칸을 같은 undo 에피소드에서 기록한다. 없으면 기능이 꺼진 그룹이다(평문만).
79
+ * 🔴 **문서에는 이 설정이 없다**(루트 `xml:lang` 은 만들 당시의 설계 언어일 뿐이다) — 호스트가 그룹 설정을 공급한다.
80
+ */
81
+ i18n?: BpmnDocumentLocales;
82
+ /** 테스트 시임 — 롤백 경로를 결정론적으로 검증하기 위한 하강 함수 주입점. 실사용은 기본값. */
83
+ lower?: typeof lowerOps;
84
+ }
85
+ export declare function applyBpmnOps(modeler: BpmnModelerLike, ops: readonly SymbolicOp[], options?: ApplyBpmnOpsOptions): ApplyBpmnOpsResult;
@@ -167,6 +167,59 @@ export type ResolveIssue =
167
167
  type: string;
168
168
  dropped: string[];
169
169
  }
170
+ /** 평문(`name`/`text`)과 로케일 맵(`names`/`texts`)을 함께 줬다 — 어느 쪽이 진실인지 모호하다(🔁 `condition-name-conflict`). */
171
+ | {
172
+ kind: 'locale-texts-conflict';
173
+ opIndex: number;
174
+ id: string;
175
+ field: string;
176
+ }
177
+ /**
178
+ * 다국어 그룹(문서 언어 설정 있음)에 평문을 줬다 — 언어를 모르는 문구는 설계 언어 칸에 다른 언어가 들어가는 경로다
179
+ * (켠 뒤의 에이전트 배치가 언어 기록 없는 이름 · drift 를 만드는 근인). `names`/`texts` 로 문서 언어 전부를 준다.
180
+ * 🔴 **조건 라벨(`condition`)도 여기다** — name 채널의 별칭(A-5)이라 다국어 그룹에선 그 플로우의 `names` 로 쓴다.
181
+ */
182
+ | {
183
+ kind: 'locale-texts-required';
184
+ opIndex: number;
185
+ id: string;
186
+ field: string;
187
+ locales: string[];
188
+ }
189
+ /** 기능이 꺼진 그룹(문서 언어 미설정)에 로케일 맵이나 `translation.confirm` 을 줬다 — 평문을 쓴다. */
190
+ | {
191
+ kind: 'locale-texts-not-enabled';
192
+ opIndex: number;
193
+ id: string;
194
+ field: string;
195
+ }
196
+ /** 로케일 맵에 문서 언어가 빠졌다 — 에이전트 쓰기는 문서 언어 **전부**를 함께 쓴다(그래야 표식이 안 생긴다). */
197
+ | {
198
+ kind: 'locale-texts-incomplete';
199
+ opIndex: number;
200
+ id: string;
201
+ field: string;
202
+ missing: string[];
203
+ }
204
+ /** 문서 언어(설계 + 병기) 밖의 언어 — 표시도 판정도 안 하는 칸이라 아무도 못 보고 못 고친다. */
205
+ | {
206
+ kind: 'locale-not-in-document';
207
+ opIndex: number;
208
+ id: string;
209
+ field: string;
210
+ locale: string;
211
+ locales: string[];
212
+ }
213
+ /**
214
+ * `translation.confirm` 의 대상 칸에 확인 요청 표식이 없다 — 읽은 뒤 사람이 이미 정리했거나 언어를 잘못 짚었다.
215
+ * 다시 읽어 `i18n.reviewRequests` 를 본다.
216
+ */
217
+ | {
218
+ kind: 'review-request-missing';
219
+ opIndex: number;
220
+ id: string;
221
+ locale: string;
222
+ }
170
223
  /** 하강 실행 중 실패 — 실행분은 롤백됨(원자성 2차 방어) */
171
224
  | {
172
225
  kind: 'lower-failed';
@@ -0,0 +1,24 @@
1
+ import { BpmnDocumentLocales } from '../../adapter/i18n';
2
+ import { SymbolicOp } from '../symbolicOp';
3
+ import { DocumentIndex } from './documentIndex';
4
+ import { ResolveIssue } from './issues';
5
+ /** 하강 뒤 한 요소에 할 번역 쓰기 — 같은 요소를 여러 op 가 건드리면 합친다. */
6
+ export interface LocaleWrite {
7
+ /** 문서 언어 전부의 문구. `null` = 라벨 제거(칸 · 표식 전부). 없으면 문구를 쓰지 않는다. */
8
+ texts?: Record<string, string> | null;
9
+ /** 문구를 바꾸지 않고 해소할 확인 요청의 언어들(`translation.confirm`). */
10
+ confirm?: string[];
11
+ }
12
+ /**
13
+ * 다국어 검증(순수). `config` = 그룹의 문서 언어 설정 — 없으면 기능이 꺼진 그룹이다.
14
+ * 페이로드 shape(맵이 객체인가 · 값이 비지 않은 문자열인가)도 여기서 본다 — 패스 0 은 kind 별 고정 자리만 안다.
15
+ */
16
+ export declare function validateLocaleTexts(ops: readonly SymbolicOp[], index: DocumentIndex, config: BpmnDocumentLocales | undefined): ResolveIssue[];
17
+ /**
18
+ * 하강 준비 — 검증 통과가 전제다. 반환 `ops` 는 평문만 남은 사본(설계 언어 문구 · `translation.confirm` 제외)이고,
19
+ * `writes` 는 하강 뒤 요소별로 할 번역 쓰기다. `config` 가 없으면(기능 끔) 입력을 그대로 돌려준다.
20
+ */
21
+ export declare function localizeOps(ops: readonly SymbolicOp[], index: DocumentIndex, config: BpmnDocumentLocales | undefined): {
22
+ ops: SymbolicOp[];
23
+ writes: Map<string, LocaleWrite>;
24
+ };
@@ -39,6 +39,14 @@ export declare function resolverServicesOf(modeler: BpmnModelerLike): ResolverSe
39
39
  * B-33 → B-34 ⓐ 가 그룹 경계 보정에서 닫은 것과 같은 클래스다.
40
40
  *
41
41
  * `selfId` = 이미 존재하는 주석(update)의 자기 도형·자기 연관을 장애물에서 뺀다 — 안 빼면 늘 "막힘"이다.
42
+ *
43
+ * **B-144** — 앵커가 레인 안이면 클램프 상자와 대안 방위의 `inside` 를 **앵커 레인 대역**으로 좁힌다(풀 클램프와
44
+ * 같은 규칙 — 레인 경계에서 클램프하고 앵커와 겹치면 오른쪽으로 비낀다). 🔴 **레인 안에 막히지 않은 자리가 없으면
45
+ * 종전대로 풀 안 빈 자리(이웃 레인일 수 있다)로 간다** — 레인 소속을 막힌 자리(겹침·관통)와 바꾸지 않는다
46
+ * (반사실: 레인 안 막힌 자리로 두는 안은 findings 가 는 케이스가 두 배였다 · 66 vs 33 / 방위 합성 6,208).
47
+ * 그것도 없으면 레인 안 선언 자리(막힘 — 판정기가 보고한다). ⚠ 잔존 대가 = 그 폴백의 이웃 레인 착지(방위 합성
48
+ * 0.6% — 사람 기저 0.4~1.0% 수준) · 레인 클램프가 오른쪽 비끼기를 더 자주 발동시켜 **가로로 풀 밖** 착지가
49
+ * 12 → 16(그 분기가 풀 우변을 넘는 것은 이 축 이전부터다 — 원장 B-144 곁).
42
50
  */
43
51
  export declare function annotationSpot(elementRegistry: ElementRegistry, anchor: {
44
52
  x: number;
@@ -54,6 +54,11 @@ export declare function forwardThreePointCandidates(edge: GeometryEdge, shapes:
54
54
  * 목표 열은 목표 중심에 도킹 편이 0/±25/±40 — 그 열에 다른 메시지가 이미 중심 도킹해 있으면(같은 방향·같은
55
55
  * 종류라 finding 은 아니지만 두 화살표가 한 선으로 합쳐 보인다 — 사용자도 -19 비껴 놓았다) 편이 후보가 피한다.
56
56
  * 채택은 호출자 몫: 관통 0 을 먼저, 그다음 다른 간선과의 공선 공유가 없는 후보를 고른다.
57
+ *
58
+ * 🔴 B-141. 목표 도킹 열이 **출발 도형 폭 안**이면(같은 열 메시지) 후보를 내지 않는다 — 되돌아오는 세로 구간이
59
+ * 출발 도형을 관통하고, 도킹 편이(최대 ±40)로는 반폭을 못 벗어난다. 그 관통은 호출자의 관통 셈과 판정이 둘 다
60
+ * **자기 끝점을 빼서** 보이지 않아 그대로 채택됐다(표본 93 갈고리 · 계보 102 재하강 = 8회차 10간선 · 전부 이 후보 ·
61
+ * 사람 문서 0/1040 · 사람은 6/7 을 고쳤다). 위 전례는 목표 열 ≠ 출발 열이었다 — 같은 열이면 ㄷ 우회(B-9 ②)로 넘긴다.
57
62
  */
58
63
  export declare function farSideChannelCandidates(edge: GeometryEdge, shapes: readonly GeometryShape[]): GeometryPoint[][];
59
64
  /**
@@ -99,6 +104,28 @@ only?: ReadonlySet<string>): Set<string>;
99
104
  * 읽을 수 없는 중첩이 늘지 않을 때만 채택(🔁 「채택 조건에 대가가 없다」 클래스를 미리 막는다).
100
105
  */
101
106
  export declare function repairIntroducedEdgeCrossings(services: Pick<ResolverServices, 'elementRegistry' | 'modeling'>, beforePairs: ReadonlySet<string>, beforeEdgeIds: ReadonlySet<string>): void;
107
+ /**
108
+ * 공유 노드 `node` 쪽 끝을 네 변 중심으로 옮긴 경로 후보(순수). 반대쪽 끝은 **지금 도킹점 · 그 변 그대로** 둔다 —
109
+ * 그 끝은 이 쌍의 교차와 무관하고, 옮기면 그쪽 이웃과의 관계가 새로 생긴다. 반대쪽 도킹점이 변 위가 아니면 후보 없음.
110
+ */
111
+ export declare function redockCandidates(edge: GeometryEdge, node: GeometryShape, shapesById: ReadonlyMap<string, GeometryShape>): GeometryPoint[][];
112
+ /**
113
+ * 🔴 **이 배치가 만든 「끝점을 공유하는」 시퀀스 플로우 교차를 공유 노드의 출입 변을 바꿔 없앤다**(B-146 ⓑ).
114
+ *
115
+ * 표본 98 의 사람 수정 형태 그대로다 — 실패 갈래(게이트웨이 → 오류 노드)가 오류 노드 왼쪽 면으로, 되돌아감(오류 노드 →
116
+ * 상류)이 윗면에서 나가 서로 가로질렀고, 사람은 **실패 갈래를 윗면으로 · 되돌아감을 왼쪽 면에서** 내도록 맞바꿨다
117
+ * (도형 무이동 · 간선 직접 2). 🔴 **한 간선만 옮겨서는 안 풀린다** — 어느 쪽만 옮겨도 다른 쪽과 공선으로 마주 달린다.
118
+ * 그래서 B-90 ⓑ(한 간선씩)와 달리 **쌍을 함께** 고른다.
119
+ *
120
+ * **범위**(B-146 수단 결정) — 시퀀스 × 시퀀스(노드 루프)만 · 블랙박스 풀을 함께 끝점으로 가진 메시지는 보류(사람 기저 0 ·
121
+ * 증언 없음) · 이 배치가 만든 쌍만(`beforeSharedPairs` 밖) · **이 배치가 만든 간선만 움직인다**(B-90 ⓑ 규약 — 기존 간선은
122
+ * 지금 경로 하나만 후보다). 도형은 옮기지 않는다 — 경로로 안 풀리는 형상(g39 = 새 게이트웨이가 기존 우회선 아래)은 남는다.
123
+ *
124
+ * **대가 판정**(B-90 ⓑ 와 같은 자세 — 계산이 곧 판별) — 이 쌍이 더는 교차하지 않고 · 둘이 공선으로 겹치지 않고 · 컨테이너
125
+ * 안이고 · 끝점 공유 교차 총수가 줄고 · **종전 교차 쌍이 새로 생기지 않고** · 문서 판정에 **새 키가 0** 일 때만. 통과한
126
+ * 조합 중 **길이 + 꺾임** 이 가장 작은 것을 고른다(사람 수정본은 도구 산출과 길이가 같고 꺾임만 달랐다).
127
+ */
128
+ export declare function repairIntroducedSharedEndpointCrossings(services: Pick<ResolverServices, 'elementRegistry' | 'modeling'>, beforeSharedPairs: ReadonlySet<string>, beforeEdgeIds: ReadonlySet<string>): void;
102
129
  /**
103
130
  * 풀 횡단 메시지플로우의 6점 경로 계획(순수). `null` = 이 간선은 대상이 아니거나(중간 풀 없음 ·
104
131
  * 끝점 해소 불가) 더 나은 열이 없다.
@@ -1,4 +1,13 @@
1
+ import { BpmnDocumentLocales } from '../../adapter/i18n';
1
2
  import { SymbolicOp } from '../symbolicOp';
2
3
  import { DocumentIndex } from './documentIndex';
3
4
  import { ResolveIssue } from './issues';
4
- export declare function validateOps(ops: readonly SymbolicOp[], index: DocumentIndex): ResolveIssue[];
5
+ /** 검증 옵션 — 문서 밖에서만 알 수 있는 입력. */
6
+ export interface ValidateOpsOptions {
7
+ /**
8
+ * 그룹의 문서 언어 설정(B-4 ④) — 있으면 다국어 그룹이다(문구 = `names`/`texts` 로 문서 언어 전부 · 평문 거부).
9
+ * 없으면 기능이 꺼진 그룹이다(평문만 · 맵 거부). 그룹 설정은 문서에 없으므로 호스트가 공급한다.
10
+ */
11
+ i18n?: BpmnDocumentLocales;
12
+ }
13
+ export declare function validateOps(ops: readonly SymbolicOp[], index: DocumentIndex, options?: ValidateOpsOptions): ResolveIssue[];
@@ -1,5 +1,5 @@
1
1
  import { BwlAfterColumn, BwlBand, BwlPlacement, BwlPoolOrder } from '../core/hints';
2
- import { IrAssociation, IrDataAssociation, IrDataStore, AddableFlowNodeType, IrEventDefinition, IrFlowCondition, IrGroup, IrLane, IrMessageFlow, IrNode, IrParticipant, IrSequenceFlow, IrTextAnnotation } from '../core/ir';
2
+ import { IrLocaleTexts, IrAssociation, IrDataAssociation, IrDataStore, AddableFlowNodeType, IrEventDefinition, IrFlowCondition, IrGroup, IrLane, IrMessageFlow, IrNode, IrParticipant, IrSequenceFlow, IrTextAnnotation } from '../core/ir';
3
3
  /** LLM 이 산출하는 단일 심볼릭 op. `kind` 로 판별한다. */
4
4
  export type SymbolicOp =
5
5
  /** 풀 추가. `order` = 풀 세로 순서 힌트(생략 시 op 순서가 곧 배치 순서). */
@@ -57,6 +57,7 @@ export type SymbolicOp =
57
57
  kind: 'participant.update';
58
58
  id: string;
59
59
  name?: string | null;
60
+ names?: IrLocaleTexts;
60
61
  lanes?: IrLane[];
61
62
  }
62
63
  /** `lane` = 레인 재배정(이동). `type` = 태스크/이벤트 타입 전환(bpmn-js replace 하강 — 외래 확장 속성 유실 가능성은 불변식 2 가 완충). */
@@ -67,6 +68,7 @@ export type SymbolicOp =
67
68
  kind: 'node.update';
68
69
  id: string;
69
70
  name?: string | null;
71
+ names?: IrLocaleTexts;
70
72
  lane?: string;
71
73
  type?: AddableFlowNodeType;
72
74
  eventDefinition?: IrEventDefinition;
@@ -85,6 +87,7 @@ export type SymbolicOp =
85
87
  kind: 'sequenceFlow.update';
86
88
  id: string;
87
89
  name?: string | null;
90
+ names?: IrLocaleTexts;
88
91
  condition?: IrFlowCondition | null;
89
92
  source?: string;
90
93
  target?: string;
@@ -92,16 +95,19 @@ export type SymbolicOp =
92
95
  kind: 'messageFlow.update';
93
96
  id: string;
94
97
  name?: string | null;
98
+ names?: IrLocaleTexts;
95
99
  } | {
96
100
  kind: 'dataStore.update';
97
101
  id: string;
98
102
  name?: string | null;
103
+ names?: IrLocaleTexts;
99
104
  }
100
105
  /** `text` 는 주석의 본질이라 제거 불가(주석 삭제 = element.remove). `placement: null` = 힌트 제거(휴리스틱 복귀). */
101
106
  | {
102
107
  kind: 'annotation.update';
103
108
  id: string;
104
109
  text?: string;
110
+ texts?: IrLocaleTexts;
105
111
  placement?: BwlPlacement | null;
106
112
  }
107
113
  /** `members` 는 전체 재선언(생략 = 보존) — resolver 가 바운즈를 재산출한다. */
@@ -109,8 +115,20 @@ export type SymbolicOp =
109
115
  kind: 'group.update';
110
116
  id: string;
111
117
  name?: string | null;
118
+ names?: IrLocaleTexts;
112
119
  members?: string[];
113
120
  }
121
+ /**
122
+ * **확인만** — 그 요소의 `locale` 칸에 걸린 확인 요청(`bwl:reviewRequest`)을 문구를 바꾸지 않고 해소한다.
123
+ * 다른 언어가 고쳐졌지만 이 칸의 번역은 여전히 맞을 때(오타 수준 수정) 쓴다. 번역을 고쳐야 하면 이것이 아니라
124
+ * 그 요소의 `*.update` 에 `names`/`texts` 를 준다 — 문구가 **실제로 바뀐 칸**의 표식만 해소된다.
125
+ * 다국어 그룹에서만 받는다 · 그 칸에 표식이 없으면 거부한다(읽은 뒤 사람이 이미 정리했을 수 있다).
126
+ */
127
+ | {
128
+ kind: 'translation.confirm';
129
+ id: string;
130
+ locale: string;
131
+ }
114
132
  /** 요소 제거(카테고리 무관 — 도형·연결 균일, 부착 연결은 연쇄 제거). */
115
133
  | {
116
134
  kind: 'element.remove';
@@ -120,5 +138,5 @@ export type SymbolicOp =
120
138
  * 심볼릭 op 종류의 닫힌 집합(단일 출처). resolver·JSON Schema(`schema.ts`)가 공유한다.
121
139
  * 아래 컴파일타임 단언이 이 튜플과 `SymbolicOp['kind']` 의 일치를 강제 — 한쪽만 늘리면 타입 에러.
122
140
  */
123
- export declare const SYMBOLIC_OP_KINDS: readonly ["participant.add", "participant.update", "node.add", "node.update", "sequenceFlow.add", "sequenceFlow.update", "messageFlow.add", "messageFlow.update", "dataStore.add", "dataStore.update", "dataAssociation.add", "association.add", "annotation.add", "annotation.update", "group.add", "group.update", "element.remove"];
141
+ export declare const SYMBOLIC_OP_KINDS: readonly ["participant.add", "participant.update", "node.add", "node.update", "sequenceFlow.add", "sequenceFlow.update", "messageFlow.add", "messageFlow.update", "dataStore.add", "dataStore.update", "dataAssociation.add", "association.add", "annotation.add", "annotation.update", "group.add", "group.update", "translation.confirm", "element.remove"];
124
142
  export type SymbolicOpKind = (typeof SYMBOLIC_OP_KINDS)[number];