@operato/twin-kernel 0.11.3 → 0.11.4

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.
@@ -50,6 +50,18 @@ export interface MasterUpdate {
50
50
  }
51
51
  export interface ProjectedState {
52
52
  revision: number;
53
+ /**
54
+ * **지금 아는 어휘 항목 수** — 「무엇을 알고 있나」를 밖에서 잴 수 있게.
55
+ *
56
+ * ── 왜 수만 내나 (2026-09-05) ─────────────────────────────────────────────
57
+ * 어휘 표 자체는 클 수 있다(로트는 계속 새로 생긴다 — 하루 수백이면 1년에 수십만). 그것을 매
58
+ * 스냅샷에 통째로 실으면 스냅샷이 그 표의 크기를 따라간다.
59
+ *
60
+ * 그래서 여기는 **수**만 낸다. 내용은 대상 하나씩 `masterDataOf()` 로 묻는다.
61
+ *
62
+ * 0 이 아니라 없을 수도 있다 — 어휘를 한 번도 안 받은 트윈에는 이 칸이 없다.
63
+ */
64
+ masterDataSize?: number;
53
65
  /**
54
66
  * 받은 정정 선언들 — 상태에 반영하지 않은 것을 **밝힌다**.
55
67
  * 비어 있지 않으면 "원 시스템이 정정을 보냈고 우리는 아직 반영하지 못했다" 는 뜻이다(조용한 무시 금지).
@@ -407,6 +419,20 @@ export declare class ObservedReducer {
407
419
  * 비직렬 재고는 물품의 키가 곧 클래스 식별자다. 직렬 개체는 클래스가 따로 있다. 두 모양이 다 오므로
408
420
  * 둘 다 본다 — 한쪽만 보면 그 원본에서는 값이 조용히 비어 있게 된다.
409
421
  */
422
+ /**
423
+ * **이 클래스에 대해 아는 것** — 수량으로만 말하는 원본에서 로트 어휘를 읽는 길.
424
+ *
425
+ * ── 왜 필요한가 (인티그레이션 레인이 올림, 2026-09-05) ─────────────────────
426
+ * 어휘 요소(로트 번호·소비기한)는 들어와서 `classMaster` 에 앉고 검사점에도 실린다. 그런데
427
+ * **밖에서 물을 길이 없었다** — `masterAttributesOf` 는 사적이고, 물품을 꾸미는 데만 쓰였다.
428
+ *
429
+ * 그리고 그 꾸미기는 **이미 서 있는 물품만** 다시 센다. 낱개에 일련번호를 안 붙이는 원본은
430
+ * `epcList` 를 비워 보내므로 걸릴 물품이 아예 없고, 그러면 로트 번호·소비기한이 **올 리 없는
431
+ * 물품을 기다린다.** 잃지는 않는데 아무도 안 본다.
432
+ *
433
+ * 그 원본에서는 **클래스가 주어**다. 물품이 아니라 클래스에게 물어야 답이 나온다.
434
+ */
435
+ masterDataOf(classUri: string | undefined): Record<string, unknown> | undefined;
410
436
  private masterAttributesOf;
411
437
  /**
412
438
  * **마스터데이터를 받는다** — 어휘 요소의 속성을 상태에 세운다(§`master-data`).
@@ -991,6 +991,22 @@ export class ObservedReducer {
991
991
  * 비직렬 재고는 물품의 키가 곧 클래스 식별자다. 직렬 개체는 클래스가 따로 있다. 두 모양이 다 오므로
992
992
  * 둘 다 본다 — 한쪽만 보면 그 원본에서는 값이 조용히 비어 있게 된다.
993
993
  */
994
+ /**
995
+ * **이 클래스에 대해 아는 것** — 수량으로만 말하는 원본에서 로트 어휘를 읽는 길.
996
+ *
997
+ * ── 왜 필요한가 (인티그레이션 레인이 올림, 2026-09-05) ─────────────────────
998
+ * 어휘 요소(로트 번호·소비기한)는 들어와서 `classMaster` 에 앉고 검사점에도 실린다. 그런데
999
+ * **밖에서 물을 길이 없었다** — `masterAttributesOf` 는 사적이고, 물품을 꾸미는 데만 쓰였다.
1000
+ *
1001
+ * 그리고 그 꾸미기는 **이미 서 있는 물품만** 다시 센다. 낱개에 일련번호를 안 붙이는 원본은
1002
+ * `epcList` 를 비워 보내므로 걸릴 물품이 아예 없고, 그러면 로트 번호·소비기한이 **올 리 없는
1003
+ * 물품을 기다린다.** 잃지는 않는데 아무도 안 본다.
1004
+ *
1005
+ * 그 원본에서는 **클래스가 주어**다. 물품이 아니라 클래스에게 물어야 답이 나온다.
1006
+ */
1007
+ masterDataOf(classUri) {
1008
+ return classUri ? this.classMaster.attributesOf(classUri) : undefined;
1009
+ }
994
1010
  masterAttributesOf(classUri, epc) {
995
1011
  return this.classMaster.attributesOf(classUri) ?? this.classMaster.attributesOf(epc);
996
1012
  }
@@ -1303,6 +1319,7 @@ export class ObservedReducer {
1303
1319
  occ.set(it.location, (occ.get(it.location) ?? 0) + 1);
1304
1320
  return {
1305
1321
  revision: this.revision,
1322
+ ...(this.classMaster.size ? { masterDataSize: this.classMaster.size } : {}),
1306
1323
  ...(this.corrections.length ? { corrections: this.corrections.map(c => ({ ...c })) } : {}),
1307
1324
  ...(this.unhandled.size
1308
1325
  ? { unhandled: [...this.unhandled.entries()].map(([eventType, v]) => ({ eventType, ...v })).sort((a, b) => b.count - a.count) }
@@ -3083,6 +3083,22 @@ var ObservedReducer = class {
3083
3083
  * 비직렬 재고는 물품의 키가 곧 클래스 식별자다. 직렬 개체는 클래스가 따로 있다. 두 모양이 다 오므로
3084
3084
  * 둘 다 본다 — 한쪽만 보면 그 원본에서는 값이 조용히 비어 있게 된다.
3085
3085
  */
3086
+ /**
3087
+ * **이 클래스에 대해 아는 것** — 수량으로만 말하는 원본에서 로트 어휘를 읽는 길.
3088
+ *
3089
+ * ── 왜 필요한가 (인티그레이션 레인이 올림, 2026-09-05) ─────────────────────
3090
+ * 어휘 요소(로트 번호·소비기한)는 들어와서 `classMaster` 에 앉고 검사점에도 실린다. 그런데
3091
+ * **밖에서 물을 길이 없었다** — `masterAttributesOf` 는 사적이고, 물품을 꾸미는 데만 쓰였다.
3092
+ *
3093
+ * 그리고 그 꾸미기는 **이미 서 있는 물품만** 다시 센다. 낱개에 일련번호를 안 붙이는 원본은
3094
+ * `epcList` 를 비워 보내므로 걸릴 물품이 아예 없고, 그러면 로트 번호·소비기한이 **올 리 없는
3095
+ * 물품을 기다린다.** 잃지는 않는데 아무도 안 본다.
3096
+ *
3097
+ * 그 원본에서는 **클래스가 주어**다. 물품이 아니라 클래스에게 물어야 답이 나온다.
3098
+ */
3099
+ masterDataOf(classUri) {
3100
+ return classUri ? this.classMaster.attributesOf(classUri) : void 0;
3101
+ }
3086
3102
  masterAttributesOf(classUri, epc) {
3087
3103
  return this.classMaster.attributesOf(classUri) ?? this.classMaster.attributesOf(epc);
3088
3104
  }
@@ -3352,6 +3368,7 @@ var ObservedReducer = class {
3352
3368
  for (const it of this.items.values()) occ.set(it.location, (occ.get(it.location) ?? 0) + 1);
3353
3369
  return {
3354
3370
  revision: this.revision,
3371
+ ...this.classMaster.size ? { masterDataSize: this.classMaster.size } : {},
3355
3372
  ...this.corrections.length ? { corrections: this.corrections.map((c) => ({ ...c })) } : {},
3356
3373
  ...this.unhandled.size ? { unhandled: [...this.unhandled.entries()].map(([eventType, v]) => ({ eventType, ...v })).sort((a, b) => b.count - a.count) } : {},
3357
3374
  locations: [...this.master.values()].map((n) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@operato/twin-kernel",
3
- "version": "0.11.3",
3
+ "version": "0.11.4",
4
4
  "type": "module",
5
5
  "description": "Twin Domain Kernel — framework-agnostic, zero-dep (domain + sim + 3-channel contract). WMS/YMS/MES, EPCIS 2.0 · ISA-95.",
6
6
  "publishConfig": {