@things-factory/headless-twin 10.0.7 โ†’ 10.0.9

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.
Files changed (143) hide show
  1. package/dist-server/engine/attention-digest.d.ts +52 -0
  2. package/dist-server/engine/attention-digest.js +76 -0
  3. package/dist-server/engine/attention-digest.js.map +1 -0
  4. package/dist-server/engine/board-vocabulary.d.ts +17 -0
  5. package/dist-server/engine/board-vocabulary.js +63 -0
  6. package/dist-server/engine/board-vocabulary.js.map +1 -0
  7. package/dist-server/engine/command-routing.d.ts +33 -0
  8. package/dist-server/engine/command-routing.js +53 -0
  9. package/dist-server/engine/command-routing.js.map +1 -0
  10. package/dist-server/engine/entity-delta.d.ts +13 -6
  11. package/dist-server/engine/entity-delta.js +38 -12
  12. package/dist-server/engine/entity-delta.js.map +1 -1
  13. package/dist-server/engine/index.d.ts +6 -0
  14. package/dist-server/engine/index.js +10 -0
  15. package/dist-server/engine/index.js.map +1 -1
  16. package/dist-server/engine/kpi-baseline.d.ts +78 -0
  17. package/dist-server/engine/kpi-baseline.js +123 -0
  18. package/dist-server/engine/kpi-baseline.js.map +1 -0
  19. package/dist-server/engine/kpi-broadcast.d.ts +4 -0
  20. package/dist-server/engine/kpi-broadcast.js +16 -0
  21. package/dist-server/engine/kpi-broadcast.js.map +1 -0
  22. package/dist-server/engine/kpi-query.d.ts +31 -0
  23. package/dist-server/engine/kpi-query.js +50 -2
  24. package/dist-server/engine/kpi-query.js.map +1 -1
  25. package/dist-server/engine/live-attentions.d.ts +1 -0
  26. package/dist-server/engine/live-attentions.js +7 -1
  27. package/dist-server/engine/live-attentions.js.map +1 -1
  28. package/dist-server/engine/runtime-key.d.ts +15 -0
  29. package/dist-server/engine/runtime-key.js +64 -0
  30. package/dist-server/engine/runtime-key.js.map +1 -0
  31. package/dist-server/engine/state-axes.d.ts +16 -0
  32. package/dist-server/engine/state-axes.js +54 -0
  33. package/dist-server/engine/state-axes.js.map +1 -0
  34. package/dist-server/engine/twin-engine.d.ts +92 -16
  35. package/dist-server/engine/twin-engine.js +335 -77
  36. package/dist-server/engine/twin-engine.js.map +1 -1
  37. package/dist-server/engine/twin-level.d.ts +23 -0
  38. package/dist-server/engine/twin-level.js +52 -0
  39. package/dist-server/engine/twin-level.js.map +1 -0
  40. package/dist-server/engine/warm-start.d.ts +58 -12
  41. package/dist-server/engine/warm-start.js +80 -9
  42. package/dist-server/engine/warm-start.js.map +1 -1
  43. package/dist-server/service/reference/discovery-result.d.ts +34 -0
  44. package/dist-server/service/reference/discovery-result.js +84 -0
  45. package/dist-server/service/reference/discovery-result.js.map +1 -0
  46. package/dist-server/service/reference/ingest-space.d.ts +30 -0
  47. package/dist-server/service/reference/ingest-space.js +63 -0
  48. package/dist-server/service/reference/ingest-space.js.map +1 -0
  49. package/dist-server/service/reference/knob-defaults.d.ts +20 -0
  50. package/dist-server/service/reference/knob-defaults.js +59 -0
  51. package/dist-server/service/reference/knob-defaults.js.map +1 -0
  52. package/dist-server/service/reference/reference-live.js +2 -2
  53. package/dist-server/service/reference/reference-live.js.map +1 -1
  54. package/dist-server/service/reference/reference-master.d.ts +37 -2
  55. package/dist-server/service/reference/reference-master.js +55 -5
  56. package/dist-server/service/reference/reference-master.js.map +1 -1
  57. package/dist-server/service/reference/reference-resolver.d.ts +2 -2
  58. package/dist-server/service/reference/reference-resolver.js +71 -15
  59. package/dist-server/service/reference/reference-resolver.js.map +1 -1
  60. package/dist-server/service/twin-attention/twin-attention-query.d.ts +8 -1
  61. package/dist-server/service/twin-attention/twin-attention-query.js +39 -8
  62. package/dist-server/service/twin-attention/twin-attention-query.js.map +1 -1
  63. package/dist-server/service/twin-control/twin-control-mutation.d.ts +2 -0
  64. package/dist-server/service/twin-control/twin-control-mutation.js +29 -10
  65. package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
  66. package/dist-server/service/twin-forecast/twin-forecast-query.js +2 -1
  67. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
  68. package/dist-server/service/twin-instance/twin-instance.js +4 -2
  69. package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
  70. package/dist-server/service/twin-journal/twin-journal-query.d.ts +6 -2
  71. package/dist-server/service/twin-journal/twin-journal-query.js +25 -7
  72. package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
  73. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +8 -0
  74. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +23 -1
  75. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
  76. package/dist-server/service/twin-metrics/twin-metrics-query.js +1 -1
  77. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
  78. package/dist-server/service/twin-space/twin-space-resolver.js +9 -0
  79. package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
  80. package/dist-server/service/twin-state/twin-state-subscription.js +1 -1
  81. package/dist-server/service/twin-state/twin-state-subscription.js.map +1 -1
  82. package/dist-server/service/twin-structure/twin-structure.js +2 -1
  83. package/dist-server/service/twin-structure/twin-structure.js.map +1 -1
  84. package/dist-server/service/twin-target/twin-target-resolver.js +21 -4
  85. package/dist-server/service/twin-target/twin-target-resolver.js.map +1 -1
  86. package/dist-server/tsconfig.tsbuildinfo +1 -1
  87. package/package.json +6 -6
  88. package/server/engine/attention-digest.ts +102 -0
  89. package/server/engine/board-vocabulary.ts +61 -0
  90. package/server/engine/command-routing.ts +67 -0
  91. package/server/engine/entity-delta.ts +33 -11
  92. package/server/engine/index.ts +10 -0
  93. package/server/engine/kpi-baseline.ts +202 -0
  94. package/server/engine/kpi-broadcast.ts +13 -0
  95. package/server/engine/kpi-query.ts +81 -3
  96. package/server/engine/live-attentions.ts +7 -2
  97. package/server/engine/runtime-key.ts +58 -0
  98. package/server/engine/state-axes.ts +55 -0
  99. package/server/engine/twin-engine.ts +350 -77
  100. package/server/engine/twin-level.ts +48 -0
  101. package/server/engine/warm-start.ts +130 -16
  102. package/server/service/reference/discovery-result.ts +95 -0
  103. package/server/service/reference/ingest-space.ts +70 -0
  104. package/server/service/reference/knob-defaults.ts +59 -0
  105. package/server/service/reference/reference-live.ts +2 -2
  106. package/server/service/reference/reference-master.ts +94 -8
  107. package/server/service/reference/reference-resolver.ts +80 -16
  108. package/server/service/twin-attention/twin-attention-query.ts +43 -6
  109. package/server/service/twin-control/twin-control-mutation.ts +31 -12
  110. package/server/service/twin-forecast/twin-forecast-query.ts +3 -2
  111. package/server/service/twin-instance/twin-instance.ts +6 -2
  112. package/server/service/twin-journal/twin-journal-query.ts +35 -5
  113. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +18 -2
  114. package/server/service/twin-metrics/twin-metrics-query.ts +1 -1
  115. package/server/service/twin-space/twin-space-resolver.ts +10 -1
  116. package/server/service/twin-state/twin-state-subscription.ts +1 -1
  117. package/server/service/twin-structure/twin-structure.ts +4 -1
  118. package/server/service/twin-target/twin-target-resolver.ts +22 -4
  119. package/test/attention-digest.test.ts +135 -0
  120. package/test/board-vocabulary.test.ts +114 -0
  121. package/test/capability-mapping.test.ts +4 -4
  122. package/test/command-routing.test.ts +61 -0
  123. package/test/discovery-result.test.ts +75 -0
  124. package/test/entity-delta.test.ts +25 -25
  125. package/test/ingest-bench.test.ts +3 -3
  126. package/test/ingest-space.test.ts +50 -0
  127. package/test/knob-defaults.test.ts +72 -0
  128. package/test/kpi-baseline-db.test.ts +214 -0
  129. package/test/kpi-baseline.test.ts +196 -0
  130. package/test/kpi-query-bench.test.ts +128 -0
  131. package/test/live-mirror-parity.test.ts +35 -2
  132. package/test/master-to-twin.test.ts +7 -3
  133. package/test/mutation-gate.test.ts +108 -0
  134. package/test/oee-accumulator.test.ts +65 -1
  135. package/test/registry-key-guard.test.ts +80 -0
  136. package/test/runtime-key.test.ts +66 -0
  137. package/test/scale-twin-bench.test.ts +2 -2
  138. package/test/state-axes.test.ts +74 -0
  139. package/test/streamline-e2e.test.ts +2 -2
  140. package/test/structure-revision-db.test.ts +5 -4
  141. package/test/tenant-registry-db.test.ts +149 -0
  142. package/test/warm-start-seam.test.ts +140 -0
  143. package/test/warm-start.test.ts +138 -4
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /*
3
+ * ๋…ธ๋ธŒ ๊ธฐ๋ณธ๊ฐ’ ์ ์šฉ โ€” **์ˆœ์ˆ˜**. "์•ˆ ์ค€ ๊ฐ’์€ ํ…œํ”Œ๋ฆฟ์ด ์„ ์–ธํ•œ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ."
4
+ *
5
+ * โ”€โ”€ ์™œ ์žˆ๋‚˜ (2026-08-05) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
6
+ * ํ…œํ”Œ๋ฆฟ์€ ๋…ธ๋ธŒ๋งˆ๋‹ค ๊ธฐ๋ณธ๊ฐ’์„ ์„ ์–ธํ•œ๋‹ค(`knobs[].default`). ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ๊ธฐ๋ณธ๊ฐ’์„ ์ฑ„์šฐ๋Š” ์ผ์„ **์œ„์ž๋“œ๋งŒ**
7
+ * ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค โ€” ์„œ๋ฒ„๋Š” ๋ฐ›์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ `build(p)` ์— ๋„˜๊ธด๋‹ค. ๊ทธ๋ž˜์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ผ๋ถ€๋งŒ ์ฃผ๊ณ 
8
+ * ๋ถ€๋ฅด๋ฉด(AIยท์Šคํฌ๋ฆฝํŠธยทAPI ํ˜ธ์ถœ์ž) ํ…œํ”Œ๋ฆฟ ์•ˆ์—์„œ `Number(p.inboundRate) || 0` ์ด **0** ์ด ๋˜๊ณ ,
9
+ * ๋ฐœ์ƒ๋ฅ  0 = ๋„์ฐฉ ์—†์Œ = **์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š๋Š” ํŠธ์œˆ**์ด ์กฐ์šฉํžˆ ๋งŒ๋“ค์–ด์ง„๋‹ค.
10
+ *
11
+ * ์‹ค์ œ๋กœ ๊ทธ ํ•จ์ •์„ ๋ฐŸ์•˜๋‹ค: ์œ ํ†ต๊ฐ€๊ณต ์ฐฝ๊ณ ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ผ๋ถ€๋งŒ ์ฃผ๊ณ  ๋งŒ๋“ค์—ˆ๋”๋‹ˆ ์ด๋ฒคํŠธ๊ฐ€ 0๊ฑด์ด์—ˆ๊ณ ,
12
+ * ์ฒ˜์Œ์—๋Š” ํ…œํ”Œ๋ฆฟ์ด ๊นจ์ง„ ๊ฒƒ์œผ๋กœ ์˜ค์ง„ํ–ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์•„๋Š” ๊ณณ์ด ๊ณ„์•ฝ(๋…ธ๋ธŒ ์Šคํ‚ค๋งˆ)์ธ๋ฐ ๊ทธ๊ฒƒ์„ ์ ์šฉํ•˜๋Š”
13
+ * ๊ณณ์ด ํ™”๋ฉด๋ฟ์ด๋ฉด, ํ™”๋ฉด์„ ๊ฑฐ์น˜์ง€ ์•Š๋Š” ๋ชจ๋“  ๊ฒฝ๋กœ๊ฐ€ ํ•จ์ •์ด ๋œ๋‹ค.
14
+ *
15
+ * โ”€โ”€ 0 ์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋ฎ์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
16
+ * ๋ฐœ์ƒ๋ฅ  `0` ์€ "๋„์ฐฉ ์—†์Œ" ์ด๋ผ๋Š” **๋œป ์žˆ๋Š” ๊ฐ’**์ด๋‹ค. ์—†๋Š” ๊ฒƒ๊ณผ 0 ์€ ๋‹ค๋ฅด๋‹ค โ€” falsy ๋กœ ํŒ์ •ํ•ด ๋ฎ์œผ๋ฉด
17
+ * "์ž๊ทน ์—†์ด ๊ตฌ์กฐ๋งŒ ๋ณด๊ฒ ๋‹ค" ๋Š” ์„ ์–ธ์ด ์กฐ์šฉํžˆ ๋’ค์ง‘ํžŒ๋‹ค. ๊ทธ๋ž˜์„œ **ํ‚ค๊ฐ€ ์—†์„ ๋•Œ๋งŒ** ์ฑ„์šด๋‹ค.
18
+ * `null` ์€ ์—†๋Š” ๊ฒƒ์œผ๋กœ ๋ณธ๋‹ค(JSONยทGraphQL ๊ฒฝ๋กœ์—์„œ "์ฃผ์ง€ ์•Š์Œ" ์ด null ๋กœ ์˜ค๋Š” ์ผ์ด ํ”ํ•˜๋‹ค).
19
+ *
20
+ * โ”€โ”€ ์„ ์–ธ ๋ฐ– ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์†๋Œ€์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
21
+ * ํ…œํ”Œ๋ฆฟ์€ ๋…ธ๋ธŒ์— ์—†๋Š” ๊ฐ’๋„ ์ฝ๋Š”๋‹ค(์˜ˆ: `geo` ๋Œ€์‹  `lat`/`lon` ํด๋ฐฑ). ๋ชจ๋ฅด๋Š” ํ‚ค๋ฅผ ๊ฑท์–ด๋‚ด๋ฉด ๊ทธ ๊ฒฝ๋กœ๊ฐ€
22
+ * ์กฐ์šฉํžˆ ๋Š๊ธด๋‹ค. ๊ทธ๋Œ€๋กœ ํ†ต๊ณผ์‹œํ‚จ๋‹ค.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.applyKnobDefaults = applyKnobDefaults;
26
+ exports.filledKnobKeys = filledKnobKeys;
27
+ /**
28
+ * ๋น ์ง„ ๋…ธ๋ธŒ๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฑ„์šด๋‹ค.
29
+ *
30
+ * @param knobs ํ…œํ”Œ๋ฆฟ์ด ์„ ์–ธํ•œ ๋…ธ๋ธŒ๋“ค(์—†์œผ๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค์ค€๋‹ค).
31
+ * @param params ํ˜ธ์ถœ์ž๊ฐ€ ์ค€ ํŒŒ๋ผ๋ฏธํ„ฐ.
32
+ * @returns ์ƒˆ ๊ฐ์ฒด โ€” ์ž…๋ ฅ์„ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค(ํ˜ธ์ถœ์ž์˜ ๊ฐ์ฒด๊ฐ€ ๋ชฐ๋ž˜ ๋ณ€ํ•˜๋ฉด ์ถ”์ ์ด ์–ด๋ ต๋‹ค).
33
+ */
34
+ function applyKnobDefaults(knobs, params) {
35
+ const out = { ...(params ?? {}) };
36
+ for (const k of knobs ?? []) {
37
+ if (!k?.key)
38
+ continue;
39
+ if (k.default === undefined)
40
+ continue; // ๊ธฐ๋ณธ๊ฐ’์„ ์„ ์–ธํ•˜์ง€ ์•Š์€ ๋…ธ๋ธŒ๋Š” ์ฑ„์šธ ๊ฒƒ์ด ์—†๋‹ค
41
+ const given = out[k.key];
42
+ if (given === undefined || given === null)
43
+ out[k.key] = k.default;
44
+ }
45
+ return out;
46
+ }
47
+ /**
48
+ * ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฑ„์šด ๋…ธ๋ธŒ ์ด๋ฆ„๋“ค โ€” ํ˜ธ์ถœ์ž์—๊ฒŒ "๋ฌด์—‡์„ ๋‚ด๊ฐ€ ์ •ํ•ด ์คฌ๋Š”์ง€" ์•Œ๋ฆด ๋•Œ ์“ด๋‹ค.
49
+ *
50
+ * ์กฐ์šฉํžˆ ์ฑ„์šฐ๋Š” ๊ฒƒ๋„ ์กฐ์šฉํžˆ ๋น„์šฐ๋Š” ๊ฒƒ๋งŒํผ ์œ„ํ—˜ํ•˜๋‹ค: ์‚ฌ์šฉ์ž๊ฐ€ ์ค€ ์  ์—†๋Š” ๊ฐ’์œผ๋กœ ํŠธ์œˆ์ด ๋งŒ๋“ค์–ด์กŒ๋Š”๋ฐ
51
+ * ์•„๋ฌด ๋ง์ด ์—†์œผ๋ฉด, ๋‚˜์ค‘์— "์™œ ์ด ์ˆ˜์น˜์ธ๊ฐ€" ๋ฅผ ์•„๋ฌด๋„ ๋‹ตํ•  ์ˆ˜ ์—†๋‹ค.
52
+ */
53
+ function filledKnobKeys(knobs, params) {
54
+ const given = params ?? {};
55
+ return (knobs ?? [])
56
+ .filter(k => k?.key && k.default !== undefined && (given[k.key] === undefined || given[k.key] === null))
57
+ .map(k => k.key);
58
+ }
59
+ //# sourceMappingURL=knob-defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knob-defaults.js","sourceRoot":"","sources":["../../../server/service/reference/knob-defaults.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;AAeH,8CASC;AAQD,wCAKC;AA7BD;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,KAA6C,EAAE,MAAkD;IACjI,MAAM,GAAG,GAA4B,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAA;IAC1D,KAAK,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,EAAE,GAAG;YAAE,SAAQ;QACrB,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;YAAE,SAAQ,CAAC,4BAA4B;QAClE,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACxB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAA;IACnE,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,KAA6C,EAAE,MAAkD;IAC9H,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,CAAA;IAC1B,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAI,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,GAAI,CAAC,KAAK,IAAI,CAAC,CAAC;SACzG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAI,CAAC,CAAA;AACrB,CAAC","sourcesContent":["/*\n * ๋…ธ๋ธŒ ๊ธฐ๋ณธ๊ฐ’ ์ ์šฉ โ€” **์ˆœ์ˆ˜**. \"์•ˆ ์ค€ ๊ฐ’์€ ํ…œํ”Œ๋ฆฟ์ด ์„ ์–ธํ•œ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ.\"\n *\n * โ”€โ”€ ์™œ ์žˆ๋‚˜ (2026-08-05) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ํ…œํ”Œ๋ฆฟ์€ ๋…ธ๋ธŒ๋งˆ๋‹ค ๊ธฐ๋ณธ๊ฐ’์„ ์„ ์–ธํ•œ๋‹ค(`knobs[].default`). ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ๊ธฐ๋ณธ๊ฐ’์„ ์ฑ„์šฐ๋Š” ์ผ์„ **์œ„์ž๋“œ๋งŒ**\n * ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค โ€” ์„œ๋ฒ„๋Š” ๋ฐ›์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ `build(p)` ์— ๋„˜๊ธด๋‹ค. ๊ทธ๋ž˜์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ผ๋ถ€๋งŒ ์ฃผ๊ณ \n * ๋ถ€๋ฅด๋ฉด(AIยท์Šคํฌ๋ฆฝํŠธยทAPI ํ˜ธ์ถœ์ž) ํ…œํ”Œ๋ฆฟ ์•ˆ์—์„œ `Number(p.inboundRate) || 0` ์ด **0** ์ด ๋˜๊ณ ,\n * ๋ฐœ์ƒ๋ฅ  0 = ๋„์ฐฉ ์—†์Œ = **์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š๋Š” ํŠธ์œˆ**์ด ์กฐ์šฉํžˆ ๋งŒ๋“ค์–ด์ง„๋‹ค.\n *\n * ์‹ค์ œ๋กœ ๊ทธ ํ•จ์ •์„ ๋ฐŸ์•˜๋‹ค: ์œ ํ†ต๊ฐ€๊ณต ์ฐฝ๊ณ ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ผ๋ถ€๋งŒ ์ฃผ๊ณ  ๋งŒ๋“ค์—ˆ๋”๋‹ˆ ์ด๋ฒคํŠธ๊ฐ€ 0๊ฑด์ด์—ˆ๊ณ ,\n * ์ฒ˜์Œ์—๋Š” ํ…œํ”Œ๋ฆฟ์ด ๊นจ์ง„ ๊ฒƒ์œผ๋กœ ์˜ค์ง„ํ–ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์•„๋Š” ๊ณณ์ด ๊ณ„์•ฝ(๋…ธ๋ธŒ ์Šคํ‚ค๋งˆ)์ธ๋ฐ ๊ทธ๊ฒƒ์„ ์ ์šฉํ•˜๋Š”\n * ๊ณณ์ด ํ™”๋ฉด๋ฟ์ด๋ฉด, ํ™”๋ฉด์„ ๊ฑฐ์น˜์ง€ ์•Š๋Š” ๋ชจ๋“  ๊ฒฝ๋กœ๊ฐ€ ํ•จ์ •์ด ๋œ๋‹ค.\n *\n * โ”€โ”€ 0 ์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋ฎ์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ๋ฐœ์ƒ๋ฅ  `0` ์€ \"๋„์ฐฉ ์—†์Œ\" ์ด๋ผ๋Š” **๋œป ์žˆ๋Š” ๊ฐ’**์ด๋‹ค. ์—†๋Š” ๊ฒƒ๊ณผ 0 ์€ ๋‹ค๋ฅด๋‹ค โ€” falsy ๋กœ ํŒ์ •ํ•ด ๋ฎ์œผ๋ฉด\n * \"์ž๊ทน ์—†์ด ๊ตฌ์กฐ๋งŒ ๋ณด๊ฒ ๋‹ค\" ๋Š” ์„ ์–ธ์ด ์กฐ์šฉํžˆ ๋’ค์ง‘ํžŒ๋‹ค. ๊ทธ๋ž˜์„œ **ํ‚ค๊ฐ€ ์—†์„ ๋•Œ๋งŒ** ์ฑ„์šด๋‹ค.\n * `null` ์€ ์—†๋Š” ๊ฒƒ์œผ๋กœ ๋ณธ๋‹ค(JSONยทGraphQL ๊ฒฝ๋กœ์—์„œ \"์ฃผ์ง€ ์•Š์Œ\" ์ด null ๋กœ ์˜ค๋Š” ์ผ์ด ํ”ํ•˜๋‹ค).\n *\n * โ”€โ”€ ์„ ์–ธ ๋ฐ– ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์†๋Œ€์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ํ…œํ”Œ๋ฆฟ์€ ๋…ธ๋ธŒ์— ์—†๋Š” ๊ฐ’๋„ ์ฝ๋Š”๋‹ค(์˜ˆ: `geo` ๋Œ€์‹  `lat`/`lon` ํด๋ฐฑ). ๋ชจ๋ฅด๋Š” ํ‚ค๋ฅผ ๊ฑท์–ด๋‚ด๋ฉด ๊ทธ ๊ฒฝ๋กœ๊ฐ€\n * ์กฐ์šฉํžˆ ๋Š๊ธด๋‹ค. ๊ทธ๋Œ€๋กœ ํ†ต๊ณผ์‹œํ‚จ๋‹ค.\n */\n\n/** ํ…œํ”Œ๋ฆฟ ๋…ธ๋ธŒ โ€” ๊ธฐ๋ณธ๊ฐ’ ์ ์šฉ์— ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ๋ณธ๋‹ค. */\nexport interface KnobLike {\n key?: string\n default?: unknown\n}\n\n/**\n * ๋น ์ง„ ๋…ธ๋ธŒ๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฑ„์šด๋‹ค.\n *\n * @param knobs ํ…œํ”Œ๋ฆฟ์ด ์„ ์–ธํ•œ ๋…ธ๋ธŒ๋“ค(์—†์œผ๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค์ค€๋‹ค).\n * @param params ํ˜ธ์ถœ์ž๊ฐ€ ์ค€ ํŒŒ๋ผ๋ฏธํ„ฐ.\n * @returns ์ƒˆ ๊ฐ์ฒด โ€” ์ž…๋ ฅ์„ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค(ํ˜ธ์ถœ์ž์˜ ๊ฐ์ฒด๊ฐ€ ๋ชฐ๋ž˜ ๋ณ€ํ•˜๋ฉด ์ถ”์ ์ด ์–ด๋ ต๋‹ค).\n */\nexport function applyKnobDefaults(knobs: readonly KnobLike[] | undefined | null, params: Record<string, unknown> | undefined | null): Record<string, unknown> {\n const out: Record<string, unknown> = { ...(params ?? {}) }\n for (const k of knobs ?? []) {\n if (!k?.key) continue\n if (k.default === undefined) continue // ๊ธฐ๋ณธ๊ฐ’์„ ์„ ์–ธํ•˜์ง€ ์•Š์€ ๋…ธ๋ธŒ๋Š” ์ฑ„์šธ ๊ฒƒ์ด ์—†๋‹ค\n const given = out[k.key]\n if (given === undefined || given === null) out[k.key] = k.default\n }\n return out\n}\n\n/**\n * ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฑ„์šด ๋…ธ๋ธŒ ์ด๋ฆ„๋“ค โ€” ํ˜ธ์ถœ์ž์—๊ฒŒ \"๋ฌด์—‡์„ ๋‚ด๊ฐ€ ์ •ํ•ด ์คฌ๋Š”์ง€\" ์•Œ๋ฆด ๋•Œ ์“ด๋‹ค.\n *\n * ์กฐ์šฉํžˆ ์ฑ„์šฐ๋Š” ๊ฒƒ๋„ ์กฐ์šฉํžˆ ๋น„์šฐ๋Š” ๊ฒƒ๋งŒํผ ์œ„ํ—˜ํ•˜๋‹ค: ์‚ฌ์šฉ์ž๊ฐ€ ์ค€ ์  ์—†๋Š” ๊ฐ’์œผ๋กœ ํŠธ์œˆ์ด ๋งŒ๋“ค์–ด์กŒ๋Š”๋ฐ\n * ์•„๋ฌด ๋ง์ด ์—†์œผ๋ฉด, ๋‚˜์ค‘์— \"์™œ ์ด ์ˆ˜์น˜์ธ๊ฐ€\" ๋ฅผ ์•„๋ฌด๋„ ๋‹ตํ•  ์ˆ˜ ์—†๋‹ค.\n */\nexport function filledKnobKeys(knobs: readonly KnobLike[] | undefined | null, params: Record<string, unknown> | undefined | null): string[] {\n const given = params ?? {}\n return (knobs ?? [])\n .filter(k => k?.key && k.default !== undefined && (given[k.key!] === undefined || given[k.key!] === null))\n .map(k => k.key!)\n}\n"]}
@@ -30,13 +30,13 @@ async function startReferenceLiveFeed(domainId, adapterType, cfg, site, instance
30
30
  index_js_1.TwinEngine.startLive(instanceId, domainId, det.kind ?? 'wms', await index_js_1.TwinEngine.withSpaceTimeBase(det.board, domainId));
31
31
  stopReferenceLiveFeed(instanceId); // ์žฌ๊ธฐ๋™ ์‹œ ์ด์ „ ํ”ผ๋“œ ์ •๋ฆฌ
32
32
  const unsubscribe = adapter.openLiveFeed(cfg, site, (records) => {
33
- if (!index_js_1.TwinEngine.instances[instanceId]) {
33
+ if (!index_js_1.TwinEngine.owns(domainId, instanceId)) {
34
34
  stopReferenceLiveFeed(instanceId); // ์ธ์Šคํ„ด์Šค ์‚ฌ๋ผ์ง€๋ฉด ์ž๊ฐ€ ์ •์ง€(์•ˆ์ „๋ง)
35
35
  return;
36
36
  }
37
37
  const { accepted } = (0, index_js_1.ingestCanonicalRecords)(records, domainId, new Date().toISOString());
38
38
  if (accepted.length)
39
- index_js_1.TwinEngine.ingestLive(instanceId, accepted);
39
+ index_js_1.TwinEngine.ingestLive(domainId, instanceId, accepted);
40
40
  });
41
41
  feeds.set(instanceId, unsubscribe);
42
42
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"reference-live.js","sourceRoot":"","sources":["../../../server/service/reference/reference-live.ts"],"names":[],"mappings":";;AAkBA,wDA4BC;AAGD,sDAMC;AAGD,wDAEC;AA5DD,iEAA+F;AAC/F,oDAAgG;AAEhG;;;;;;GAMG;AAEH,iEAAiE;AACjE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAA;AAE3C;;;GAGG;AACI,KAAK,UAAU,sBAAsB,CAC1C,QAAgB,EAChB,WAAmB,EACnB,GAAqB,EACrB,IAAoB,EACpB,UAAkB;IAElB,MAAM,OAAO,GAAG,IAAA,iCAAU,EAAC,WAAW,CAAC,CAAA;IACvC,IAAI,CAAC,OAAO,EAAE,YAAY;QAAE,OAAO,KAAK,CAAA;IAExC,MAAM,GAAG,GAAG,MAAM,qBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACzD,IAAI,CAAC,GAAG,EAAE,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,aAAa,UAAU,gEAAgE,CAAC,CAAA;IAEzH,wFAAwF;IACxF,uDAAuD;IACvD,qBAAU,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,IAAI,KAAK,EAAE,MAAM,qBAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEtH,qBAAqB,CAAC,UAAU,CAAC,CAAA,CAAC,iBAAiB;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,OAAkB,EAAE,EAAE;QACzE,IAAI,CAAC,qBAAU,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,qBAAqB,CAAC,UAAU,CAAC,CAAA,CAAC,uBAAuB;YACzD,OAAM;QACR,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAA,iCAAsB,EAAC,OAA4B,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;QAC7G,IAAI,QAAQ,CAAC,MAAM;YAAE,qBAAU,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAClE,CAAC,CAAC,CAAA;IACF,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;IAClC,OAAO,IAAI,CAAA;AACb,CAAC;AAED,8BAA8B;AAC9B,SAAgB,qBAAqB,CAAC,UAAkB;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IACxB,IAAI,CAAC;QAAC,KAAK,EAAE,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACpC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACxB,OAAO,IAAI,CAAA;AACb,CAAC;AAED,oBAAoB;AACpB,SAAgB,sBAAsB;IACpC,OAAO,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;AAC1B,CAAC;AAED,kCAAkC;AAClC,qBAAU,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAA","sourcesContent":["import { getAdapter, type ConnectionConfig, type SiteDescriptor } from './reference-adapter.js'\nimport { TwinEngine, ingestCanonicalRecords, type CanonicalRecord } from '../../engine/index.js'\n\n/*\n * ์ปค๋„ฅํ„ฐ ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ ํ”ผ๋“œ ๊ฒฐ์„ (reference โ†’ live, ยง0 ํ”„๋ ˆ์ž„ โ‘  realityMode='mirror').\n * ํ๋ฆ„: adapter.openLiveFeed(cfg, site, records) โ†’ ingestCanonicalRecords(์ •๊ทœโ†’๋ด‰ํˆฌ) โ†’ TwinEngine.ingestLive(projector ๋ฏธ๋Ÿฌ).\n * ์ปค๋„ฅํ„ฐ๊ฐ€ \"๋ฒค๋” ์ด๋ฒคํŠธ โ†’ ์ •๊ทœ ๋ ˆ์ฝ”๋“œ\" ๋งคํ•‘์„ ์†Œ์œ (์ฝ”๋“œ)ํ•œ๋‹ค โ€” preset ๊ธฐ๋ฐ˜ startLiveFeed(operato-twin, http-get+jsonata)์™€\n * ๋Œ€์นญ์ด๋˜, ๋งคํ•‘ ์œ„์น˜๋งŒ ๋‹ค๋ฅด๋‹ค. ์‹ค ์‹œ์Šคํ…œ ์ „ํ™˜์€ connectionConfig.baseUrl ๊ต์ฒด๋ฟ(์ฝ”๋“œ ๊ฒฝ๋กœ ๋™์ผ).\n * ์ƒ๋ช…์ฃผ๊ธฐ: ์ธ์Šคํ„ด์Šค ์ •์ง€(TwinEngine.stop)์— ํ›…์œผ๋กœ ๋ฌถ์—ฌ ํ”ผ๋“œ๋„ ํ•จ๊ป˜ unsubscribe.\n */\n\n/** ํ™œ์„ฑ ๋ผ์ด๋ธŒ ํ”ผ๋“œ โ€” instanceId โ†’ unsubscribe(์–ด๋Œ‘ํ„ฐ openLiveFeed ๋ฐ˜ํ™˜). */\nconst feeds = new Map<string, () => void>()\n\n/**\n * ์ปค๋„ฅํ„ฐ ๋ผ์ด๋ธŒ ๊ธฐ๋™ โ€” ์–ด๋Œ‘ํ„ฐ openLiveFeed ๋ฅผ ์ธ์Šคํ„ด์Šค์— ๊ฒฐ์„ .\n * ๋ฐ˜ํ™˜: ๋ผ์ด๋ธŒ ๊ฒฐ์„  ์„ฑ๊ณต ์—ฌ๋ถ€(์–ด๋Œ‘ํ„ฐ๊ฐ€ openLiveFeed ๋ฏธ์ง€์›์ด๋ฉด false โ†’ ํ˜ธ์ถœ์ธก์ด sim ํด๋ฐฑ).\n */\nexport async function startReferenceLiveFeed(\n domainId: string,\n adapterType: string,\n cfg: ConnectionConfig,\n site: SiteDescriptor,\n instanceId: string\n): Promise<boolean> {\n const adapter = getAdapter(adapterType)\n if (!adapter?.openLiveFeed) return false\n\n const det = await TwinEngine.detail(domainId, instanceId)\n if (!det?.board) throw new Error(`instance \"${instanceId}\" not provisioned (no board) โ€” ingest master before live start`)\n\n // mirror ๋ชจ๋“œ ๊ธฐ๋™ โ€” ์ปค๋„ tick ์—†์ด projector ๊ฐ€ ์‹ค ์ด๋ฒคํŠธ๋ฅผ ๋ฏธ๋Ÿฌ(startLive ๊ฐ€ realityMode='mirror' ์„ค์ •).\n // ์‹œ๊ฐ ๊ธฐ์ค€์€ **๊ณต๊ฐ„**์ด ๊ฐ–๋Š”๋‹ค(ํ…Œ๋„ŒํŠธ ์•„๋‹˜) โ€” ๊ต๋Œ€์˜ HH:MM ์„ ์–ด๋А ๊ธฐ์ค€์œผ๋กœ ์ฝ๋‚˜.\n TwinEngine.startLive(instanceId, domainId, det.kind ?? 'wms', await TwinEngine.withSpaceTimeBase(det.board, domainId))\n\n stopReferenceLiveFeed(instanceId) // ์žฌ๊ธฐ๋™ ์‹œ ์ด์ „ ํ”ผ๋“œ ์ •๋ฆฌ\n const unsubscribe = adapter.openLiveFeed(cfg, site, (records: unknown[]) => {\n if (!TwinEngine.instances[instanceId]) {\n stopReferenceLiveFeed(instanceId) // ์ธ์Šคํ„ด์Šค ์‚ฌ๋ผ์ง€๋ฉด ์ž๊ฐ€ ์ •์ง€(์•ˆ์ „๋ง)\n return\n }\n const { accepted } = ingestCanonicalRecords(records as CanonicalRecord[], domainId, new Date().toISOString())\n if (accepted.length) TwinEngine.ingestLive(instanceId, accepted)\n })\n feeds.set(instanceId, unsubscribe)\n return true\n}\n\n/** ๋ผ์ด๋ธŒ ํ”ผ๋“œ ์ค‘์ง€(unsubscribe). */\nexport function stopReferenceLiveFeed(instanceId: string): boolean {\n const unsub = feeds.get(instanceId)\n if (!unsub) return false\n try { unsub() } catch { /* noop */ }\n feeds.delete(instanceId)\n return true\n}\n\n/** ํ™œ์„ฑ ํ”ผ๋“œ ๋ชฉ๋ก(๊ด€์ธก). */\nexport function listReferenceLiveFeeds(): string[] {\n return [...feeds.keys()]\n}\n\n/* ์ธ์Šคํ„ด์Šค ์ •์ง€ ์‹œ ํ”ผ๋“œ ์ž๋™ ์ •๋ฆฌ(์ƒ๋ช…์ฃผ๊ธฐ ๋Œ€์นญ). */\nTwinEngine.onStop(instanceId => stopReferenceLiveFeed(instanceId))\n"]}
1
+ {"version":3,"file":"reference-live.js","sourceRoot":"","sources":["../../../server/service/reference/reference-live.ts"],"names":[],"mappings":";;AAkBA,wDA4BC;AAGD,sDAMC;AAGD,wDAEC;AA5DD,iEAA+F;AAC/F,oDAAgG;AAEhG;;;;;;GAMG;AAEH,iEAAiE;AACjE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAA;AAE3C;;;GAGG;AACI,KAAK,UAAU,sBAAsB,CAC1C,QAAgB,EAChB,WAAmB,EACnB,GAAqB,EACrB,IAAoB,EACpB,UAAkB;IAElB,MAAM,OAAO,GAAG,IAAA,iCAAU,EAAC,WAAW,CAAC,CAAA;IACvC,IAAI,CAAC,OAAO,EAAE,YAAY;QAAE,OAAO,KAAK,CAAA;IAExC,MAAM,GAAG,GAAG,MAAM,qBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACzD,IAAI,CAAC,GAAG,EAAE,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,aAAa,UAAU,gEAAgE,CAAC,CAAA;IAEzH,wFAAwF;IACxF,uDAAuD;IACvD,qBAAU,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,IAAI,KAAK,EAAE,MAAM,qBAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEtH,qBAAqB,CAAC,UAAU,CAAC,CAAA,CAAC,iBAAiB;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,OAAkB,EAAE,EAAE;QACzE,IAAI,CAAC,qBAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;YAC3C,qBAAqB,CAAC,UAAU,CAAC,CAAA,CAAC,uBAAuB;YACzD,OAAM;QACR,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAA,iCAAsB,EAAC,OAA4B,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;QAC7G,IAAI,QAAQ,CAAC,MAAM;YAAE,qBAAU,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;IACF,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;IAClC,OAAO,IAAI,CAAA;AACb,CAAC;AAED,8BAA8B;AAC9B,SAAgB,qBAAqB,CAAC,UAAkB;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IACxB,IAAI,CAAC;QAAC,KAAK,EAAE,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACpC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACxB,OAAO,IAAI,CAAA;AACb,CAAC;AAED,oBAAoB;AACpB,SAAgB,sBAAsB;IACpC,OAAO,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;AAC1B,CAAC;AAED,kCAAkC;AAClC,qBAAU,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAA","sourcesContent":["import { getAdapter, type ConnectionConfig, type SiteDescriptor } from './reference-adapter.js'\nimport { TwinEngine, ingestCanonicalRecords, type CanonicalRecord } from '../../engine/index.js'\n\n/*\n * ์ปค๋„ฅํ„ฐ ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ ํ”ผ๋“œ ๊ฒฐ์„ (reference โ†’ live, ยง0 ํ”„๋ ˆ์ž„ โ‘  realityMode='mirror').\n * ํ๋ฆ„: adapter.openLiveFeed(cfg, site, records) โ†’ ingestCanonicalRecords(์ •๊ทœโ†’๋ด‰ํˆฌ) โ†’ TwinEngine.ingestLive(projector ๋ฏธ๋Ÿฌ).\n * ์ปค๋„ฅํ„ฐ๊ฐ€ \"๋ฒค๋” ์ด๋ฒคํŠธ โ†’ ์ •๊ทœ ๋ ˆ์ฝ”๋“œ\" ๋งคํ•‘์„ ์†Œ์œ (์ฝ”๋“œ)ํ•œ๋‹ค โ€” preset ๊ธฐ๋ฐ˜ startLiveFeed(operato-twin, http-get+jsonata)์™€\n * ๋Œ€์นญ์ด๋˜, ๋งคํ•‘ ์œ„์น˜๋งŒ ๋‹ค๋ฅด๋‹ค. ์‹ค ์‹œ์Šคํ…œ ์ „ํ™˜์€ connectionConfig.baseUrl ๊ต์ฒด๋ฟ(์ฝ”๋“œ ๊ฒฝ๋กœ ๋™์ผ).\n * ์ƒ๋ช…์ฃผ๊ธฐ: ์ธ์Šคํ„ด์Šค ์ •์ง€(TwinEngine.stop)์— ํ›…์œผ๋กœ ๋ฌถ์—ฌ ํ”ผ๋“œ๋„ ํ•จ๊ป˜ unsubscribe.\n */\n\n/** ํ™œ์„ฑ ๋ผ์ด๋ธŒ ํ”ผ๋“œ โ€” instanceId โ†’ unsubscribe(์–ด๋Œ‘ํ„ฐ openLiveFeed ๋ฐ˜ํ™˜). */\nconst feeds = new Map<string, () => void>()\n\n/**\n * ์ปค๋„ฅํ„ฐ ๋ผ์ด๋ธŒ ๊ธฐ๋™ โ€” ์–ด๋Œ‘ํ„ฐ openLiveFeed ๋ฅผ ์ธ์Šคํ„ด์Šค์— ๊ฒฐ์„ .\n * ๋ฐ˜ํ™˜: ๋ผ์ด๋ธŒ ๊ฒฐ์„  ์„ฑ๊ณต ์—ฌ๋ถ€(์–ด๋Œ‘ํ„ฐ๊ฐ€ openLiveFeed ๋ฏธ์ง€์›์ด๋ฉด false โ†’ ํ˜ธ์ถœ์ธก์ด sim ํด๋ฐฑ).\n */\nexport async function startReferenceLiveFeed(\n domainId: string,\n adapterType: string,\n cfg: ConnectionConfig,\n site: SiteDescriptor,\n instanceId: string\n): Promise<boolean> {\n const adapter = getAdapter(adapterType)\n if (!adapter?.openLiveFeed) return false\n\n const det = await TwinEngine.detail(domainId, instanceId)\n if (!det?.board) throw new Error(`instance \"${instanceId}\" not provisioned (no board) โ€” ingest master before live start`)\n\n // mirror ๋ชจ๋“œ ๊ธฐ๋™ โ€” ์ปค๋„ tick ์—†์ด projector ๊ฐ€ ์‹ค ์ด๋ฒคํŠธ๋ฅผ ๋ฏธ๋Ÿฌ(startLive ๊ฐ€ realityMode='mirror' ์„ค์ •).\n // ์‹œ๊ฐ ๊ธฐ์ค€์€ **๊ณต๊ฐ„**์ด ๊ฐ–๋Š”๋‹ค(ํ…Œ๋„ŒํŠธ ์•„๋‹˜) โ€” ๊ต๋Œ€์˜ HH:MM ์„ ์–ด๋А ๊ธฐ์ค€์œผ๋กœ ์ฝ๋‚˜.\n TwinEngine.startLive(instanceId, domainId, det.kind ?? 'wms', await TwinEngine.withSpaceTimeBase(det.board, domainId))\n\n stopReferenceLiveFeed(instanceId) // ์žฌ๊ธฐ๋™ ์‹œ ์ด์ „ ํ”ผ๋“œ ์ •๋ฆฌ\n const unsubscribe = adapter.openLiveFeed(cfg, site, (records: unknown[]) => {\n if (!TwinEngine.owns(domainId, instanceId)) {\n stopReferenceLiveFeed(instanceId) // ์ธ์Šคํ„ด์Šค ์‚ฌ๋ผ์ง€๋ฉด ์ž๊ฐ€ ์ •์ง€(์•ˆ์ „๋ง)\n return\n }\n const { accepted } = ingestCanonicalRecords(records as CanonicalRecord[], domainId, new Date().toISOString())\n if (accepted.length) TwinEngine.ingestLive(domainId, instanceId, accepted)\n })\n feeds.set(instanceId, unsubscribe)\n return true\n}\n\n/** ๋ผ์ด๋ธŒ ํ”ผ๋“œ ์ค‘์ง€(unsubscribe). */\nexport function stopReferenceLiveFeed(instanceId: string): boolean {\n const unsub = feeds.get(instanceId)\n if (!unsub) return false\n try { unsub() } catch { /* noop */ }\n feeds.delete(instanceId)\n return true\n}\n\n/** ํ™œ์„ฑ ํ”ผ๋“œ ๋ชฉ๋ก(๊ด€์ธก). */\nexport function listReferenceLiveFeeds(): string[] {\n return [...feeds.keys()]\n}\n\n/* ์ธ์Šคํ„ด์Šค ์ •์ง€ ์‹œ ํ”ผ๋“œ ์ž๋™ ์ •๋ฆฌ(์ƒ๋ช…์ฃผ๊ธฐ ๋Œ€์นญ). */\nTwinEngine.onStop(instanceId => stopReferenceLiveFeed(instanceId))\n"]}
@@ -311,7 +311,14 @@ export interface ReferenceMaster {
311
311
  * ์—†์œผ๋ฉด ์ปค๋„์€ ๋ ˆ๊ฑฐ์‹œ(ํ•˜๋“œ์ฝ”๋”ฉ) ํ๋ฆ„์œผ๋กœ ๋ˆ๋‹ค. ์ฆ‰ **ํ˜„์žฅ ๋ ˆ์‹œํ”ผ๋ฅผ ์ ์–ด๋„ ์ด ์ž๋ฆฌ์— ์‹ค๋ฆฌ์ง€ ์•Š์œผ๋ฉด
312
312
  * ์ปค๋„์€ ๊ทธ๊ฒƒ์„ ๋ณด์ง€ ๋ชปํ•œ๋‹ค** โ€” ์„ ์–ธ๊ณผ ์‹คํ–‰์ด ๊ฐˆ๋ผ์ง€๋Š” ์ง€์ ์ด๋ผ ์ž๋ฆฌ๋ฅผ ์—ฐ๋‹ค.
313
313
  */
314
- mesSpec?: unknown;
314
+ /**
315
+ * ์ƒ์‚ฐ ์„ ์–ธ โ€” `BoardDef.productionSpec` ์œผ๋กœ ํ†ต๊ณผํ•œ๋‹ค(ISA-95 OperationsSegment + BOM).
316
+ *
317
+ * ์˜ˆ์ „ ์ด๋ฆ„์€ `mesSpec` ์ด์—ˆ๋‹ค. ๋‹ด๊ธด ๊ฒƒ์€ MES ๋งŒ์˜ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ "์ž์žฌ๋ฅผ ์†Œ๋น„ํ•ด ์ž์žฌ๋ฅผ ์‚ฐ์ถœํ•˜๋Š”
318
+ * ๊ณต์ •" ์ด๊ณ , ์ด๋ฆ„์ด MES ์˜€๊ธฐ ๋•Œ๋ฌธ์— ์ฐฝ๊ณ  ํŠธ์œˆ์€ ์ด ์ž๋ฆฌ๋ฅผ ์“ธ ์ƒ๊ฐ์กฐ์ฐจ ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค(์œ ํ†ต๊ฐ€๊ณต ์ฐฝ๊ณ ๊ฐ€
319
+ * BOM ์„ ์„ค๋ช… ๋ฌธ์„œ์—๋งŒ ์ ์–ด ๋‘” ์ฑ„ ํ‚คํŠธ๋ฅผ ๋ชป ๋งŒ๋“œ๋Š” ํŠธ์œˆ์„ ๋งŒ๋“  ์›์ธ). ๊ทผ๊ฑฐ๋Š” ์ปค๋„ ๊ณ„์•ฝ ์ฃผ์„์—.
320
+ */
321
+ productionSpec?: unknown;
315
322
  /**
316
323
  * ์‚ฌ๋žŒ โ€” ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ฉด **์ธ์› ์ œ์•ฝ์ด ์—†๋Š” ํŠธ์œˆ**์ด ๋œ๋‹ค(์„ค๋น„๋งŒ ์žˆ์œผ๋ฉด ์–ธ์ œ๋‚˜ ๋Œ์•„๊ฐ€๋Š” ๊ณต์žฅ).
317
324
  * ๊ณต์ •์ด ์ธ์›์„ ์š”๊ตฌํ•˜๋Š”๋ฐ ์‚ฌ๋žŒ์ด ์—†์œผ๋ฉด ๊ทธ ์ž‘์—…์€ ์‹œ์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค โ€” ๊ทธ๊ฒƒ์ด ์‚ฌ์‹ค์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค.
@@ -336,7 +343,7 @@ export interface ReferenceMaster {
336
343
  export interface IngestedTwin {
337
344
  board: any;
338
345
  spaceContent: any;
339
- warnings: string[];
346
+ warnings: IngestWarning[];
340
347
  }
341
348
  /**
342
349
  * ๋งˆ์Šคํ„ฐ โ†’ ํŠธ์œˆ ๊ตฌ์กฐ ๋งคํ•‘(์ˆœ์ˆ˜). ๋…ธ๋“œํƒ€์ž…์„ ์นดํƒˆ๋กœ๊ทธ๋กœ ๊ฒ€์ฆ(๋ชจ๋ฅด๋Š” ํƒ€์ž…์€ warning, ๋ฒ„๋ฆฌ์ง„ ์•Š์Œ โ€” ๋ฐ˜์˜ ์šฐ์„ ).
@@ -356,4 +363,32 @@ export interface IngestedTwin {
356
363
  * ๊ทธ๋ ‡๊ฒŒ ๋ฐ”๊พธ๋ฉด ํŒ์ •์ด ์กฐ์šฉํžˆ ํ‹€๋ฆฐ๋‹ค.
357
364
  */
358
365
  export declare function utcOffsetOf(timezone?: string, at?: Date): number | undefined;
366
+ /** ์ธ์ œ์ŠคํŠธ๊ฐ€ ์•Œ๋ฆฌ๋Š” ํ•œ ๊ฐ€์ง€. */
367
+ export interface IngestWarning {
368
+ /** ์–ธ์–ด ์ค‘๋ฆฝ ์ฝ”๋“œ. ํ™”๋ฉด์€ `twin.ingest.<code>` ๋กœ ๋ Œ๋”ํ•œ๋‹ค. */
369
+ code: string;
370
+ /** ๋ฌธ์žฅ์— ๋ผ์šธ ๊ฐ’. ๋ฒˆ์—ญ์ด ์–ด์ˆœ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๊ฒŒ ์ด๋ฆ„์œผ๋กœ ๋„˜๊ธด๋‹ค. */
371
+ params?: Record<string, string | number>;
372
+ /** ์˜์–ด canonical ๋ฌธ์žฅ โ€” ๋กœ๊ทธยทํด๋ฐฑ์šฉ. ๋ฒˆ์—ญ์ด ์—†์–ด๋„ ์ฝ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. */
373
+ message: string;
374
+ }
375
+ /** ์ปค๋„ ์นดํƒˆ๋กœ๊ทธ๊ฐ€ ๋ชจ๋ฅด๋Š” ์ž๋ฆฌ ํƒ€์ž… โ€” ๊ทธ ์ž๋ฆฌ๋Š” ํ๋ฆ„์— ์ฐธ์—ฌํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค. */
376
+ export declare const unknownLocationType: (system: string, type: string, id: string) => IngestWarning;
377
+ /** ์‹œ๊ฐ„๋Œ€ ๋ฌธ์ž์—ด์„ ๋ชป ์ฝ์—ˆ๋‹ค โ€” ์‹œ๊ฐ ํ•ด์„์ด UTC ๋กœ ๋–จ์–ด์ง„๋‹ค(์กฐ์šฉํžˆ ํ˜„์ง€ ์‹œ๊ฐ์œผ๋กœ ๊ฐ€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค). */
378
+ export declare const unknownTimezone: (timezone: string) => IngestWarning;
379
+ /** ์ž‘์—… ์ •์˜์— ์†Œ์š”์‹œ๊ฐ„ยทํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋‹ค โ€” ์ปค๋„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋ˆ๋‹ค. */
380
+ export declare const operationWithoutDuration: (operation: string) => IngestWarning;
381
+ /** ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ‘œํ˜„์ด ์—†๋‹ค โ€” ํ˜„์žฅ์ด ํ™”๋ฉด์— ๋œจ์ง€ ์•Š๋Š”๋‹ค. */
382
+ export declare const noViewableRepresentation: () => IngestWarning;
383
+ /** ํ•ฉ์น˜๋Š” ๊ณต๊ฐ„์— ๊ฐ™์€ id ์˜ ๋žœ๋“œ๋งˆํฌ๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค โ€” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์ด ํ•˜๋‚˜๋กœ ์ ‘ํ˜”์„ ์ˆ˜ ์žˆ๋‹ค. */
384
+ export declare const landmarkIdsMerged: (spaceId: string, ids: readonly string[]) => IngestWarning;
385
+ /** ๋กœ๊ทธ ํ•œ ์ค„ โ€” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์˜์–ด canonical ๋ฌธ์žฅ์„ ์“ด๋‹ค. */
386
+ export declare const describeWarnings: (warnings: readonly IngestWarning[]) => string;
387
+ /**
388
+ * ์„œ๋ฒ„๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฑ„์šด ๋…ธ๋ธŒ๋“ค โ€” ์‚ฌ์šฉ์ž๊ฐ€ ์ค€ ์  ์—†๋Š” ๊ฐ’์œผ๋กœ ํŠธ์œˆ์ด ๋งŒ๋“ค์–ด์กŒ์Œ์„ ์•Œ๋ฆฐ๋‹ค.
389
+ *
390
+ * ์กฐ์šฉํžˆ ์ฑ„์šฐ๋ฉด ๋‚˜์ค‘์— "์™œ ์ด ์ˆ˜์น˜์ธ๊ฐ€" ๋ฅผ ์•„๋ฌด๋„ ๋‹ตํ•  ์ˆ˜ ์—†๋‹ค. ๋ง‰์„ ์ผ์€ ์•„๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’์€ ํ…œํ”Œ๋ฆฟ์ด
391
+ * ํ™•์‹ ์„ ๊ฐ–๊ณ  ์„ ์–ธํ•œ ๊ฐ’์ด๋‹ค) โ€” ๋‹ค๋งŒ ๋ฐํžŒ๋‹ค.
392
+ */
393
+ export declare const knobDefaultsFilled: (keys: readonly string[]) => IngestWarning;
359
394
  export declare function masterToTwin(master: ReferenceMaster, catalog?: any): IngestedTwin;
@@ -8,6 +8,7 @@
8
8
  * ์ขŒํ‘œยทrepresentations ๋Š” ํŠธ์œˆ ๊ณต๊ฐ„์ธต(๋ณด์™„/์ถ”๊ฐ€). ์‹ค ์‹œ์Šคํ…œ์ด ์ขŒํ‘œ๋ฅผ ์•ˆ ์ฃผ๋ฉด layout ์—†์ด ์œ„์ƒ๋งŒ ์ธ์ œ์ŠคํŠธ.
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.knobDefaultsFilled = exports.describeWarnings = exports.landmarkIdsMerged = exports.noViewableRepresentation = exports.operationWithoutDuration = exports.unknownTimezone = exports.unknownLocationType = void 0;
11
12
  exports.utcOffsetOf = utcOffsetOf;
12
13
  exports.masterToTwin = masterToTwin;
13
14
  /**
@@ -45,6 +46,55 @@ function utcOffsetOf(timezone, at = new Date()) {
45
46
  return undefined; // ์•Œ ์ˆ˜ ์—†๋Š” ์ด๋ฆ„ โ€” Intl ์ด ๋˜์ง„๋‹ค
46
47
  }
47
48
  }
49
+ /** ์ปค๋„ ์นดํƒˆ๋กœ๊ทธ๊ฐ€ ๋ชจ๋ฅด๋Š” ์ž๋ฆฌ ํƒ€์ž… โ€” ๊ทธ ์ž๋ฆฌ๋Š” ํ๋ฆ„์— ์ฐธ์—ฌํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค. */
50
+ const unknownLocationType = (system, type, id) => ({
51
+ code: 'unknown-location-type',
52
+ params: { system, type, id },
53
+ message: `"${type}" is not a known ${system} location type (${id}) โ€” the kernel may not include this location in the flow`
54
+ });
55
+ exports.unknownLocationType = unknownLocationType;
56
+ /** ์‹œ๊ฐ„๋Œ€ ๋ฌธ์ž์—ด์„ ๋ชป ์ฝ์—ˆ๋‹ค โ€” ์‹œ๊ฐ ํ•ด์„์ด UTC ๋กœ ๋–จ์–ด์ง„๋‹ค(์กฐ์šฉํžˆ ํ˜„์ง€ ์‹œ๊ฐ์œผ๋กœ ๊ฐ€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค). */
57
+ const unknownTimezone = (timezone) => ({
58
+ code: 'unknown-timezone',
59
+ params: { timezone },
60
+ message: `space timezone "${timezone}" is not a known IANA zone โ€” the twin will read times as UTC`
61
+ });
62
+ exports.unknownTimezone = unknownTimezone;
63
+ /** ์ž‘์—… ์ •์˜์— ์†Œ์š”์‹œ๊ฐ„ยทํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋‹ค โ€” ์ปค๋„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋ˆ๋‹ค. */
64
+ const operationWithoutDuration = (operation) => ({
65
+ code: 'operation-without-duration',
66
+ params: { operation },
67
+ message: `operation "${operation}" has no duration or parameters โ€” kernel defaults will be used`
68
+ });
69
+ exports.operationWithoutDuration = operationWithoutDuration;
70
+ /** ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ‘œํ˜„์ด ์—†๋‹ค โ€” ํ˜„์žฅ์ด ํ™”๋ฉด์— ๋œจ์ง€ ์•Š๋Š”๋‹ค. */
71
+ const noViewableRepresentation = () => ({
72
+ code: 'no-viewable-representation',
73
+ message: 'the space has no viewable representation (no representations and no geo) โ€” add one, or provide geo/board'
74
+ });
75
+ exports.noViewableRepresentation = noViewableRepresentation;
76
+ /** ํ•ฉ์น˜๋Š” ๊ณต๊ฐ„์— ๊ฐ™์€ id ์˜ ๋žœ๋“œ๋งˆํฌ๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค โ€” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์ด ํ•˜๋‚˜๋กœ ์ ‘ํ˜”์„ ์ˆ˜ ์žˆ๋‹ค. */
77
+ const landmarkIdsMerged = (spaceId, ids) => ({
78
+ code: 'landmark-ids-merged',
79
+ params: { spaceId, ids: ids.join(', '), count: ids.length },
80
+ message: `landmark ids already present in space "${spaceId}" โ€” merged: ${ids.join(', ')}`
81
+ });
82
+ exports.landmarkIdsMerged = landmarkIdsMerged;
83
+ /** ๋กœ๊ทธ ํ•œ ์ค„ โ€” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์˜์–ด canonical ๋ฌธ์žฅ์„ ์“ด๋‹ค. */
84
+ const describeWarnings = (warnings) => warnings.map(w => `${w.code}: ${w.message}`).join(' | ');
85
+ exports.describeWarnings = describeWarnings;
86
+ /**
87
+ * ์„œ๋ฒ„๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฑ„์šด ๋…ธ๋ธŒ๋“ค โ€” ์‚ฌ์šฉ์ž๊ฐ€ ์ค€ ์  ์—†๋Š” ๊ฐ’์œผ๋กœ ํŠธ์œˆ์ด ๋งŒ๋“ค์–ด์กŒ์Œ์„ ์•Œ๋ฆฐ๋‹ค.
88
+ *
89
+ * ์กฐ์šฉํžˆ ์ฑ„์šฐ๋ฉด ๋‚˜์ค‘์— "์™œ ์ด ์ˆ˜์น˜์ธ๊ฐ€" ๋ฅผ ์•„๋ฌด๋„ ๋‹ตํ•  ์ˆ˜ ์—†๋‹ค. ๋ง‰์„ ์ผ์€ ์•„๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’์€ ํ…œํ”Œ๋ฆฟ์ด
90
+ * ํ™•์‹ ์„ ๊ฐ–๊ณ  ์„ ์–ธํ•œ ๊ฐ’์ด๋‹ค) โ€” ๋‹ค๋งŒ ๋ฐํžŒ๋‹ค.
91
+ */
92
+ const knobDefaultsFilled = (keys) => ({
93
+ code: 'knob-defaults-filled',
94
+ params: { keys: keys.join(', '), count: keys.length },
95
+ message: `values you did not provide were filled from the template defaults: ${keys.join(', ')}`
96
+ });
97
+ exports.knobDefaultsFilled = knobDefaultsFilled;
48
98
  function masterToTwin(master, catalog) {
49
99
  const warnings = [];
50
100
  const known = catalog?.[master.system]?.locationTypes ?? [];
@@ -52,7 +102,7 @@ function masterToTwin(master, catalog) {
52
102
  const areaLocs = master.locations.filter(l => l.role === 'area' || l.role === 'both');
53
103
  const locations = locationEntries.map(l => {
54
104
  if (known.length && !known.includes(l.type))
55
- warnings.push(`unknown ${master.system} location type "${l.type}" (${l.id}) โ€” ์นดํƒˆ๋กœ๊ทธ์— ์—†์Œ`);
105
+ warnings.push((0, exports.unknownLocationType)(master.system, l.type, l.id));
56
106
  // gs1Id(์ •์‹ ์ •์ฒด์„ฑ)๋ฅผ ๋ณด๋“œ ๋…ธ๋“œ๋กœ ํ†ต๊ณผ โ€” ๊ฒฐํ•ฉ(tag)/์ถ”์ ์ด GS1 ๋กœ(ยงJ). ๋กœ์ปฌ id ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€(name/xref).
57
107
  return { id: l.id, type: l.type, capacity: l.capacity ?? 0, ...(l.parallelism !== undefined ? { parallelism: l.parallelism } : {}), ...(l.level ? { level: l.level } : {}), parentId: l.parentId, gs1Id: l.gs1Id };
58
108
  });
@@ -79,7 +129,7 @@ function masterToTwin(master, catalog) {
79
129
  */
80
130
  const utcOffsetMinutes = utcOffsetOf(master.space.timezone);
81
131
  if (master.space.timezone && utcOffsetMinutes === undefined) {
82
- warnings.push(`space timezone "${master.space.timezone}" is not a known IANA zone โ€” the twin will read times as UTC`);
132
+ warnings.push((0, exports.unknownTimezone)(String(master.space.timezone)));
83
133
  }
84
134
  /*
85
135
  * ์˜คํผ๋ ˆ์ด์…˜ ๋ช…์„ธ๋ฅผ board ์— ํ†ต๊ณผ์‹œํ‚จ๋‹ค โ€” ์ปค๋„์ด `loadOperations` ๋กœ ์†Œ๋น„ํ•œ๋‹ค(BoardDef ํ™•์žฅ ํ•„๋“œ,
@@ -89,7 +139,7 @@ function masterToTwin(master, catalog) {
89
139
  if (operations?.length) {
90
140
  for (const o of operations) {
91
141
  if (!o.duration && !o.parameters?.length)
92
- warnings.push(`operation "${o.key}" has no duration or parameters โ€” kernel defaults will be used`);
142
+ warnings.push((0, exports.operationWithoutDuration)(o.key));
93
143
  }
94
144
  }
95
145
  /* ์‚ฌ๋žŒ๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๋“ฑ๊ธ‰ยท๊ต๋Œ€ ๊ทธ๋Œ€๋กœ ์ปค๋„๊นŒ์ง€ ๊ฐ„๋‹ค(๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค). */
@@ -109,7 +159,7 @@ function masterToTwin(master, catalog) {
109
159
  const board = {
110
160
  locations, equipment, layout, spaceId,
111
161
  /* ์ƒ์‚ฐ ์ •์˜๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค(์ปค๋„์ด ๊ทธ๋Œ€๋กœ ์†Œ๋น„ํ•œ๋‹ค). */
112
- ...(master.mesSpec ? { mesSpec: master.mesSpec } : {}),
162
+ ...(master.productionSpec ? { productionSpec: master.productionSpec } : {}),
113
163
  ...(materialDefinitions?.length ? { materialDefinitions } : {}),
114
164
  ...(master.materialClasses?.length ? { materialClasses: master.materialClasses } : {}),
115
165
  ...(utcOffsetMinutes !== undefined ? { utcOffsetMinutes } : {}),
@@ -135,7 +185,7 @@ function masterToTwin(master, catalog) {
135
185
  ? [{ id: 'r-map', type: 'map', name: '์œ„์„ฑ ์ง€๋„', primary: true, center: { lat: geo.lat, lon: geo.lon }, zoom: 17 }]
136
186
  : [];
137
187
  if (representations.length === 0) {
138
- warnings.push('space has no viewable representation (no representations and no geo) โ€” add one manually or provide geo/board');
188
+ warnings.push((0, exports.noViewableRepresentation)());
139
189
  }
140
190
  const spaceContent = {
141
191
  width: master.space.width, depth: master.space.depth, unit: master.space.unit ?? 'm',
@@ -1 +1 @@
1
- {"version":3,"file":"reference-master.js","sourceRoot":"","sources":["../../../server/service/reference/reference-master.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Face2 ๋งˆ์Šคํ„ฐ ์ธ์ œ์ŠคํŠธ(ADR-0018 ๋ฐ˜์˜ ๋ชจ๋“œ) โ€” ๋ ˆํผ๋Ÿฐ์Šค ์‹œ์Šคํ…œ(์‹ค WMS/YMS/MES ๋˜๋Š” ๊ฐ€์ƒ ๋ ˆํผ๋Ÿฐ์Šค)์˜\n * ๋งˆ์Šคํ„ฐ๋ฅผ ์ฝ์–ด ํŠธ์œˆ ๊ตฌ์กฐ(BoardDef) + ๊ณต๊ฐ„(Space content)์„ ์ƒ์„ฑ. ์†๋ฐฐ์„ ์ด ์•„๋‹ˆ๋ผ ์ธ์ œ์ŠคํŠธ๋กœ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ํ๋ฅธ๋‹ค.\n *\n * ๊ทœ์œจ(ADR-0018): ๋„๋ฉ”์ธ ํƒ€์ž…(location.type=๋…ธ๋“œ์šฉ)์€ ์ปค๋„ ์นดํƒˆ๋กœ๊ทธ ์–ดํœ˜๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜์˜(๋ฐœ๋ช… ๊ธˆ์ง€).\n * location ์€ role ๋กœ ๋…ธ๋“œ(์šด์˜์ )ยทarea(๊ณต๊ฐ„์˜์—ญ)ยทboth ๋ฅผ ๊ตฌ๋ถ„ โ€” ๋…ธ๋“œโ†’BoardDef, areaโ†’Space.areas.\n * ์ขŒํ‘œยทrepresentations ๋Š” ํŠธ์œˆ ๊ณต๊ฐ„์ธต(๋ณด์™„/์ถ”๊ฐ€). ์‹ค ์‹œ์Šคํ…œ์ด ์ขŒํ‘œ๋ฅผ ์•ˆ ์ฃผ๋ฉด layout ์—†์ด ์œ„์ƒ๋งŒ ์ธ์ œ์ŠคํŠธ.\n */\n\nimport type { EquipmentLevel, WorkCalendarEntry } from '@operato/twin-kernel'\n\nexport interface RefLocation {\n id: string\n type: string // ๋…ธ๋“œ๋Š” ์ปค๋„ ๋…ธ๋“œํƒ€์ž…(dock/storage/yard-slotโ€ฆ), area ๋Š” ๊ณต๊ฐ„ region ํƒ€์ž…\n name?: string\n role: 'location' | 'area' | 'both'\n parentId?: string\n /** ์ €์žฅ ์šฉ๋Ÿ‰ โ€” ์ด ์ž๋ฆฌ์— ๋™์‹œ์— ๋†“์ผ ์ˆ˜ ์žˆ๋Š” ๋ฌผํ’ˆ ์ˆ˜. */\n capacity?: number\n /**\n * ๋™์‹œ ์ฒ˜๋ฆฌ ์ˆ˜ โ€” ์ด ์ž๋ฆฌ์—์„œ ํ•œ ๋ฒˆ์— ์ง„ํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ์ˆ˜. **์ €์žฅ ์šฉ๋Ÿ‰๊ณผ ๋‹ค๋ฅธ ์ถ•**์ด๋‹ค\n * (์ž์žฌ๋ฅผ 20๊ฐœ ์Œ“์•„ ๋‘๋Š” ์ ˆ๋‹จ ์Šคํ…Œ์ด์…˜์ด ํ•œ ๋ฒˆ์— ํ•œ ๋Œ€๋งŒ ๊นŽ๋Š”๋‹ค). ๋ฏธ์ง€์ •=์ œ์•ฝ ์—†์Œ.\n */\n parallelism?: number\n /**\n * **ISA-95 ์„ค๋น„ ๊ณ„์ธต ๋‹จ๊ณ„** โ€” `EquipmentLevel` ์—ด๊ฑฐ๊ฐ’(`ProductionLine`ยท`StorageZone`ยท`WorkCenter`โ€ฆ).\n *\n * `type` ์€ ํ˜„์žฅ์˜ ๋‚ฑ๋ง(`paint-booth`)์ด๊ณ  ์ด๊ฒƒ์€ **ํ‘œ์ค€์ด ์ •ํ•œ ์—ญํ• **์ด๋‹ค. ๋‘˜์€ ๋‹ค๋ฅธ ์ถ•์ด๋ผ ํ•จ๊ป˜ ๋“ ๋‹ค โ€”\n * ์—ฐ๋™ยท์ง‘๊ณ„๋Š” ํ‘œ์ค€ ์ถ•์œผ๋กœ, ํ™”๋ฉด์€ ํ˜„์žฅ ๋‚ฑ๋ง๋กœ. ๋ฏธ์ง€์ •์ด๋ฉด ๊ทธ ์ž๋ฆฌ์˜ ํ‘œ์ค€ ์—ญํ• ์„ ์•„์ง ๋ชจ๋ฅธ๋‹ค๋Š” ๋œป์ด๊ณ ,\n * ์ง์ž‘ํ•ด ์ฑ„์šฐ์ง€ ์•Š๋Š”๋‹ค.\n */\n level?: EquipmentLevel\n footprint?: { x: number; y: number; w: number; h: number } // ์žˆ์œผ๋ฉด area ๊ธฐํ•˜ + ๋…ธ๋“œ ์ค‘์‹ฌ์ขŒํ‘œ\n gs1Id?: string // ์ •์‹ GS1 ์ •์ฒด์„ฑ(ยงJ) โ€” ์œ„์น˜=SGLN. ๊ฒฐํ•ฉ(tag)/์ถ”์  canonical id. ๋ฐ›์•„๋“ค์ด๊ธฐ ๊ฒฝ๊ณ„์„œ ๋ถ€์—ฌ(๋กœ์ปฌ id=name/xref ๋กœ ๋ณด์กด).\n}\n\n/**\n * ์„ค๋น„ ์†์„ฑ โ€” **ISA-95 `EquipmentSpecificationProperty`(`OpEquipmentSpecificationPropertyType`) 1:1.**\n * ๊ทธ ํƒ€์ž…๋„ `ID` + `Value`(`ValueString`ยท`DataType`ยท`UnitOfMeasure`) ์ด๋ฏ€๋กœ ๊ณต์ • ๋ชจ์ˆ˜์™€ ๊ฐ™์€ ๋ชจ์–‘์ด๋‹ค.\n *\n * ๋‹จ์œ„ ์ฝ”๋“œ๋Š” **UN/CEFACT ๊ถŒ๊ณ  20 ๊ณตํ†ต์ฝ”๋“œ**(EPCIS `uom` ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ณ„): ์†๋„๋Š” `MTS`(metre per\n * second) ๋˜๋Š” `KMH`(kilometre per hour). ์ฝ”๋“œ๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ๋ฐœ๋ช…ํ•˜์ง€ ์•Š๋Š”๋‹ค.\n */\n/**\n * ์ž์› ์†์„ฑ โ€” **์ปค๋„ `ResourceProperty` ์™€ ๊ฐ™์€ ๋ชจ์–‘**์ด๊ณ , ๊ทธ ๋ชจ์–‘์€ ISA-95 ๊ฐ€ ์„ธ ์ž์›์— ๋˜‘๊ฐ™์ด\n * ์ •์˜ํ•œ ๊ฒƒ์ด๋‹ค(`EquipmentPropertyType` ยท `PersonPropertyType` ยท `PhysicalAssetPropertyType`).\n *\n * ๊ทธ๋ž˜์„œ ์ž์›๋งˆ๋‹ค ๋‹ค๋ฅธ ์†์„ฑ ํƒ€์ž…์„ ๋‘์ง€ ์•Š๋Š”๋‹ค โ€” ์˜ˆ์ „์—๋Š” ์„ค๋น„๋งŒ ์†์„ฑ์„ ๊ฐ€์กŒ๊ณ (RefEquipmentProperty),\n * ์ธ์›ยท์ž์‚ฐ์— ๋ถ™๋Š” ์‚ฌ์‹ค์€ **์‹ค์„ ์ž๋ฆฌ๊ฐ€ ์—†์–ด์„œ ๋“ค์–ด์˜ค์ง€ ๋ชปํ–ˆ๋‹ค.**\n */\nexport interface RefResourceProperty {\n id: string\n description?: string\n value?: string\n /** ํ‘œ์ค€ `Value.DataType`. */\n dataType?: string\n /** ํ‘œ์ค€ `Value.UnitOfMeasure` โ€” UN/CEFACT ๊ณตํ†ต์ฝ”๋“œ. ๋ฌผ๋ฆฌ๋Ÿ‰์— ๋‹จ์œ„๊ฐ€ ์—†์œผ๋ฉด ์†Œ๋น„์ฒ˜๊ฐ€ ๊ฑฐ์ ˆํ•œ๋‹ค. */\n uom?: string\n /** ํ•˜์œ„ ์†์„ฑ(์žฌ๊ท€) โ€” ํ‘œ์ค€ `<X>PropertyChild`. */\n children?: RefResourceProperty[]\n /** ์ด ๊ฐœ์ฒด ์†์„ฑ์ด ๊ตฌ์ฒดํ™”ํ•˜๋Š” ๋“ฑ๊ธ‰ ์†์„ฑ โ€” ํ‘œ์ค€ `<X>ClassPropertyID`. */\n classPropertyId?: string\n}\n\n/** ์˜› ์ด๋ฆ„ โ€” ์„ค๋น„ ์ „์šฉ์ด๋˜ ์‹œ์ ˆ์˜ ๋ณ„์นญ(์†Œ๋น„์ฒ˜ ํ˜ธํ™˜). ์‹ ๊ทœ ์†Œ์‹ฑ์€ `RefResourceProperty`. */\nexport type RefEquipmentProperty = RefResourceProperty\n\n/**\n * ์ž์› **๋“ฑ๊ธ‰ ์ •์˜** โ€” ์ปค๋„ `ResourceClassDef` ์™€ ๊ฐ™์€ ๋ชจ์–‘์ด๊ณ , ๊ทธ ๋ชจ์–‘์€ ISA-95 ๊ฐ€ ์„ธ ์ž์›์— ๋˜‘๊ฐ™์ด\n * ์ •์˜ํ•œ ๊ฒƒ์ด๋‹ค(`PersonnelClassType`ยท`EquipmentClassType`ยท`PhysicalAssetClassType`).\n *\n * ์™œ ํ•„์š”ํ•œ๊ฐ€: ์› ์‹œ์Šคํ…œ์€ ๋“ฑ๊ธ‰ **์ฒด๊ณ„**๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค(\"6์ถ• ์šฉ์ ‘ ์ž๊ฒฉ์ž\" ๋Š” \"์šฉ์ ‘ ์ž๊ฒฉ์ž\" ์ด๊ณ , ๊ทธ๊ฒƒ์€\n * \"์ƒ์‚ฐ์ง\" ์ด๋‹ค). ๊ทธ ์ฒด๊ณ„๊ฐ€ ๋“ค์–ด์˜ฌ ์ž๋ฆฌ๊ฐ€ ์—†์œผ๋ฉด ์š”๊ตฌ์™€ ์†Œ์†์ด **๋ฌธ์ž์—ด์ด ๋˜‘๊ฐ™์„ ๋•Œ๋งŒ** ๋งž์•„,\n * ํ˜„์žฅ์—์„œ๋Š” ๋˜๋Š” ๋ฐฐ์ •์ด ๋ชจ๋ธ์—์„œ ๋ง‰ํžŒ๋‹ค.\n */\nexport interface RefResourceClass {\n id: string\n description?: string\n /** ์ƒ์œ„ ๋“ฑ๊ธ‰๋“ค โ€” ํ‘œ์ค€ `<X>ClassBaseID`(๋ณต์ˆ˜ = ๋‹ค์ค‘ ์ƒ์†). */\n baseIds?: string[]\n properties?: RefResourceProperty[]\n testSpecificationIds?: string[]\n /** ์œ ํšจ ๊ธฐ๊ฐ„(ISO) โ€” ํ‘œ์ค€ `EffectiveStartDate`/`EffectiveEndDate`. ๋ฐ–์ด๋ฉด ์ž๊ฒฉ์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š๋Š”๋‹ค. */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\nexport interface RefEquipment {\n id: string\n kind: string\n homeLocationId: string\n mtbfMs?: number // ํ‰๊ท  ๊ณ ์žฅ ๊ฐ„๊ฒฉ(ํ™•๋ฅ ์  ๊ณ ์žฅ) โ€” ์ง€์ • ์‹œ ์ปค๋„์ด breakdown ์‹œ๋ฎฌ โ†’ ์ฃผ๋ชฉ(๊ณ ์žฅ) ๋ฐœ์ƒ\n mttrMs?: number // ํ‰๊ท  ์ˆ˜๋ฆฌ ์‹œ๊ฐ„\n gs1Id?: string // ์ •์‹ GS1 ์ •์ฒด์„ฑ(ยงJ) โ€” ์„ค๋น„=GIAI.\n /**\n * ๊ต๋Œ€(๊ฐ€๋™์‹œ๊ฐ„) โ€” ์ด ์‹œ๊ฐ„๋Œ€์—๋งŒ ๋ฐฐ์ •๋œ๋‹ค. `startHour <= endHour` ๋ฉด ๊ฐ™์€ ๋‚ , ๋„˜์–ด๊ฐ€๋ฉด ์•ผ๊ฐ„(22โ†’6).\n * ๋ฏธ์ง€์ •=24์‹œ๊ฐ„ ๊ฐ€์šฉ. ๊ต๋Œ€ ๋ฐ– ์ž์›์€ ๊ณ ์žฅยท๊ณ„ํš์ •์ง€์™€ **๊ตฌ๋ณ„๋˜๋Š” ์ด์œ **๋กœ ์‰ฐ๋‹ค(์ƒํƒœ์— ๋“œ๋Ÿฌ๋‚œ๋‹ค).\n */\n window?: { startHour: number; endHour: number }\n /**\n * ๊ทผ๋ฌด ์บ˜๋ฆฐ๋” โ€” ํ‘œ์ค€ `WorkCalendarEntry`(๋ณต์ˆ˜). ์žˆ์œผ๋ฉด `window` ๋ณด๋‹ค ์ด๊ฒƒ์„ ๋ณธ๋‹ค.\n *\n * ์ถ•์„ ํ”„๋ ˆ์ž„์›Œํฌ `@things-factory/work-shift` ์˜ `WorkShift`(`fromDate`ยท`fromTime`ยท`toDate`ยท`toTime`)์™€\n * ๋งž์ถฐ ๋‘์—ˆ๋‹ค โ€” ๊ทธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ต๋Œ€์˜ ์ •๋ณธ์œผ๋กœ ๊ฒฐ์„ ํ•  ๋•Œ ์ง์„  ๋งคํ•‘์ด ๋˜๊ฒŒ. **์•„์ง ๊ฒฐ์„ ํ•˜์ง€ ์•Š์•˜๋‹ค**:\n * ๊ทธ ์—”ํ‹ฐํ‹ฐ์—๋Š” ์ž์› ์—ฐ๊ฒฐ๊ณผ ๋น„๊ทผ๋ฌด(ํœด์ผ)๊ฐ€ ์—†์–ด ํ™•์žฅ์ด ํ•จ๊ป˜ ํ•„์š”ํ•˜๊ณ , operato-twin ์˜ ์˜์กด์„ฑ ์ถ”๊ฐ€๋Š”\n * ์•ฑ ์•„ํ‚คํ…์ฒ˜ ๊ฒฐ์ •์ด๋‹ค(์ปค๋ฒ„๋ฆฌ์ง€ ยง4-7 ์— ๊ฒฐ์„  ์ง€์ ์œผ๋กœ ๊ธฐ๋ก).\n */\n workCalendar?: WorkCalendarEntry[]\n /**\n * ์„ค๋น„ ์†์„ฑ(์†๋„ ๋“ฑ) โ€” ์—†์œผ๋ฉด **์ด๋™์‹œ๊ฐ„์„ ๊ฑฐ๋ฆฌ์—์„œ ๊ณ„์‚ฐํ•  ์ˆ˜ ์—†๋‹ค**(์†๋„ ์—†์ด ๊ฑฐ๋ฆฌ๋งŒ์œผ๋กœ๋Š” ์‹œ๊ฐ„์ด\n * ์•ˆ ๋‚˜์˜จ๋‹ค). ๊ทธ๋•Œ๋Š” ์ปค๋„ ์ƒ์ˆ˜๋กœ ๋–จ์–ด์ง€๊ณ  ๊ทธ ์‚ฌ์‹ค์ด `specCoverage()` ์— ๋‚จ๋Š”๋‹ค.\n */\n properties?: RefResourceProperty[]\n /** ์ ๊ฒฉ์„ ๊ฒ€์ฆํ•œ ์‹œํ—˜ ๋ช…์„ธ๋“ค โ€” ํ‘œ์ค€ `TestSpecificationID`(๊ต์ • ๋“ฑ). */\n testSpecificationIds?: string[]\n /**\n * ์œ ํšจ ๊ธฐ๊ฐ„ โ€” **ํ‘œ์ค€ `EffectiveStartDate` / `EffectiveEndDate`**(๊ฐœ์ฒด ํƒ€์ž… ์…‹ ๋ชจ๋‘์— ์žˆ๋‹ค).\n *\n * ์—†์œผ๋ฉด **ํ๊ธฐํ•œ ๊ฒƒ์ด ์˜๊ตฌํžˆ ์‚ด์•„ ์žˆ๋‹ค**: ๋ฐฐ์ • ๋Œ€์ƒ์— ๋‚จ๊ณ , ๊ฐ€์šฉ ์ˆ˜์— ๋“ค์–ด๊ฐ€๊ณ , ํ™”๋ฉด์— ๋œฌ๋‹ค.\n * ๋„์ž… ์˜ˆ์ •์ธ ๊ฒƒ์€ ๋ฐ˜๋Œ€๋กœ ์˜ค๋Š˜๋ถ€ํ„ฐ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ๊ธฐ๊ฐ„ ๋ฐ–์ด๋ฉด ์ปค๋„์ด ๊ทธ ์‹œ๊ฐ์˜ ๋ชจ๋ธ์—์„œ\n * ๋นผ๊ณ  **์ด์œ ๋ฅผ ๋‹ฌ์•„ ๋‚จ๊ธด๋‹ค**(`effectivity: 'not-yet' | 'expired'`) โ€” ์กฐ์šฉํžˆ ์ง€์šฐ์ง€ ์•Š๋Š”๋‹ค.\n */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\n/**\n * ๊ณต์ • ๋ชจ์ˆ˜ โ€” ์ปค๋„ `OperationParameter`(= ISA-95 `ParameterSpecification`/`ParameterType`) ์™€ **๊ฐ™์€ ๋ชจ์–‘**.\n * ์ด๋ฆ„์„ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค: ์ธ์ œ์ŠคํŠธ ๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๊ฐ€ ๊ฐˆ๋ฆฌ๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฐฉ์–ธ์ด ์ƒ๊ธด๋‹ค.\n * ID ์–ดํœ˜์˜ ์ •๋ณธ์€ ์ปค๋„ `OP_PARAM`(ํ‘œ์ค€์ด ํŒŒ๋ผ๋ฏธํ„ฐ ID ๋ฅผ ์ •ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ•œ ๊ณณ์—์„œ ์ •ํ•œ๋‹ค).\n */\nexport interface RefOperationParameter {\n id: string\n /** ISA-95 `Value.ValueString` โ€” ํ‘œ์ค€์ด ๋ฌธ์ž์—ด๋กœ ์‹ฃ๋Š”๋‹ค. ๊ธฐ๊ฐ„ ๋ชจ์ˆ˜๋Š” ISO 8601(`PT8M`). */\n value: string\n /** ISA-95 `Value.UnitOfMeasure`. ๋ฌด์ฐจ์›(๋น„์œจ)์ด๋ฉด ์ƒ๋žต. */\n uom?: string\n}\n\n/**\n * ๊ณต์ •์˜ ์ž์žฌ ์š”๊ตฌยท์‚ฐ์ถœ โ€” **ISA-95 `OperationsSegment.MaterialSpecification`** ๊ณผ ๊ฐ™์€ ๋ชจ์–‘.\n * ์ธ์›ยท์„ค๋น„ยท์ž์‚ฐ ๋ช…์„ธ์™€ ๊ฐ™์€ ์ž๋ฆฌ์— ์žˆ์–ด์•ผ 4๋Œ€ ์ž์›์ด ๋Œ€์นญ์ด ๋œ๋‹ค(์ž์žฌ๋งŒ ๋น ์ ธ ์žˆ์—ˆ๋‹ค).\n */\nexport interface RefOpMaterialSpecification {\n id?: string\n /** ํ’ˆ๋ชฉ ๋“ฑ๊ธ‰์œผ๋กœ ์š”๊ตฌ โ€” ํ‘œ์ค€ `MaterialClassID`. */\n materialClass?: string\n /** ํŠน์ • ํ’ˆ๋ชฉ์œผ๋กœ ์š”๊ตฌ โ€” ํ‘œ์ค€ `MaterialDefinitionID`. */\n materialDefinition?: string\n /** ํ‘œ์ค€ `MaterialUse` โ€” ์ด ๊ณต์ •์—์„œ์˜ ์“ฐ์ž„. */\n use: 'consumed' | 'produced' | 'consumable'\n /** ํ‘œ์ค€ `Quantity`. ๋‹จ์œ„ ๋ฏธ์ง€์ •์ด๋ฉด ๊ฐœ์ˆ˜. */\n quantity: number\n uom?: string\n}\n\n/** ์†Œ์š”์‹œ๊ฐ„ ๋ณ€๋™ โ€” **ํ‘œ์ค€ ๋ฐ– ํ™•์žฅ**(ISA-95 Duration ์€ ์Šค์นผ๋ผ). ์ปค๋„ `DurationVariability` ์™€ ๋™ํ˜•. */\nexport interface RefOperationVariability {\n distribution: 'constant' | 'exponential' | 'uniform' | 'triangular'\n min?: string\n max?: string\n mode?: string\n}\n\n/**\n * ์˜คํผ๋ ˆ์ด์…˜ ๋ช…์„ธ โ€” ISA-95 `OperationsSegment`. ์ปค๋„ `OperationDef` ์™€ ํ•„๋“œ ์ด๋ฆ„์ด 1:1์ด๋‹ค.\n *\n * **์ด๊ฒƒ์ด ์—†์œผ๋ฉด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์˜ ์‹œ๊ฐ„์€ ์šฐ๋ฆฌ๊ฐ€ ์ฝ”๋“œ์— ๋ฐ•์•„ ๋‘” ์ƒ์ˆ˜๋‹ค.** ์› ์‹œ์Šคํ…œ(๋˜๋Š” ๊ฐ€์ƒ ๋ ˆํผ๋Ÿฐ์Šค)์ด\n * ๊ณต์ •๋ณ„ ์†Œ์š”ยท๋ณ€๋™ยท์ˆ˜์œจ์„ ๋งํ•ด ์ค˜์•ผ ์˜ˆ์ธก์ด ๊ทธ ํ˜„์žฅ์˜ ์˜ˆ์ธก์ด ๋œ๋‹ค. ์ฃผ์ง€ ์•Š์œผ๋ฉด ์ปค๋„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ\n * ๊ตด๋Ÿฌ๊ฐ€๊ณ , **๊ธฐ๋ณธ๊ฐ’์„ ์ผ๋‹ค๋Š” ์‚ฌ์‹ค์€ ์ปค๋„ `specCoverage()` ๊ฐ€ ๋ฐํžŒ๋‹ค**(์กฐ์šฉํžˆ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋Š”๋‹ค).\n */\nexport interface RefOperation {\n /** ์ž‘์—… ์ข…๋ฅ˜ ํ‚ค โ€” ์ปค๋„ `FlowTask.kind` ์™€ ๊ฐ™์€ ๊ฐ’์ด์–ด์•ผ ๋ช…์„ธ๊ฐ€ ๊ทธ ์ž‘์—…์— ๋ถ™๋Š”๋‹ค. */\n key: string\n label: string\n intent: 'transport' | 'process' | 'dwell'\n locationType?: string\n resourceType?: string\n bizStep?: string\n /** ISA-95 `OperationsSegment.Duration` โ€” ISO 8601 ๊ธฐ๊ฐ„(`PT12M`). */\n duration?: string\n variability?: RefOperationVariability\n parameters?: RefOperationParameter[]\n /**\n * ํ•„์š” ์ธ์› โ€” ISA-95 `PersonnelSpecification`(`PersonnelClassID` + `Quantity`) 1:1.\n * ์—†์œผ๋ฉด ์‚ฌ๋žŒ ์—†์ด ๋„๋Š” ๊ณต์ •์ด๋‹ค(์„ค๋น„๋งŒ ์žก๋Š”๋‹ค).\n */\n personnelSpecification?: { personnelClass?: string; quantity: number }[]\n /** ํ•„์š” ๋ฌผ๋ฆฌ ์ž์‚ฐ โ€” ISA-95 `PhysicalAssetSpecification`(๋“ฑ๊ธ‰ + ์ˆ˜๋Ÿ‰). ๋นˆ ํŒ”๋ ˆํŠธ๊ฐ€ ์—†์œผ๋ฉด ๋ชป ๋‚˜๊ฐ„๋‹ค. */\n physicalAssetSpecification?: { assetClass?: string; quantity: number }[]\n /**\n * ํ•„์š”ยท์‚ฐ์ถœ ์ž์žฌ โ€” ISA-95 `MaterialSpecification`. **4๋Œ€ ์ž์› ์ค‘ ์ž์žฌ๋งŒ ์ด ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค** โ€”\n * ๊ทธ๋ž˜์„œ ๋ถ€ํ’ˆ์ด ๋–จ์–ด์ ธ ๋ผ์ธ์ด ์„œ๋Š” ์ƒํ™ฉ์ด ์˜ˆ์ธก์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜๋‹ค.\n * BOM ์˜ \"๋ช‡ ๊ฐœ\" ๋Š” ์—ฌ๊ธฐ๋‹ค(ํ’ˆ๋ชฉ ์ •์˜์˜ ์กฐ๋ฆฝ ๊ตฌ์กฐ์—๋Š” ์ˆ˜๋Ÿ‰์ด ์—†๋‹ค โ€” 1์ฐจ ์ถœ์ฒ˜ ํ™•์ธ).\n */\n materialSpecification?: RefOpMaterialSpecification[]\n}\n\n/**\n * ์‚ฌ๋žŒ โ€” **ISA-95 `Person`.** ์„ค๋น„์™€ ๋ณ„๊ฐœ ์ž์›์ด๋‹ค(๊ณ ์žฅยท์„ค๋น„ํšจ์œจ์ด ์•„๋‹ˆ๋ผ ๋“ฑ๊ธ‰ยท๊ต๋Œ€๋กœ ์‚ฐ๋‹ค).\n * `personnelClass` ๊ฐ€ ISA-95 `PersonnelClassID` โ€” ๊ณต์ •์€ ํŠน์ •์ธ์ด ์•„๋‹ˆ๋ผ **๋“ฑ๊ธ‰์œผ๋กœ** ์ธ์›์„ ์š”๊ตฌํ•œ๋‹ค.\n */\nexport interface RefPerson {\n id: string\n name?: string\n /**\n * ์†ํ•œ ๋“ฑ๊ธ‰๋“ค โ€” **ํ‘œ์ค€ `Person.PersonnelClassID`, `maxOccurs=\"unbounded\"`**.\n * ๋ณต์ˆ˜์ธ ๊ฒƒ์ด ํ‘œ์ค€์ด๊ณ  ๊ทธ๊ฒƒ์ด ์ž๊ฒฉ ํ‘œํ˜„์ด๋‹ค: ํ•œ ์‚ฌ๋žŒ์ด ์šฉ์ ‘ ์ž๊ฒฉ๊ณผ ์ง€๊ฒŒ์ฐจ ์ž๊ฒฉ์„ ํ•จ๊ป˜ ๊ฐ–๋Š”๋‹ค.\n */\n personnelClassIds?: string[]\n /** ๊ต๋Œ€ โ€” ์„ค๋น„์™€ ๊ฐ™์€ ๋ชจ์–‘. ๋ฏธ์ง€์ •=24์‹œ๊ฐ„ ๊ฐ€์šฉ. */\n window?: { startHour: number; endHour: number }\n /** ๊ทผ๋ฌด ์บ˜๋ฆฐ๋” โ€” ํ‘œ์ค€ `WorkCalendarEntry`(๋ณต์ˆ˜). 2๊ต๋Œ€ยทํœด๊ฒŒยทํœด์ผ์„ ํ•จ๊ป˜ ํ‘œํ˜„ํ•œ๋‹ค. */\n workCalendar?: WorkCalendarEntry[]\n /**\n * ๊ธฐ๋ณธ ์œ„์น˜ โ€” ํ‘œ์ค€ `Person.OperationalLocation`. ์—†์œผ๋ฉด \"์ด ๋ผ์ธ์— ๋ช‡ ๋ช… ์žˆ๋‚˜\" ๋ฅผ ๋ฌผ์„ ์ˆ˜ ์—†๋‹ค.\n * ์‚ฌ๋žŒ์€ ์›€์ง์ด๋ฏ€๋กœ ์ด ๊ฐ’์€ **์ถœ๋ฐœ์ **์ด๊ณ , ์‹ค์ œ ์œ„์น˜๋Š” ๊ด€์ธก(person.status)์ด ๊ฐฑ์‹ ํ•œ๋‹ค.\n */\n homeLocationId?: string\n /**\n * ์ž์› ์†์„ฑ โ€” ํ‘œ์ค€ `PersonProperty`. **์ž๊ฒฉ์ฆยท์ˆ™๋ จ๋„๊ฐ€ ์—ฌ๊ธฐ ๋“ค์–ด๊ฐ„๋‹ค.**\n *\n * ํ‘œ์ค€์—๋Š” ์ž๊ฒฉ(Qualification)์ด๋ผ๋Š” ๋ณ„๋„ ์š”์†Œ๊ฐ€ ์—†๋‹ค(`B2MML-Personnel.xsd` ํ™•์ธ). ์ž๊ฒฉ์€\n * โ‘  ๋“ฑ๊ธ‰ ๋ณต์ˆ˜ ์†Œ์†์œผ๋กœ(`personnelClassIds: ['welder-certified','forklift-licensed']`) โ‘ก\n * ์ฆ๋น™์€ ์ด ์†์„ฑ์œผ๋กœ(์ž๊ฒฉ์ฆ ๋ฒˆํ˜ธยท๋งŒ๋ฃŒ์ผ), โ‘ข ๊ฒ€์ฆ ์‹œํ—˜์€ ํ‘œ์ค€ `TestSpecificationID`(์•„์ง ๋ฏธ๊ตฌํ˜„).\n */\n properties?: RefResourceProperty[]\n /** ์ž๊ฒฉ์„ ๊ฒ€์ฆํ•œ ์‹œํ—˜ ๋ช…์„ธ๋“ค โ€” ํ‘œ์ค€ `TestSpecificationID`(์ฐธ์กฐ๋งŒ; ์‹œํ—˜ ๋ช…์„ธยท๊ฒฐ๊ณผ ๋ชจ๋ธ์€ ์•„์ง ์—†๋‹ค). */\n testSpecificationIds?: string[]\n /** ์œ ํšจ ๊ธฐ๊ฐ„ โ€” ์‚ฌ๋žŒ์—๊ฒŒ๋Š” **์ž…์‚ฌ ์ „ยทํ‡ด์‚ฌ ํ›„**๋‹ค(์ž๊ฒฉ ๋งŒ๋ฃŒ๋Š” ๋“ฑ๊ธ‰ ์ชฝ ๊ธฐ๊ฐ„์ด๋‹ค: ์‚ฌ๋žŒ์€ ๋‚จ๊ณ  ์ž๊ฒฉ๋งŒ ๋Š๊ธด๋‹ค). */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\n/**\n * ๋ฌผ๋ฆฌ ์ž์‚ฐ(๋ฐ˜๋ณต์‚ฌ์šฉ) โ€” **ISA-95 `PhysicalAsset`, GS1 `GRAI`.**\n * ํŒ”๋ ˆํŠธยท๋ž™ยท์šฉ๊ธฐ์ฒ˜๋Ÿผ **๋‚˜๊ฐ”๋‹ค ๋Œ์•„์˜ค๋Š”** ๊ฒƒ. ๋ฌผ๋ฅ˜๋‹จ์œ„(SSCC)์™€ ๋‹ค๋ฅด๋‹ค: SSCC ๋Š” ๊ทธ ํŒ”๋ ˆํŠธ์— ์‹ค๋ฆฐ ํ™”๋ฌผ\n * ํ•œ ๋ฉ์–ด๋ฆฌ์ด๊ณ , GRAI ๋Š” ํŒ”๋ ˆํŠธ ์ž์ฒด๋‹ค(์˜ค๋Š˜์€ ์ด ํ™”๋ฌผ, ๋‚ด์ผ์€ ์ € ํ™”๋ฌผ์„ ์‹ฃ๋Š”๋‹ค).\n */\nexport interface RefAsset {\n id: string\n name?: string\n /**\n * ์†ํ•œ ๋“ฑ๊ธ‰๋“ค โ€” ํ‘œ์ค€ `PhysicalAssetClassID`(๋ณต์ˆ˜). ํŒ”๋ ˆํŠธ๊ฐ€ 'euro-pallet' ์ด๋ฉด์„œ 'food-grade' ์ผ ์ˆ˜ ์žˆ๋‹ค.\n * ๊ณต์ •์˜ ์š”๊ตฌ๋Š” ๋“ฑ๊ธ‰ ํ•˜๋‚˜ + ์ˆ˜๋Ÿ‰์ด๋‹ค(ํ‘œ์ค€ `PhysicalAssetSpecification`).\n */\n assetClassIds?: string[]\n /** ๊ธฐ๋ณธ ์œ„์น˜. */\n homeLocationId?: string\n /** ์ •์‹ GS1 ์ •์ฒด์„ฑ โ€” ๋ฐ˜๋ณต์‚ฌ์šฉ ์ž์‚ฐ=GRAI. */\n gs1Id?: string\n /** ์ž์› ์†์„ฑ โ€” ํ‘œ์ค€ `PhysicalAssetProperty`(์ ์žฌ ํ•œ๋„ยท๊ทœ๊ฒฉ ๋“ฑ). */\n properties?: RefResourceProperty[]\n /** ์ ๊ฒฉ์„ ๊ฒ€์ฆํ•œ ์‹œํ—˜ ๋ช…์„ธ๋“ค โ€” ํ‘œ์ค€ `TestSpecificationID`. */\n testSpecificationIds?: string[]\n /** ์œ ํšจ ๊ธฐ๊ฐ„ โ€” ์ž์‚ฐ์—์„œ๋Š” **ํ๊ธฐํ•œ ํŒ”๋ ˆํŠธ๊ฐ€ ํ’€์—์„œ ๋น ์ง€๋Š” ๊ฒƒ**์ด๋‹ค(ํšŒ์ˆ˜ ๋Œ€์ƒ ์ˆ˜๊ฐ€ ๋ถ€ํ’€์ง€ ์•Š๊ฒŒ). */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\n/**\n * ํ’ˆ๋ชฉ ์ •์˜ โ€” **ISA-95 `MaterialDefinition`.**\n *\n * ์—†์œผ๋ฉด ๋กœํŠธ๋งŒ ๊ด€์ธก์œผ๋กœ ๋“ค์–ด์˜ค๊ณ  **ํ’ˆ๋ชฉ์ด ๋ฌด์—‡์ธ์ง€๋Š” ์•„๋ฌด ๋ฐ๋„ ์—†๋‹ค.** ๊ทธ๋ž˜์„œ ๊ฐ™์€ ๋กœํŠธ๋ฅผ 100๊ฐœ๋กœ\n * ๋ฐ›์•„๋„ \"๋ช‡ kg ์ธ๊ฐ€\" ์— ๋‹ตํ•  ์ˆ˜ ์—†๋‹ค(์ปค๋„ `quantityIn` ์ด ํ™˜์‚ฐ์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๊ทผ๊ฑฐ).\n *\n * **ํ‘œ์ค€์— ๋‹จ์œ„ ํ™˜์‚ฐ ์š”์†Œ๋Š” ์—†๋‹ค**(1์ฐจ ์ถœ์ฒ˜ ์ „์ˆ˜ ํ™•์ธ) โ€” ์†์„ฑ ์ฃผ๋จธ๋‹ˆ๋ฟ์ด๋‹ค. ๊ทธ๋ž˜์„œ ํ™˜์‚ฐ ๊ณ„์ˆ˜๋Š”\n * ์ปค๋„์ด ์ •ํ•œ ์†์„ฑ ์ด๋ฆ„(`perBaseUnit`, `uom` ์ด ๋Œ€์ƒ ๋‹จ์œ„)์œผ๋กœ `properties` ์— ์‹ฃ๋Š”๋‹ค.\n */\nexport interface RefMaterialDefinition {\n /** ํ‘œ์ค€ `ID` โ€” GTIN(`urn:epc:idpat:sgtin:โ€ฆ`)์„ ์“ด๋‹ค(์ •์ฒด์„ฑ์˜ ์ •๋ณธ์ด EPCIS ๋‹ค). */\n id: string\n name?: string\n /** ์†ํ•œ ๋“ฑ๊ธ‰๋“ค โ€” ํ‘œ์ค€ `MaterialClassID`(๋ณต์ˆ˜). */\n materialClassIds?: string[]\n /** ํ’ˆ๋ชฉ ์†์„ฑ โ€” ํ‘œ์ค€ `MaterialDefinitionProperty`. ํ™˜์‚ฐ ๊ณ„์ˆ˜๊ฐ€ ์—ฌ๊ธฐ ๋“ค์–ด๊ฐ„๋‹ค. */\n properties?: RefResourceProperty[]\n testSpecificationIds?: string[]\n effectiveStart?: string\n effectiveEnd?: string\n}\n\nexport interface ReferenceMaster {\n source: string\n system: 'wms' | 'yms' | 'mes'\n siteName: string\n /* spaceId ๋ช…์‹œ ์‹œ ๊ทธ ๊ณต๊ฐ„์„ ์ฐธ์กฐ(์—ฌ๋Ÿฌ ํŠธ์œˆ์ด ํ•œ ๊ณต๊ฐ„ ๊ณต์œ , N:1). ์—†์œผ๋ฉด source ์—์„œ ํŒŒ์ƒ(1:1). */\n /**\n * ํ˜„์žฅ(๊ณต๊ฐ„). **์‹œ๊ฐ ๊ธฐ์ค€(`timezone`)์ด ์—ฌ๊ธฐ ์žˆ๋Š” ์ด์œ **: ํ•œ ํ…Œ๋„ŒํŠธ๊ฐ€ Rosarito(ํƒœํ‰์–‘)์™€ ํ•œ๊ตญ\n * ๊ณต์žฅ์„ ํ•จ๊ป˜ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. ํ…Œ๋„ŒํŠธ ๋‹จ์œ„(`Domain.timezone`)๋กœ ๋‘๋ฉด **๋‘˜ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ˜๋“œ์‹œ ํ‹€๋ฆฐ๋‹ค.**\n * ์‹œ๊ฐ ๊ธฐ์ค€์€ **๋ฌผ๋ฆฌ ํ˜„์žฅ์˜ ์„ฑ์งˆ**์ด๋ฏ€๋กœ ๊ณต๊ฐ„์ด ๊ทธ๊ฒƒ์„ ๊ฐ–๋Š”๋‹ค(๊ณต๊ฐ„ ์ค‘์‹ฌ ์›์น™).\n *\n * `timezone` ์€ IANA ์ด๋ฆ„(`'America/Tijuana'`) โ€” ์˜คํ”„์…‹ ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ˆซ์ž๋กœ ๋‘๋ฉด ์ผ๊ด‘์ ˆ์•ฝ์‹œ๊ฐ„์„\n * ํ‘œํ˜„ํ•  ์ˆ˜ ์—†๊ณ , ๋‚˜์ค‘์— ์ ˆ๋Œ€ ๊ตฌ๊ฐ„์œผ๋กœ ์˜ฎ๊ธธ ๋•Œ๋„ ์ด๋ฆ„์ด ์žˆ์–ด์•ผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.\n */\n space: { spaceId?: string; width: number; depth: number; unit?: string; timezone?: string; geo?: { lat: number; lon: number; rotation?: number }; representations?: any[]; primaryId?: string }\n locations: RefLocation[]\n equipment?: RefEquipment[]\n /** ๊ณต์ • ๋ช…์„ธ(์†Œ์š”ยท๋ณ€๋™ยท์ˆ˜์œจ) โ€” ์—†์œผ๋ฉด ์ปค๋„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๊ตด๋Ÿฌ๊ฐ„๋‹ค(๊ทธ ์‚ฌ์‹ค์€ specCoverage ๊ฐ€ ๋ณด๊ณ ). */\n operations?: RefOperation[]\n /**\n * **์ƒ์‚ฐ ์ •์˜**(๋ ˆ์‹œํ”ผยท๋ผ์šฐํŠธยท์ž์žฌ ๋ฐ”์ธ๋”ฉ) โ€” ์ปค๋„์˜ ์ •์˜-๊ตฌ๋™ MES ๋ชจ๋“œ ์ž…๊ตฌ.\n *\n * ์—†์œผ๋ฉด ์ปค๋„์€ ๋ ˆ๊ฑฐ์‹œ(ํ•˜๋“œ์ฝ”๋”ฉ) ํ๋ฆ„์œผ๋กœ ๋ˆ๋‹ค. ์ฆ‰ **ํ˜„์žฅ ๋ ˆ์‹œํ”ผ๋ฅผ ์ ์–ด๋„ ์ด ์ž๋ฆฌ์— ์‹ค๋ฆฌ์ง€ ์•Š์œผ๋ฉด\n * ์ปค๋„์€ ๊ทธ๊ฒƒ์„ ๋ณด์ง€ ๋ชปํ•œ๋‹ค** โ€” ์„ ์–ธ๊ณผ ์‹คํ–‰์ด ๊ฐˆ๋ผ์ง€๋Š” ์ง€์ ์ด๋ผ ์ž๋ฆฌ๋ฅผ ์—ฐ๋‹ค.\n */\n mesSpec?: unknown\n /**\n * ์‚ฌ๋žŒ โ€” ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ฉด **์ธ์› ์ œ์•ฝ์ด ์—†๋Š” ํŠธ์œˆ**์ด ๋œ๋‹ค(์„ค๋น„๋งŒ ์žˆ์œผ๋ฉด ์–ธ์ œ๋‚˜ ๋Œ์•„๊ฐ€๋Š” ๊ณต์žฅ).\n * ๊ณต์ •์ด ์ธ์›์„ ์š”๊ตฌํ•˜๋Š”๋ฐ ์‚ฌ๋žŒ์ด ์—†์œผ๋ฉด ๊ทธ ์ž‘์—…์€ ์‹œ์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค โ€” ๊ทธ๊ฒƒ์ด ์‚ฌ์‹ค์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค.\n */\n persons?: RefPerson[]\n /**\n * ๋ฌผ๋ฆฌ ์ž์‚ฐ(๋ฐ˜๋ณต์‚ฌ์šฉ) โ€” ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ฉด ์ž์‚ฐ ์ œ์•ฝ์ด ์—†๋Š” ํŠธ์œˆ์ด๋‹ค.\n * ๊ณต์ •์ด ์ž์‚ฐ์„ ์š”๊ตฌํ•˜๋Š”๋ฐ ์—†์œผ๋ฉด ๊ทธ ์ž‘์—…์€ ์‹œ์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค โ€” ๊ทธ๊ฒƒ์ด ์‚ฌ์‹ค์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค.\n */\n assets?: RefAsset[]\n /**\n * ๋“ฑ๊ธ‰ ์ •์˜ โ€” ํ‘œ์ค€ `PersonnelClass`ยท`EquipmentClass`ยท`PhysicalAssetClass`.\n * ์•ˆ ์‹ค์–ด๋„ ํŠธ์œˆ์€ ๋ˆ๋‹ค(์†Œ์† ๋ฌธ์ž์—ด ๊ทธ๋Œ€๋กœ ํŒ์ •). ์‹ค์œผ๋ฉด ์ƒ์†ยท์œ ํšจ๊ธฐ๊ฐ„์ด ์‚ด์•„๋‚œ๋‹ค.\n */\n personnelClasses?: RefResourceClass[]\n equipmentClasses?: RefResourceClass[]\n assetClasses?: RefResourceClass[]\n /** ํ’ˆ๋ชฉ ์ •์˜ยท๋“ฑ๊ธ‰ โ€” ํ‘œ์ค€ `MaterialDefinition` / `MaterialClass`. ์—†์œผ๋ฉด ๋‹จ์œ„ ํ™˜์‚ฐ์„ ํ•  ์ˆ˜ ์—†๋‹ค. */\n materialDefinitions?: RefMaterialDefinition[]\n materialClasses?: RefResourceClass[]\n}\n\nexport interface IngestedTwin {\n board: any // BoardDef(+layout+spaceId) โ€” ์ปค๋„ ์†Œ๋น„\n spaceContent: any // TwinSpace content โ€” ๋ทฐ ์†Œ๋น„\n warnings: string[]\n}\n\n/**\n * ๋งˆ์Šคํ„ฐ โ†’ ํŠธ์œˆ ๊ตฌ์กฐ ๋งคํ•‘(์ˆœ์ˆ˜). ๋…ธ๋“œํƒ€์ž…์„ ์นดํƒˆ๋กœ๊ทธ๋กœ ๊ฒ€์ฆ(๋ชจ๋ฅด๋Š” ํƒ€์ž…์€ warning, ๋ฒ„๋ฆฌ์ง„ ์•Š์Œ โ€” ๋ฐ˜์˜ ์šฐ์„ ).\n * @param catalog DOMAIN_CATALOG (์ปค๋„ SSOT). ์—†์œผ๋ฉด ๊ฒ€์ฆ ์ƒ๋žต.\n */\n/**\n * IANA ์‹œ๊ฐ„๋Œ€ ์ด๋ฆ„ โ†’ **๊ทธ ์‹œ๊ฐ์˜** UTC ์˜คํ”„์…‹(๋ถ„). ์˜์กด์„ฑ ์—†์ด `Intl` ๋กœ ํ‘ผ๋‹ค.\n *\n * `Intl.DateTimeFormat` ์˜ `longOffset` ์€ `\"GMT-07:00\"` ์ฒ˜๋Ÿผ ๋‚˜์˜ค๊ณ , ์ด๊ฒƒ์€ **์ผ๊ด‘์ ˆ์•ฝ์‹œ๊ฐ„์„ ๋ฐ˜์˜ํ•œ**\n * ๊ฐ’์ด๋‹ค. ๊ทธ๋ž˜์„œ 8์›”์˜ `America/Tijuana` ๋Š” โˆ’420(PDT), 1์›”์€ โˆ’480(PST)์ด ๋œ๋‹ค.\n *\n * **ํ•œ๊ณ„๋ฅผ ๋ฐํžŒ๋‹ค**: ์—ฌ๊ธฐ์„œ ๋‚˜์˜ค๋Š” ๊ฒƒ์€ **ํ•œ ์‹œ์ ์˜** ์˜คํ”„์…‹์ด๋‹ค. ์ปค๋„์€ ๊ณ ์ • ์˜คํ”„์…‹์œผ๋กœ ํ•˜๋ฃจ ์ค‘ ๋ถ„์„\n * ์ฝ์œผ๋ฏ€๋กœ, ๋ณด๋“œ๋ฅผ ๋งŒ๋“  ๊ณ„์ ˆ๊ณผ ๋‹ค๋ฅธ ๊ณ„์ ˆ์„ ๊ธธ๊ฒŒ ์˜ˆ์ธกํ•˜๋ฉด ํ•œ ์‹œ๊ฐ„ ์–ด๊ธ‹๋‚œ๋‹ค. ํ‘œ์ค€์— ์ถฉ์‹คํ•œ ๋ ๋ชจ์Šต์€\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ์ ˆ๋Œ€ ๊ตฌ๊ฐ„(`StartDateTime`/`FinishDateTime`)์„ ๊ณ„์‚ฐํ•ด ๋„ฃ๋Š” ๊ฒƒ์ด๊ณ , ๊ทธ๋•Œ ์ด ํ•จ์ˆ˜๋Š” ์‚ฌ๋ผ์ง„๋‹ค.\n *\n * ๋ชจ๋ฅด๋Š” ์ด๋ฆ„์—๋Š” **0 ์„ ๋‹ตํ•˜์ง€ ์•Š๋Š”๋‹ค**(`undefined`) โ€” 0 ์€ \"UTC ๋ผ๊ณ  ์„ ์–ธํ–ˆ๋‹ค\" ๋Š” ๋œป์ด๊ณ , ๋ชจ๋ฅด๋Š” ๊ฒƒ์„\n * ๊ทธ๋ ‡๊ฒŒ ๋ฐ”๊พธ๋ฉด ํŒ์ •์ด ์กฐ์šฉํžˆ ํ‹€๋ฆฐ๋‹ค.\n */\nexport function utcOffsetOf(timezone?: string, at: Date = new Date()): number | undefined {\n if (!timezone) return undefined\n try {\n const parts = new Intl.DateTimeFormat('en-US', { timeZone: timezone, timeZoneName: 'longOffset' }).formatToParts(at)\n const name = parts.find(p => p.type === 'timeZoneName')?.value ?? ''\n if (name === 'GMT') return 0 // UTC ๊ณ„์—ด์€ ์˜คํ”„์…‹ ํ‘œ๊ธฐ๊ฐ€ ์—†๋‹ค\n const m = /^GMT([+-])(\\d{1,2})(?::(\\d{2}))?$/.exec(name)\n if (!m) return undefined\n const sign = m[1] === '-' ? -1 : 1\n return sign * (Number(m[2]) * 60 + Number(m[3] ?? 0))\n } catch {\n return undefined // ์•Œ ์ˆ˜ ์—†๋Š” ์ด๋ฆ„ โ€” Intl ์ด ๋˜์ง„๋‹ค\n }\n}\n\nexport function masterToTwin(master: ReferenceMaster, catalog?: any): IngestedTwin {\n const warnings: string[] = []\n const known: string[] = catalog?.[master.system]?.locationTypes ?? []\n\n const locationEntries = master.locations.filter(l => l.role === 'location' || l.role === 'both')\n const areaLocs = master.locations.filter(l => l.role === 'area' || l.role === 'both')\n\n const locations = locationEntries.map(l => {\n if (known.length && !known.includes(l.type)) warnings.push(`unknown ${master.system} location type \"${l.type}\" (${l.id}) โ€” ์นดํƒˆ๋กœ๊ทธ์— ์—†์Œ`)\n // gs1Id(์ •์‹ ์ •์ฒด์„ฑ)๋ฅผ ๋ณด๋“œ ๋…ธ๋“œ๋กœ ํ†ต๊ณผ โ€” ๊ฒฐํ•ฉ(tag)/์ถ”์ ์ด GS1 ๋กœ(ยงJ). ๋กœ์ปฌ id ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€(name/xref).\n return { id: l.id, type: l.type, capacity: l.capacity ?? 0, ...(l.parallelism !== undefined ? { parallelism: l.parallelism } : {}), ...(l.level ? { level: l.level } : {}), parentId: l.parentId, gs1Id: l.gs1Id }\n })\n\n const equipment = (master.equipment ?? []).map(e => ({\n id: e.id, kind: e.kind, homeLocation: e.homeLocationId, mtbfMs: e.mtbfMs, mttrMs: e.mttrMs, gs1Id: e.gs1Id,\n ...(e.window ? { window: e.window } : {}),\n /* ์†์„ฑ์€ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ์ด๋™์‹œ๊ฐ„ ์ถ”์ •๊ธฐ๊ฐ€ kind ๋ณ„ ์†๋„๋ฅผ ์—ฌ๊ธฐ์„œ ์ฝ๋Š”๋‹ค(๋‹จ์œ„ ์ฝ”๋“œ ๊ทธ๋Œ€๋กœ). */\n ...(e.properties?.length ? { properties: e.properties } : {}), ...(e.workCalendar?.length ? { workCalendar: e.workCalendar } : {}), ...(e.testSpecificationIds?.length ? { testSpecificationIds: e.testSpecificationIds } : {}),\n /* ์œ ํšจ ๊ธฐ๊ฐ„๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ํŒ์ •์€ ์ปค๋„์ด ์ž๊ธฐ ์‹œ๊ณ„๋กœ ํ•œ๋‹ค(ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ฏธ๋ฆฌ ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค). */\n ...(e.effectiveStart ? { effectiveStart: e.effectiveStart } : {}), ...(e.effectiveEnd ? { effectiveEnd: e.effectiveEnd } : {})\n }))\n\n // ์ขŒํ‘œ(layout) โ€” footprint ์ค‘์‹ฌ. ์—†์œผ๋ฉด ์ƒ๋žต(coordinate-free ์œ ์ง€).\n const layout: Record<string, { x: number; y: number }> = {}\n for (const l of locationEntries) if (l.footprint) layout[l.id] = { x: l.footprint.x + l.footprint.w / 2, y: l.footprint.y + l.footprint.h / 2 }\n\n const spaceId = master.space.spaceId ?? `${master.source}-site`\n /*\n * ์‹œ๊ฐ ๊ธฐ์ค€์„ ์ปค๋„์ด ์ฝ์„ ํ˜•ํƒœ๋กœ ํ‘ผ๋‹ค โ€” ์ปค๋„์€ zero-dep ์ด๋ผ ์‹œ๊ฐ„๋Œ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋“ค์ด์ง€ ์•Š๊ณ \n * **๋ถ„ ์˜คํ”„์…‹**๋งŒ ๋ฐ›๋Š”๋‹ค(๊ณ„์•ฝ `BoardDef.utcOffsetMinutes`). ํ‘ธ๋Š” ์ผ์€ ํ˜ธ์ŠคํŠธ์˜ ๋ชซ์ด๋‹ค.\n *\n * ์„ ์–ธ์ด ์—†์œผ๋ฉด **ํ•„๋“œ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ทธ๋Ÿฌ๋ฉด ์ปค๋„์ด UTC ๋กœ ์ฝ๊ณ , ๊ทธ ๊ธฐ๋ณธ๊ฐ’์€ ๊ณ„์•ฝ์— ๋ฐํ˜€์ ธ ์žˆ๋‹ค.\n * ์—ฌ๊ธฐ์„œ 0 ์„ ๋„ฃ์œผ๋ฉด \"UTC ๋ผ๊ณ  ์„ ์–ธํ–ˆ๋‹ค\" ์™€ \"์„ ์–ธํ•˜์ง€ ์•Š์•˜๋‹ค\" ๊ฐ€ ๊ตฌ๋ณ„๋˜์ง€ ์•Š๋Š”๋‹ค.\n */\n const utcOffsetMinutes = utcOffsetOf(master.space.timezone)\n if (master.space.timezone && utcOffsetMinutes === undefined) {\n warnings.push(`space timezone \"${master.space.timezone}\" is not a known IANA zone โ€” the twin will read times as UTC`)\n }\n /*\n * ์˜คํผ๋ ˆ์ด์…˜ ๋ช…์„ธ๋ฅผ board ์— ํ†ต๊ณผ์‹œํ‚จ๋‹ค โ€” ์ปค๋„์ด `loadOperations` ๋กœ ์†Œ๋น„ํ•œ๋‹ค(BoardDef ํ™•์žฅ ํ•„๋“œ,\n * ๋ชจ๋ฅด๋Š” ์ปค๋„์€ ๋ฌด์‹œ). ์—ฌ๊ธฐ์„œ ๊ฐ’์„ ์†๋Œ€์ง€ ์•Š๋Š”๋‹ค: ๊ธฐ๊ฐ„์€ ํ‘œ์ค€ ํ‘œ๊ธฐ(ISO 8601)๋กœ ์ปค๋„๊นŒ์ง€ ๊ทธ๋Œ€๋กœ ๊ฐ„๋‹ค.\n */\n const operations = master.operations\n if (operations?.length) {\n for (const o of operations) {\n if (!o.duration && !o.parameters?.length) warnings.push(`operation \"${o.key}\" has no duration or parameters โ€” kernel defaults will be used`)\n }\n }\n /* ์‚ฌ๋žŒ๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๋“ฑ๊ธ‰ยท๊ต๋Œ€ ๊ทธ๋Œ€๋กœ ์ปค๋„๊นŒ์ง€ ๊ฐ„๋‹ค(๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค). */\n const persons = master.persons?.map(p => ({ id: p.id, personnelClassIds: p.personnelClassIds, ...(p.window ? { window: p.window } : {}), ...(p.workCalendar?.length ? { workCalendar: p.workCalendar } : {}), ...(p.homeLocationId ? { homeLocation: p.homeLocationId } : {}), ...(p.properties?.length ? { properties: p.properties } : {}), ...(p.testSpecificationIds?.length ? { testSpecificationIds: p.testSpecificationIds } : {}), ...(p.effectiveStart ? { effectiveStart: p.effectiveStart } : {}), ...(p.effectiveEnd ? { effectiveEnd: p.effectiveEnd } : {}) }))\n /* ์ž์‚ฐ๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๋“ฑ๊ธ‰ยท์ž๋ฆฌ ๊ทธ๋Œ€๋กœ ์ปค๋„๊นŒ์ง€. */\n const assets = master.assets?.map(a => ({ id: a.id, assetClassIds: a.assetClassIds, homeLocation: a.homeLocationId, gs1Id: a.gs1Id, ...(a.properties?.length ? { properties: a.properties } : {}), ...(a.testSpecificationIds?.length ? { testSpecificationIds: a.testSpecificationIds } : {}), ...(a.effectiveStart ? { effectiveStart: a.effectiveStart } : {}), ...(a.effectiveEnd ? { effectiveEnd: a.effectiveEnd } : {}) }))\n /* ํ’ˆ๋ชฉ ์ •์˜ยท๋“ฑ๊ธ‰๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค(ํ™˜์‚ฐ ๊ณ„์ˆ˜๋Š” ์ปค๋„์ด ์ฝ๋Š”๋‹ค). */\n const materialDefinitions = master.materialDefinitions?.map(d => ({\n id: d.id,\n ...(d.name ? { description: d.name } : {}),\n ...(d.materialClassIds?.length ? { materialClassIds: d.materialClassIds } : {}),\n ...(d.properties?.length ? { properties: d.properties } : {}),\n ...(d.testSpecificationIds?.length ? { testSpecificationIds: d.testSpecificationIds } : {}),\n ...(d.effectiveStart ? { effectiveStart: d.effectiveStart } : {}),\n ...(d.effectiveEnd ? { effectiveEnd: d.effectiveEnd } : {})\n }))\n const board = {\n locations, equipment, layout, spaceId,\n /* ์ƒ์‚ฐ ์ •์˜๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค(์ปค๋„์ด ๊ทธ๋Œ€๋กœ ์†Œ๋น„ํ•œ๋‹ค). */\n ...(master.mesSpec ? { mesSpec: master.mesSpec } : {}),\n ...(materialDefinitions?.length ? { materialDefinitions } : {}),\n ...(master.materialClasses?.length ? { materialClasses: master.materialClasses } : {}),\n ...(utcOffsetMinutes !== undefined ? { utcOffsetMinutes } : {}),\n ...(operations?.length ? { operations } : {}),\n ...(master.personnelClasses?.length ? { personnelClasses: master.personnelClasses } : {}),\n ...(master.equipmentClasses?.length ? { equipmentClasses: master.equipmentClasses } : {}),\n ...(master.assetClasses?.length ? { assetClasses: master.assetClasses } : {}),\n ...(persons?.length ? { persons } : {}),\n ...(assets?.length ? { assets } : {})\n }\n\n const areas = areaLocs.map(l => ({\n id: l.id, type: l.type, name: l.name ?? l.id, parentId: l.parentId,\n x: l.footprint?.x ?? 0, y: l.footprint?.y ?? 0, w: l.footprint?.w ?? 10, h: l.footprint?.h ?? 10\n }))\n // ์ธ์ œ์ŠคํŠธ ํ˜„์žฅ ๋ฌผ์งˆํ™”(space facet #4) โ€” ํ‘œํ˜„์ด ์—†๊ณ  geo ๊ฐ€ ์žˆ์œผ๋ฉด ๊ธฐ๋ณธ map ํ‘œํ˜„ ํ•ฉ์„ฑ.\n // \"์ธ์ œ์ŠคํŠธํ•˜๋ฉด ์•Œ์•„๋ณผ ํ˜„์žฅ(๋‚ด place)์ด ๋œฌ๋‹ค\"๋Š” ๊ณต๊ฐ„ ์ค‘์‹ฌ ์ •์ˆ˜ ๋ณด์žฅ(zero-to-twin): ์ปค๋„ฅํ„ฐ/ํ…œํ”Œ๋ฆฟ์ด\n // ํ‘œํ˜„์„ ์•ˆ ์ค˜๋„ geo ๋งŒ ์žˆ์œผ๋ฉด ์œ„์„ฑ ์ง€๋„๋กœ ์ฐฉ์ง€. (area ํด๋ฆฌ๊ณค ๋ฌผ์งˆํ™”๋Š” ์ขŒํ‘œ ํˆฌ์˜ ํ•„์š” โ†’ space #3.)\n const geo = master.space.geo\n const givenReps = master.space.representations ?? []\n const representations =\n givenReps.length > 0\n ? givenReps\n : geo\n ? [{ id: 'r-map', type: 'map', name: '์œ„์„ฑ ์ง€๋„', primary: true, center: { lat: geo.lat, lon: geo.lon }, zoom: 17 }]\n : []\n if (representations.length === 0) {\n warnings.push('space has no viewable representation (no representations and no geo) โ€” add one manually or provide geo/board')\n }\n const spaceContent = {\n width: master.space.width, depth: master.space.depth, unit: master.space.unit ?? 'm',\n geo, representations, primaryId: master.space.primaryId ?? representations[0]?.id,\n areas, landmarks: []\n }\n\n return { board, spaceContent, warnings }\n}\n"]}
1
+ {"version":3,"file":"reference-master.js","sourceRoot":"","sources":["../../../server/service/reference/reference-master.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Face2 ๋งˆ์Šคํ„ฐ ์ธ์ œ์ŠคํŠธ(ADR-0018 ๋ฐ˜์˜ ๋ชจ๋“œ) โ€” ๋ ˆํผ๋Ÿฐ์Šค ์‹œ์Šคํ…œ(์‹ค WMS/YMS/MES ๋˜๋Š” ๊ฐ€์ƒ ๋ ˆํผ๋Ÿฐ์Šค)์˜\n * ๋งˆ์Šคํ„ฐ๋ฅผ ์ฝ์–ด ํŠธ์œˆ ๊ตฌ์กฐ(BoardDef) + ๊ณต๊ฐ„(Space content)์„ ์ƒ์„ฑ. ์†๋ฐฐ์„ ์ด ์•„๋‹ˆ๋ผ ์ธ์ œ์ŠคํŠธ๋กœ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ํ๋ฅธ๋‹ค.\n *\n * ๊ทœ์œจ(ADR-0018): ๋„๋ฉ”์ธ ํƒ€์ž…(location.type=๋…ธ๋“œ์šฉ)์€ ์ปค๋„ ์นดํƒˆ๋กœ๊ทธ ์–ดํœ˜๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜์˜(๋ฐœ๋ช… ๊ธˆ์ง€).\n * location ์€ role ๋กœ ๋…ธ๋“œ(์šด์˜์ )ยทarea(๊ณต๊ฐ„์˜์—ญ)ยทboth ๋ฅผ ๊ตฌ๋ถ„ โ€” ๋…ธ๋“œโ†’BoardDef, areaโ†’Space.areas.\n * ์ขŒํ‘œยทrepresentations ๋Š” ํŠธ์œˆ ๊ณต๊ฐ„์ธต(๋ณด์™„/์ถ”๊ฐ€). ์‹ค ์‹œ์Šคํ…œ์ด ์ขŒํ‘œ๋ฅผ ์•ˆ ์ฃผ๋ฉด layout ์—†์ด ์œ„์ƒ๋งŒ ์ธ์ œ์ŠคํŠธ.\n */\n\nimport type { EquipmentLevel, WorkCalendarEntry } from '@operato/twin-kernel'\n\nexport interface RefLocation {\n id: string\n type: string // ๋…ธ๋“œ๋Š” ์ปค๋„ ๋…ธ๋“œํƒ€์ž…(dock/storage/yard-slotโ€ฆ), area ๋Š” ๊ณต๊ฐ„ region ํƒ€์ž…\n name?: string\n role: 'location' | 'area' | 'both'\n parentId?: string\n /** ์ €์žฅ ์šฉ๋Ÿ‰ โ€” ์ด ์ž๋ฆฌ์— ๋™์‹œ์— ๋†“์ผ ์ˆ˜ ์žˆ๋Š” ๋ฌผํ’ˆ ์ˆ˜. */\n capacity?: number\n /**\n * ๋™์‹œ ์ฒ˜๋ฆฌ ์ˆ˜ โ€” ์ด ์ž๋ฆฌ์—์„œ ํ•œ ๋ฒˆ์— ์ง„ํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ์ˆ˜. **์ €์žฅ ์šฉ๋Ÿ‰๊ณผ ๋‹ค๋ฅธ ์ถ•**์ด๋‹ค\n * (์ž์žฌ๋ฅผ 20๊ฐœ ์Œ“์•„ ๋‘๋Š” ์ ˆ๋‹จ ์Šคํ…Œ์ด์…˜์ด ํ•œ ๋ฒˆ์— ํ•œ ๋Œ€๋งŒ ๊นŽ๋Š”๋‹ค). ๋ฏธ์ง€์ •=์ œ์•ฝ ์—†์Œ.\n */\n parallelism?: number\n /**\n * **ISA-95 ์„ค๋น„ ๊ณ„์ธต ๋‹จ๊ณ„** โ€” `EquipmentLevel` ์—ด๊ฑฐ๊ฐ’(`ProductionLine`ยท`StorageZone`ยท`WorkCenter`โ€ฆ).\n *\n * `type` ์€ ํ˜„์žฅ์˜ ๋‚ฑ๋ง(`paint-booth`)์ด๊ณ  ์ด๊ฒƒ์€ **ํ‘œ์ค€์ด ์ •ํ•œ ์—ญํ• **์ด๋‹ค. ๋‘˜์€ ๋‹ค๋ฅธ ์ถ•์ด๋ผ ํ•จ๊ป˜ ๋“ ๋‹ค โ€”\n * ์—ฐ๋™ยท์ง‘๊ณ„๋Š” ํ‘œ์ค€ ์ถ•์œผ๋กœ, ํ™”๋ฉด์€ ํ˜„์žฅ ๋‚ฑ๋ง๋กœ. ๋ฏธ์ง€์ •์ด๋ฉด ๊ทธ ์ž๋ฆฌ์˜ ํ‘œ์ค€ ์—ญํ• ์„ ์•„์ง ๋ชจ๋ฅธ๋‹ค๋Š” ๋œป์ด๊ณ ,\n * ์ง์ž‘ํ•ด ์ฑ„์šฐ์ง€ ์•Š๋Š”๋‹ค.\n */\n level?: EquipmentLevel\n footprint?: { x: number; y: number; w: number; h: number } // ์žˆ์œผ๋ฉด area ๊ธฐํ•˜ + ๋…ธ๋“œ ์ค‘์‹ฌ์ขŒํ‘œ\n gs1Id?: string // ์ •์‹ GS1 ์ •์ฒด์„ฑ(ยงJ) โ€” ์œ„์น˜=SGLN. ๊ฒฐํ•ฉ(tag)/์ถ”์  canonical id. ๋ฐ›์•„๋“ค์ด๊ธฐ ๊ฒฝ๊ณ„์„œ ๋ถ€์—ฌ(๋กœ์ปฌ id=name/xref ๋กœ ๋ณด์กด).\n}\n\n/**\n * ์„ค๋น„ ์†์„ฑ โ€” **ISA-95 `EquipmentSpecificationProperty`(`OpEquipmentSpecificationPropertyType`) 1:1.**\n * ๊ทธ ํƒ€์ž…๋„ `ID` + `Value`(`ValueString`ยท`DataType`ยท`UnitOfMeasure`) ์ด๋ฏ€๋กœ ๊ณต์ • ๋ชจ์ˆ˜์™€ ๊ฐ™์€ ๋ชจ์–‘์ด๋‹ค.\n *\n * ๋‹จ์œ„ ์ฝ”๋“œ๋Š” **UN/CEFACT ๊ถŒ๊ณ  20 ๊ณตํ†ต์ฝ”๋“œ**(EPCIS `uom` ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ณ„): ์†๋„๋Š” `MTS`(metre per\n * second) ๋˜๋Š” `KMH`(kilometre per hour). ์ฝ”๋“œ๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ๋ฐœ๋ช…ํ•˜์ง€ ์•Š๋Š”๋‹ค.\n */\n/**\n * ์ž์› ์†์„ฑ โ€” **์ปค๋„ `ResourceProperty` ์™€ ๊ฐ™์€ ๋ชจ์–‘**์ด๊ณ , ๊ทธ ๋ชจ์–‘์€ ISA-95 ๊ฐ€ ์„ธ ์ž์›์— ๋˜‘๊ฐ™์ด\n * ์ •์˜ํ•œ ๊ฒƒ์ด๋‹ค(`EquipmentPropertyType` ยท `PersonPropertyType` ยท `PhysicalAssetPropertyType`).\n *\n * ๊ทธ๋ž˜์„œ ์ž์›๋งˆ๋‹ค ๋‹ค๋ฅธ ์†์„ฑ ํƒ€์ž…์„ ๋‘์ง€ ์•Š๋Š”๋‹ค โ€” ์˜ˆ์ „์—๋Š” ์„ค๋น„๋งŒ ์†์„ฑ์„ ๊ฐ€์กŒ๊ณ (RefEquipmentProperty),\n * ์ธ์›ยท์ž์‚ฐ์— ๋ถ™๋Š” ์‚ฌ์‹ค์€ **์‹ค์„ ์ž๋ฆฌ๊ฐ€ ์—†์–ด์„œ ๋“ค์–ด์˜ค์ง€ ๋ชปํ–ˆ๋‹ค.**\n */\nexport interface RefResourceProperty {\n id: string\n description?: string\n value?: string\n /** ํ‘œ์ค€ `Value.DataType`. */\n dataType?: string\n /** ํ‘œ์ค€ `Value.UnitOfMeasure` โ€” UN/CEFACT ๊ณตํ†ต์ฝ”๋“œ. ๋ฌผ๋ฆฌ๋Ÿ‰์— ๋‹จ์œ„๊ฐ€ ์—†์œผ๋ฉด ์†Œ๋น„์ฒ˜๊ฐ€ ๊ฑฐ์ ˆํ•œ๋‹ค. */\n uom?: string\n /** ํ•˜์œ„ ์†์„ฑ(์žฌ๊ท€) โ€” ํ‘œ์ค€ `<X>PropertyChild`. */\n children?: RefResourceProperty[]\n /** ์ด ๊ฐœ์ฒด ์†์„ฑ์ด ๊ตฌ์ฒดํ™”ํ•˜๋Š” ๋“ฑ๊ธ‰ ์†์„ฑ โ€” ํ‘œ์ค€ `<X>ClassPropertyID`. */\n classPropertyId?: string\n}\n\n/** ์˜› ์ด๋ฆ„ โ€” ์„ค๋น„ ์ „์šฉ์ด๋˜ ์‹œ์ ˆ์˜ ๋ณ„์นญ(์†Œ๋น„์ฒ˜ ํ˜ธํ™˜). ์‹ ๊ทœ ์†Œ์‹ฑ์€ `RefResourceProperty`. */\nexport type RefEquipmentProperty = RefResourceProperty\n\n/**\n * ์ž์› **๋“ฑ๊ธ‰ ์ •์˜** โ€” ์ปค๋„ `ResourceClassDef` ์™€ ๊ฐ™์€ ๋ชจ์–‘์ด๊ณ , ๊ทธ ๋ชจ์–‘์€ ISA-95 ๊ฐ€ ์„ธ ์ž์›์— ๋˜‘๊ฐ™์ด\n * ์ •์˜ํ•œ ๊ฒƒ์ด๋‹ค(`PersonnelClassType`ยท`EquipmentClassType`ยท`PhysicalAssetClassType`).\n *\n * ์™œ ํ•„์š”ํ•œ๊ฐ€: ์› ์‹œ์Šคํ…œ์€ ๋“ฑ๊ธ‰ **์ฒด๊ณ„**๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค(\"6์ถ• ์šฉ์ ‘ ์ž๊ฒฉ์ž\" ๋Š” \"์šฉ์ ‘ ์ž๊ฒฉ์ž\" ์ด๊ณ , ๊ทธ๊ฒƒ์€\n * \"์ƒ์‚ฐ์ง\" ์ด๋‹ค). ๊ทธ ์ฒด๊ณ„๊ฐ€ ๋“ค์–ด์˜ฌ ์ž๋ฆฌ๊ฐ€ ์—†์œผ๋ฉด ์š”๊ตฌ์™€ ์†Œ์†์ด **๋ฌธ์ž์—ด์ด ๋˜‘๊ฐ™์„ ๋•Œ๋งŒ** ๋งž์•„,\n * ํ˜„์žฅ์—์„œ๋Š” ๋˜๋Š” ๋ฐฐ์ •์ด ๋ชจ๋ธ์—์„œ ๋ง‰ํžŒ๋‹ค.\n */\nexport interface RefResourceClass {\n id: string\n description?: string\n /** ์ƒ์œ„ ๋“ฑ๊ธ‰๋“ค โ€” ํ‘œ์ค€ `<X>ClassBaseID`(๋ณต์ˆ˜ = ๋‹ค์ค‘ ์ƒ์†). */\n baseIds?: string[]\n properties?: RefResourceProperty[]\n testSpecificationIds?: string[]\n /** ์œ ํšจ ๊ธฐ๊ฐ„(ISO) โ€” ํ‘œ์ค€ `EffectiveStartDate`/`EffectiveEndDate`. ๋ฐ–์ด๋ฉด ์ž๊ฒฉ์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š๋Š”๋‹ค. */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\nexport interface RefEquipment {\n id: string\n kind: string\n homeLocationId: string\n mtbfMs?: number // ํ‰๊ท  ๊ณ ์žฅ ๊ฐ„๊ฒฉ(ํ™•๋ฅ ์  ๊ณ ์žฅ) โ€” ์ง€์ • ์‹œ ์ปค๋„์ด breakdown ์‹œ๋ฎฌ โ†’ ์ฃผ๋ชฉ(๊ณ ์žฅ) ๋ฐœ์ƒ\n mttrMs?: number // ํ‰๊ท  ์ˆ˜๋ฆฌ ์‹œ๊ฐ„\n gs1Id?: string // ์ •์‹ GS1 ์ •์ฒด์„ฑ(ยงJ) โ€” ์„ค๋น„=GIAI.\n /**\n * ๊ต๋Œ€(๊ฐ€๋™์‹œ๊ฐ„) โ€” ์ด ์‹œ๊ฐ„๋Œ€์—๋งŒ ๋ฐฐ์ •๋œ๋‹ค. `startHour <= endHour` ๋ฉด ๊ฐ™์€ ๋‚ , ๋„˜์–ด๊ฐ€๋ฉด ์•ผ๊ฐ„(22โ†’6).\n * ๋ฏธ์ง€์ •=24์‹œ๊ฐ„ ๊ฐ€์šฉ. ๊ต๋Œ€ ๋ฐ– ์ž์›์€ ๊ณ ์žฅยท๊ณ„ํš์ •์ง€์™€ **๊ตฌ๋ณ„๋˜๋Š” ์ด์œ **๋กœ ์‰ฐ๋‹ค(์ƒํƒœ์— ๋“œ๋Ÿฌ๋‚œ๋‹ค).\n */\n window?: { startHour: number; endHour: number }\n /**\n * ๊ทผ๋ฌด ์บ˜๋ฆฐ๋” โ€” ํ‘œ์ค€ `WorkCalendarEntry`(๋ณต์ˆ˜). ์žˆ์œผ๋ฉด `window` ๋ณด๋‹ค ์ด๊ฒƒ์„ ๋ณธ๋‹ค.\n *\n * ์ถ•์„ ํ”„๋ ˆ์ž„์›Œํฌ `@things-factory/work-shift` ์˜ `WorkShift`(`fromDate`ยท`fromTime`ยท`toDate`ยท`toTime`)์™€\n * ๋งž์ถฐ ๋‘์—ˆ๋‹ค โ€” ๊ทธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ต๋Œ€์˜ ์ •๋ณธ์œผ๋กœ ๊ฒฐ์„ ํ•  ๋•Œ ์ง์„  ๋งคํ•‘์ด ๋˜๊ฒŒ. **์•„์ง ๊ฒฐ์„ ํ•˜์ง€ ์•Š์•˜๋‹ค**:\n * ๊ทธ ์—”ํ‹ฐํ‹ฐ์—๋Š” ์ž์› ์—ฐ๊ฒฐ๊ณผ ๋น„๊ทผ๋ฌด(ํœด์ผ)๊ฐ€ ์—†์–ด ํ™•์žฅ์ด ํ•จ๊ป˜ ํ•„์š”ํ•˜๊ณ , operato-twin ์˜ ์˜์กด์„ฑ ์ถ”๊ฐ€๋Š”\n * ์•ฑ ์•„ํ‚คํ…์ฒ˜ ๊ฒฐ์ •์ด๋‹ค(์ปค๋ฒ„๋ฆฌ์ง€ ยง4-7 ์— ๊ฒฐ์„  ์ง€์ ์œผ๋กœ ๊ธฐ๋ก).\n */\n workCalendar?: WorkCalendarEntry[]\n /**\n * ์„ค๋น„ ์†์„ฑ(์†๋„ ๋“ฑ) โ€” ์—†์œผ๋ฉด **์ด๋™์‹œ๊ฐ„์„ ๊ฑฐ๋ฆฌ์—์„œ ๊ณ„์‚ฐํ•  ์ˆ˜ ์—†๋‹ค**(์†๋„ ์—†์ด ๊ฑฐ๋ฆฌ๋งŒ์œผ๋กœ๋Š” ์‹œ๊ฐ„์ด\n * ์•ˆ ๋‚˜์˜จ๋‹ค). ๊ทธ๋•Œ๋Š” ์ปค๋„ ์ƒ์ˆ˜๋กœ ๋–จ์–ด์ง€๊ณ  ๊ทธ ์‚ฌ์‹ค์ด `specCoverage()` ์— ๋‚จ๋Š”๋‹ค.\n */\n properties?: RefResourceProperty[]\n /** ์ ๊ฒฉ์„ ๊ฒ€์ฆํ•œ ์‹œํ—˜ ๋ช…์„ธ๋“ค โ€” ํ‘œ์ค€ `TestSpecificationID`(๊ต์ • ๋“ฑ). */\n testSpecificationIds?: string[]\n /**\n * ์œ ํšจ ๊ธฐ๊ฐ„ โ€” **ํ‘œ์ค€ `EffectiveStartDate` / `EffectiveEndDate`**(๊ฐœ์ฒด ํƒ€์ž… ์…‹ ๋ชจ๋‘์— ์žˆ๋‹ค).\n *\n * ์—†์œผ๋ฉด **ํ๊ธฐํ•œ ๊ฒƒ์ด ์˜๊ตฌํžˆ ์‚ด์•„ ์žˆ๋‹ค**: ๋ฐฐ์ • ๋Œ€์ƒ์— ๋‚จ๊ณ , ๊ฐ€์šฉ ์ˆ˜์— ๋“ค์–ด๊ฐ€๊ณ , ํ™”๋ฉด์— ๋œฌ๋‹ค.\n * ๋„์ž… ์˜ˆ์ •์ธ ๊ฒƒ์€ ๋ฐ˜๋Œ€๋กœ ์˜ค๋Š˜๋ถ€ํ„ฐ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ๊ธฐ๊ฐ„ ๋ฐ–์ด๋ฉด ์ปค๋„์ด ๊ทธ ์‹œ๊ฐ์˜ ๋ชจ๋ธ์—์„œ\n * ๋นผ๊ณ  **์ด์œ ๋ฅผ ๋‹ฌ์•„ ๋‚จ๊ธด๋‹ค**(`effectivity: 'not-yet' | 'expired'`) โ€” ์กฐ์šฉํžˆ ์ง€์šฐ์ง€ ์•Š๋Š”๋‹ค.\n */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\n/**\n * ๊ณต์ • ๋ชจ์ˆ˜ โ€” ์ปค๋„ `OperationParameter`(= ISA-95 `ParameterSpecification`/`ParameterType`) ์™€ **๊ฐ™์€ ๋ชจ์–‘**.\n * ์ด๋ฆ„์„ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค: ์ธ์ œ์ŠคํŠธ ๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๊ฐ€ ๊ฐˆ๋ฆฌ๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฐฉ์–ธ์ด ์ƒ๊ธด๋‹ค.\n * ID ์–ดํœ˜์˜ ์ •๋ณธ์€ ์ปค๋„ `OP_PARAM`(ํ‘œ์ค€์ด ํŒŒ๋ผ๋ฏธํ„ฐ ID ๋ฅผ ์ •ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ•œ ๊ณณ์—์„œ ์ •ํ•œ๋‹ค).\n */\nexport interface RefOperationParameter {\n id: string\n /** ISA-95 `Value.ValueString` โ€” ํ‘œ์ค€์ด ๋ฌธ์ž์—ด๋กœ ์‹ฃ๋Š”๋‹ค. ๊ธฐ๊ฐ„ ๋ชจ์ˆ˜๋Š” ISO 8601(`PT8M`). */\n value: string\n /** ISA-95 `Value.UnitOfMeasure`. ๋ฌด์ฐจ์›(๋น„์œจ)์ด๋ฉด ์ƒ๋žต. */\n uom?: string\n}\n\n/**\n * ๊ณต์ •์˜ ์ž์žฌ ์š”๊ตฌยท์‚ฐ์ถœ โ€” **ISA-95 `OperationsSegment.MaterialSpecification`** ๊ณผ ๊ฐ™์€ ๋ชจ์–‘.\n * ์ธ์›ยท์„ค๋น„ยท์ž์‚ฐ ๋ช…์„ธ์™€ ๊ฐ™์€ ์ž๋ฆฌ์— ์žˆ์–ด์•ผ 4๋Œ€ ์ž์›์ด ๋Œ€์นญ์ด ๋œ๋‹ค(์ž์žฌ๋งŒ ๋น ์ ธ ์žˆ์—ˆ๋‹ค).\n */\nexport interface RefOpMaterialSpecification {\n id?: string\n /** ํ’ˆ๋ชฉ ๋“ฑ๊ธ‰์œผ๋กœ ์š”๊ตฌ โ€” ํ‘œ์ค€ `MaterialClassID`. */\n materialClass?: string\n /** ํŠน์ • ํ’ˆ๋ชฉ์œผ๋กœ ์š”๊ตฌ โ€” ํ‘œ์ค€ `MaterialDefinitionID`. */\n materialDefinition?: string\n /** ํ‘œ์ค€ `MaterialUse` โ€” ์ด ๊ณต์ •์—์„œ์˜ ์“ฐ์ž„. */\n use: 'consumed' | 'produced' | 'consumable'\n /** ํ‘œ์ค€ `Quantity`. ๋‹จ์œ„ ๋ฏธ์ง€์ •์ด๋ฉด ๊ฐœ์ˆ˜. */\n quantity: number\n uom?: string\n}\n\n/** ์†Œ์š”์‹œ๊ฐ„ ๋ณ€๋™ โ€” **ํ‘œ์ค€ ๋ฐ– ํ™•์žฅ**(ISA-95 Duration ์€ ์Šค์นผ๋ผ). ์ปค๋„ `DurationVariability` ์™€ ๋™ํ˜•. */\nexport interface RefOperationVariability {\n distribution: 'constant' | 'exponential' | 'uniform' | 'triangular'\n min?: string\n max?: string\n mode?: string\n}\n\n/**\n * ์˜คํผ๋ ˆ์ด์…˜ ๋ช…์„ธ โ€” ISA-95 `OperationsSegment`. ์ปค๋„ `OperationDef` ์™€ ํ•„๋“œ ์ด๋ฆ„์ด 1:1์ด๋‹ค.\n *\n * **์ด๊ฒƒ์ด ์—†์œผ๋ฉด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์˜ ์‹œ๊ฐ„์€ ์šฐ๋ฆฌ๊ฐ€ ์ฝ”๋“œ์— ๋ฐ•์•„ ๋‘” ์ƒ์ˆ˜๋‹ค.** ์› ์‹œ์Šคํ…œ(๋˜๋Š” ๊ฐ€์ƒ ๋ ˆํผ๋Ÿฐ์Šค)์ด\n * ๊ณต์ •๋ณ„ ์†Œ์š”ยท๋ณ€๋™ยท์ˆ˜์œจ์„ ๋งํ•ด ์ค˜์•ผ ์˜ˆ์ธก์ด ๊ทธ ํ˜„์žฅ์˜ ์˜ˆ์ธก์ด ๋œ๋‹ค. ์ฃผ์ง€ ์•Š์œผ๋ฉด ์ปค๋„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ\n * ๊ตด๋Ÿฌ๊ฐ€๊ณ , **๊ธฐ๋ณธ๊ฐ’์„ ์ผ๋‹ค๋Š” ์‚ฌ์‹ค์€ ์ปค๋„ `specCoverage()` ๊ฐ€ ๋ฐํžŒ๋‹ค**(์กฐ์šฉํžˆ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋Š”๋‹ค).\n */\nexport interface RefOperation {\n /** ์ž‘์—… ์ข…๋ฅ˜ ํ‚ค โ€” ์ปค๋„ `FlowTask.kind` ์™€ ๊ฐ™์€ ๊ฐ’์ด์–ด์•ผ ๋ช…์„ธ๊ฐ€ ๊ทธ ์ž‘์—…์— ๋ถ™๋Š”๋‹ค. */\n key: string\n label: string\n intent: 'transport' | 'process' | 'dwell'\n locationType?: string\n resourceType?: string\n bizStep?: string\n /** ISA-95 `OperationsSegment.Duration` โ€” ISO 8601 ๊ธฐ๊ฐ„(`PT12M`). */\n duration?: string\n variability?: RefOperationVariability\n parameters?: RefOperationParameter[]\n /**\n * ํ•„์š” ์ธ์› โ€” ISA-95 `PersonnelSpecification`(`PersonnelClassID` + `Quantity`) 1:1.\n * ์—†์œผ๋ฉด ์‚ฌ๋žŒ ์—†์ด ๋„๋Š” ๊ณต์ •์ด๋‹ค(์„ค๋น„๋งŒ ์žก๋Š”๋‹ค).\n */\n personnelSpecification?: { personnelClass?: string; quantity: number }[]\n /** ํ•„์š” ๋ฌผ๋ฆฌ ์ž์‚ฐ โ€” ISA-95 `PhysicalAssetSpecification`(๋“ฑ๊ธ‰ + ์ˆ˜๋Ÿ‰). ๋นˆ ํŒ”๋ ˆํŠธ๊ฐ€ ์—†์œผ๋ฉด ๋ชป ๋‚˜๊ฐ„๋‹ค. */\n physicalAssetSpecification?: { assetClass?: string; quantity: number }[]\n /**\n * ํ•„์š”ยท์‚ฐ์ถœ ์ž์žฌ โ€” ISA-95 `MaterialSpecification`. **4๋Œ€ ์ž์› ์ค‘ ์ž์žฌ๋งŒ ์ด ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค** โ€”\n * ๊ทธ๋ž˜์„œ ๋ถ€ํ’ˆ์ด ๋–จ์–ด์ ธ ๋ผ์ธ์ด ์„œ๋Š” ์ƒํ™ฉ์ด ์˜ˆ์ธก์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜๋‹ค.\n * BOM ์˜ \"๋ช‡ ๊ฐœ\" ๋Š” ์—ฌ๊ธฐ๋‹ค(ํ’ˆ๋ชฉ ์ •์˜์˜ ์กฐ๋ฆฝ ๊ตฌ์กฐ์—๋Š” ์ˆ˜๋Ÿ‰์ด ์—†๋‹ค โ€” 1์ฐจ ์ถœ์ฒ˜ ํ™•์ธ).\n */\n materialSpecification?: RefOpMaterialSpecification[]\n}\n\n/**\n * ์‚ฌ๋žŒ โ€” **ISA-95 `Person`.** ์„ค๋น„์™€ ๋ณ„๊ฐœ ์ž์›์ด๋‹ค(๊ณ ์žฅยท์„ค๋น„ํšจ์œจ์ด ์•„๋‹ˆ๋ผ ๋“ฑ๊ธ‰ยท๊ต๋Œ€๋กœ ์‚ฐ๋‹ค).\n * `personnelClass` ๊ฐ€ ISA-95 `PersonnelClassID` โ€” ๊ณต์ •์€ ํŠน์ •์ธ์ด ์•„๋‹ˆ๋ผ **๋“ฑ๊ธ‰์œผ๋กœ** ์ธ์›์„ ์š”๊ตฌํ•œ๋‹ค.\n */\nexport interface RefPerson {\n id: string\n name?: string\n /**\n * ์†ํ•œ ๋“ฑ๊ธ‰๋“ค โ€” **ํ‘œ์ค€ `Person.PersonnelClassID`, `maxOccurs=\"unbounded\"`**.\n * ๋ณต์ˆ˜์ธ ๊ฒƒ์ด ํ‘œ์ค€์ด๊ณ  ๊ทธ๊ฒƒ์ด ์ž๊ฒฉ ํ‘œํ˜„์ด๋‹ค: ํ•œ ์‚ฌ๋žŒ์ด ์šฉ์ ‘ ์ž๊ฒฉ๊ณผ ์ง€๊ฒŒ์ฐจ ์ž๊ฒฉ์„ ํ•จ๊ป˜ ๊ฐ–๋Š”๋‹ค.\n */\n personnelClassIds?: string[]\n /** ๊ต๋Œ€ โ€” ์„ค๋น„์™€ ๊ฐ™์€ ๋ชจ์–‘. ๋ฏธ์ง€์ •=24์‹œ๊ฐ„ ๊ฐ€์šฉ. */\n window?: { startHour: number; endHour: number }\n /** ๊ทผ๋ฌด ์บ˜๋ฆฐ๋” โ€” ํ‘œ์ค€ `WorkCalendarEntry`(๋ณต์ˆ˜). 2๊ต๋Œ€ยทํœด๊ฒŒยทํœด์ผ์„ ํ•จ๊ป˜ ํ‘œํ˜„ํ•œ๋‹ค. */\n workCalendar?: WorkCalendarEntry[]\n /**\n * ๊ธฐ๋ณธ ์œ„์น˜ โ€” ํ‘œ์ค€ `Person.OperationalLocation`. ์—†์œผ๋ฉด \"์ด ๋ผ์ธ์— ๋ช‡ ๋ช… ์žˆ๋‚˜\" ๋ฅผ ๋ฌผ์„ ์ˆ˜ ์—†๋‹ค.\n * ์‚ฌ๋žŒ์€ ์›€์ง์ด๋ฏ€๋กœ ์ด ๊ฐ’์€ **์ถœ๋ฐœ์ **์ด๊ณ , ์‹ค์ œ ์œ„์น˜๋Š” ๊ด€์ธก(person.status)์ด ๊ฐฑ์‹ ํ•œ๋‹ค.\n */\n homeLocationId?: string\n /**\n * ์ž์› ์†์„ฑ โ€” ํ‘œ์ค€ `PersonProperty`. **์ž๊ฒฉ์ฆยท์ˆ™๋ จ๋„๊ฐ€ ์—ฌ๊ธฐ ๋“ค์–ด๊ฐ„๋‹ค.**\n *\n * ํ‘œ์ค€์—๋Š” ์ž๊ฒฉ(Qualification)์ด๋ผ๋Š” ๋ณ„๋„ ์š”์†Œ๊ฐ€ ์—†๋‹ค(`B2MML-Personnel.xsd` ํ™•์ธ). ์ž๊ฒฉ์€\n * โ‘  ๋“ฑ๊ธ‰ ๋ณต์ˆ˜ ์†Œ์†์œผ๋กœ(`personnelClassIds: ['welder-certified','forklift-licensed']`) โ‘ก\n * ์ฆ๋น™์€ ์ด ์†์„ฑ์œผ๋กœ(์ž๊ฒฉ์ฆ ๋ฒˆํ˜ธยท๋งŒ๋ฃŒ์ผ), โ‘ข ๊ฒ€์ฆ ์‹œํ—˜์€ ํ‘œ์ค€ `TestSpecificationID`(์•„์ง ๋ฏธ๊ตฌํ˜„).\n */\n properties?: RefResourceProperty[]\n /** ์ž๊ฒฉ์„ ๊ฒ€์ฆํ•œ ์‹œํ—˜ ๋ช…์„ธ๋“ค โ€” ํ‘œ์ค€ `TestSpecificationID`(์ฐธ์กฐ๋งŒ; ์‹œํ—˜ ๋ช…์„ธยท๊ฒฐ๊ณผ ๋ชจ๋ธ์€ ์•„์ง ์—†๋‹ค). */\n testSpecificationIds?: string[]\n /** ์œ ํšจ ๊ธฐ๊ฐ„ โ€” ์‚ฌ๋žŒ์—๊ฒŒ๋Š” **์ž…์‚ฌ ์ „ยทํ‡ด์‚ฌ ํ›„**๋‹ค(์ž๊ฒฉ ๋งŒ๋ฃŒ๋Š” ๋“ฑ๊ธ‰ ์ชฝ ๊ธฐ๊ฐ„์ด๋‹ค: ์‚ฌ๋žŒ์€ ๋‚จ๊ณ  ์ž๊ฒฉ๋งŒ ๋Š๊ธด๋‹ค). */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\n/**\n * ๋ฌผ๋ฆฌ ์ž์‚ฐ(๋ฐ˜๋ณต์‚ฌ์šฉ) โ€” **ISA-95 `PhysicalAsset`, GS1 `GRAI`.**\n * ํŒ”๋ ˆํŠธยท๋ž™ยท์šฉ๊ธฐ์ฒ˜๋Ÿผ **๋‚˜๊ฐ”๋‹ค ๋Œ์•„์˜ค๋Š”** ๊ฒƒ. ๋ฌผ๋ฅ˜๋‹จ์œ„(SSCC)์™€ ๋‹ค๋ฅด๋‹ค: SSCC ๋Š” ๊ทธ ํŒ”๋ ˆํŠธ์— ์‹ค๋ฆฐ ํ™”๋ฌผ\n * ํ•œ ๋ฉ์–ด๋ฆฌ์ด๊ณ , GRAI ๋Š” ํŒ”๋ ˆํŠธ ์ž์ฒด๋‹ค(์˜ค๋Š˜์€ ์ด ํ™”๋ฌผ, ๋‚ด์ผ์€ ์ € ํ™”๋ฌผ์„ ์‹ฃ๋Š”๋‹ค).\n */\nexport interface RefAsset {\n id: string\n name?: string\n /**\n * ์†ํ•œ ๋“ฑ๊ธ‰๋“ค โ€” ํ‘œ์ค€ `PhysicalAssetClassID`(๋ณต์ˆ˜). ํŒ”๋ ˆํŠธ๊ฐ€ 'euro-pallet' ์ด๋ฉด์„œ 'food-grade' ์ผ ์ˆ˜ ์žˆ๋‹ค.\n * ๊ณต์ •์˜ ์š”๊ตฌ๋Š” ๋“ฑ๊ธ‰ ํ•˜๋‚˜ + ์ˆ˜๋Ÿ‰์ด๋‹ค(ํ‘œ์ค€ `PhysicalAssetSpecification`).\n */\n assetClassIds?: string[]\n /** ๊ธฐ๋ณธ ์œ„์น˜. */\n homeLocationId?: string\n /** ์ •์‹ GS1 ์ •์ฒด์„ฑ โ€” ๋ฐ˜๋ณต์‚ฌ์šฉ ์ž์‚ฐ=GRAI. */\n gs1Id?: string\n /** ์ž์› ์†์„ฑ โ€” ํ‘œ์ค€ `PhysicalAssetProperty`(์ ์žฌ ํ•œ๋„ยท๊ทœ๊ฒฉ ๋“ฑ). */\n properties?: RefResourceProperty[]\n /** ์ ๊ฒฉ์„ ๊ฒ€์ฆํ•œ ์‹œํ—˜ ๋ช…์„ธ๋“ค โ€” ํ‘œ์ค€ `TestSpecificationID`. */\n testSpecificationIds?: string[]\n /** ์œ ํšจ ๊ธฐ๊ฐ„ โ€” ์ž์‚ฐ์—์„œ๋Š” **ํ๊ธฐํ•œ ํŒ”๋ ˆํŠธ๊ฐ€ ํ’€์—์„œ ๋น ์ง€๋Š” ๊ฒƒ**์ด๋‹ค(ํšŒ์ˆ˜ ๋Œ€์ƒ ์ˆ˜๊ฐ€ ๋ถ€ํ’€์ง€ ์•Š๊ฒŒ). */\n effectiveStart?: string\n effectiveEnd?: string\n}\n\n/**\n * ํ’ˆ๋ชฉ ์ •์˜ โ€” **ISA-95 `MaterialDefinition`.**\n *\n * ์—†์œผ๋ฉด ๋กœํŠธ๋งŒ ๊ด€์ธก์œผ๋กœ ๋“ค์–ด์˜ค๊ณ  **ํ’ˆ๋ชฉ์ด ๋ฌด์—‡์ธ์ง€๋Š” ์•„๋ฌด ๋ฐ๋„ ์—†๋‹ค.** ๊ทธ๋ž˜์„œ ๊ฐ™์€ ๋กœํŠธ๋ฅผ 100๊ฐœ๋กœ\n * ๋ฐ›์•„๋„ \"๋ช‡ kg ์ธ๊ฐ€\" ์— ๋‹ตํ•  ์ˆ˜ ์—†๋‹ค(์ปค๋„ `quantityIn` ์ด ํ™˜์‚ฐ์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๊ทผ๊ฑฐ).\n *\n * **ํ‘œ์ค€์— ๋‹จ์œ„ ํ™˜์‚ฐ ์š”์†Œ๋Š” ์—†๋‹ค**(1์ฐจ ์ถœ์ฒ˜ ์ „์ˆ˜ ํ™•์ธ) โ€” ์†์„ฑ ์ฃผ๋จธ๋‹ˆ๋ฟ์ด๋‹ค. ๊ทธ๋ž˜์„œ ํ™˜์‚ฐ ๊ณ„์ˆ˜๋Š”\n * ์ปค๋„์ด ์ •ํ•œ ์†์„ฑ ์ด๋ฆ„(`perBaseUnit`, `uom` ์ด ๋Œ€์ƒ ๋‹จ์œ„)์œผ๋กœ `properties` ์— ์‹ฃ๋Š”๋‹ค.\n */\nexport interface RefMaterialDefinition {\n /** ํ‘œ์ค€ `ID` โ€” GTIN(`urn:epc:idpat:sgtin:โ€ฆ`)์„ ์“ด๋‹ค(์ •์ฒด์„ฑ์˜ ์ •๋ณธ์ด EPCIS ๋‹ค). */\n id: string\n name?: string\n /** ์†ํ•œ ๋“ฑ๊ธ‰๋“ค โ€” ํ‘œ์ค€ `MaterialClassID`(๋ณต์ˆ˜). */\n materialClassIds?: string[]\n /** ํ’ˆ๋ชฉ ์†์„ฑ โ€” ํ‘œ์ค€ `MaterialDefinitionProperty`. ํ™˜์‚ฐ ๊ณ„์ˆ˜๊ฐ€ ์—ฌ๊ธฐ ๋“ค์–ด๊ฐ„๋‹ค. */\n properties?: RefResourceProperty[]\n testSpecificationIds?: string[]\n effectiveStart?: string\n effectiveEnd?: string\n}\n\nexport interface ReferenceMaster {\n source: string\n system: 'wms' | 'yms' | 'mes'\n siteName: string\n /* spaceId ๋ช…์‹œ ์‹œ ๊ทธ ๊ณต๊ฐ„์„ ์ฐธ์กฐ(์—ฌ๋Ÿฌ ํŠธ์œˆ์ด ํ•œ ๊ณต๊ฐ„ ๊ณต์œ , N:1). ์—†์œผ๋ฉด source ์—์„œ ํŒŒ์ƒ(1:1). */\n /**\n * ํ˜„์žฅ(๊ณต๊ฐ„). **์‹œ๊ฐ ๊ธฐ์ค€(`timezone`)์ด ์—ฌ๊ธฐ ์žˆ๋Š” ์ด์œ **: ํ•œ ํ…Œ๋„ŒํŠธ๊ฐ€ Rosarito(ํƒœํ‰์–‘)์™€ ํ•œ๊ตญ\n * ๊ณต์žฅ์„ ํ•จ๊ป˜ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. ํ…Œ๋„ŒํŠธ ๋‹จ์œ„(`Domain.timezone`)๋กœ ๋‘๋ฉด **๋‘˜ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ˜๋“œ์‹œ ํ‹€๋ฆฐ๋‹ค.**\n * ์‹œ๊ฐ ๊ธฐ์ค€์€ **๋ฌผ๋ฆฌ ํ˜„์žฅ์˜ ์„ฑ์งˆ**์ด๋ฏ€๋กœ ๊ณต๊ฐ„์ด ๊ทธ๊ฒƒ์„ ๊ฐ–๋Š”๋‹ค(๊ณต๊ฐ„ ์ค‘์‹ฌ ์›์น™).\n *\n * `timezone` ์€ IANA ์ด๋ฆ„(`'America/Tijuana'`) โ€” ์˜คํ”„์…‹ ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ˆซ์ž๋กœ ๋‘๋ฉด ์ผ๊ด‘์ ˆ์•ฝ์‹œ๊ฐ„์„\n * ํ‘œํ˜„ํ•  ์ˆ˜ ์—†๊ณ , ๋‚˜์ค‘์— ์ ˆ๋Œ€ ๊ตฌ๊ฐ„์œผ๋กœ ์˜ฎ๊ธธ ๋•Œ๋„ ์ด๋ฆ„์ด ์žˆ์–ด์•ผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.\n */\n space: { spaceId?: string; width: number; depth: number; unit?: string; timezone?: string; geo?: { lat: number; lon: number; rotation?: number }; representations?: any[]; primaryId?: string }\n locations: RefLocation[]\n equipment?: RefEquipment[]\n /** ๊ณต์ • ๋ช…์„ธ(์†Œ์š”ยท๋ณ€๋™ยท์ˆ˜์œจ) โ€” ์—†์œผ๋ฉด ์ปค๋„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๊ตด๋Ÿฌ๊ฐ„๋‹ค(๊ทธ ์‚ฌ์‹ค์€ specCoverage ๊ฐ€ ๋ณด๊ณ ). */\n operations?: RefOperation[]\n /**\n * **์ƒ์‚ฐ ์ •์˜**(๋ ˆ์‹œํ”ผยท๋ผ์šฐํŠธยท์ž์žฌ ๋ฐ”์ธ๋”ฉ) โ€” ์ปค๋„์˜ ์ •์˜-๊ตฌ๋™ MES ๋ชจ๋“œ ์ž…๊ตฌ.\n *\n * ์—†์œผ๋ฉด ์ปค๋„์€ ๋ ˆ๊ฑฐ์‹œ(ํ•˜๋“œ์ฝ”๋”ฉ) ํ๋ฆ„์œผ๋กœ ๋ˆ๋‹ค. ์ฆ‰ **ํ˜„์žฅ ๋ ˆ์‹œํ”ผ๋ฅผ ์ ์–ด๋„ ์ด ์ž๋ฆฌ์— ์‹ค๋ฆฌ์ง€ ์•Š์œผ๋ฉด\n * ์ปค๋„์€ ๊ทธ๊ฒƒ์„ ๋ณด์ง€ ๋ชปํ•œ๋‹ค** โ€” ์„ ์–ธ๊ณผ ์‹คํ–‰์ด ๊ฐˆ๋ผ์ง€๋Š” ์ง€์ ์ด๋ผ ์ž๋ฆฌ๋ฅผ ์—ฐ๋‹ค.\n */\n /**\n * ์ƒ์‚ฐ ์„ ์–ธ โ€” `BoardDef.productionSpec` ์œผ๋กœ ํ†ต๊ณผํ•œ๋‹ค(ISA-95 OperationsSegment + BOM).\n *\n * ์˜ˆ์ „ ์ด๋ฆ„์€ `mesSpec` ์ด์—ˆ๋‹ค. ๋‹ด๊ธด ๊ฒƒ์€ MES ๋งŒ์˜ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ \"์ž์žฌ๋ฅผ ์†Œ๋น„ํ•ด ์ž์žฌ๋ฅผ ์‚ฐ์ถœํ•˜๋Š”\n * ๊ณต์ •\" ์ด๊ณ , ์ด๋ฆ„์ด MES ์˜€๊ธฐ ๋•Œ๋ฌธ์— ์ฐฝ๊ณ  ํŠธ์œˆ์€ ์ด ์ž๋ฆฌ๋ฅผ ์“ธ ์ƒ๊ฐ์กฐ์ฐจ ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค(์œ ํ†ต๊ฐ€๊ณต ์ฐฝ๊ณ ๊ฐ€\n * BOM ์„ ์„ค๋ช… ๋ฌธ์„œ์—๋งŒ ์ ์–ด ๋‘” ์ฑ„ ํ‚คํŠธ๋ฅผ ๋ชป ๋งŒ๋“œ๋Š” ํŠธ์œˆ์„ ๋งŒ๋“  ์›์ธ). ๊ทผ๊ฑฐ๋Š” ์ปค๋„ ๊ณ„์•ฝ ์ฃผ์„์—.\n */\n productionSpec?: unknown\n /**\n * ์‚ฌ๋žŒ โ€” ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ฉด **์ธ์› ์ œ์•ฝ์ด ์—†๋Š” ํŠธ์œˆ**์ด ๋œ๋‹ค(์„ค๋น„๋งŒ ์žˆ์œผ๋ฉด ์–ธ์ œ๋‚˜ ๋Œ์•„๊ฐ€๋Š” ๊ณต์žฅ).\n * ๊ณต์ •์ด ์ธ์›์„ ์š”๊ตฌํ•˜๋Š”๋ฐ ์‚ฌ๋žŒ์ด ์—†์œผ๋ฉด ๊ทธ ์ž‘์—…์€ ์‹œ์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค โ€” ๊ทธ๊ฒƒ์ด ์‚ฌ์‹ค์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค.\n */\n persons?: RefPerson[]\n /**\n * ๋ฌผ๋ฆฌ ์ž์‚ฐ(๋ฐ˜๋ณต์‚ฌ์šฉ) โ€” ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ฉด ์ž์‚ฐ ์ œ์•ฝ์ด ์—†๋Š” ํŠธ์œˆ์ด๋‹ค.\n * ๊ณต์ •์ด ์ž์‚ฐ์„ ์š”๊ตฌํ•˜๋Š”๋ฐ ์—†์œผ๋ฉด ๊ทธ ์ž‘์—…์€ ์‹œ์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค โ€” ๊ทธ๊ฒƒ์ด ์‚ฌ์‹ค์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค.\n */\n assets?: RefAsset[]\n /**\n * ๋“ฑ๊ธ‰ ์ •์˜ โ€” ํ‘œ์ค€ `PersonnelClass`ยท`EquipmentClass`ยท`PhysicalAssetClass`.\n * ์•ˆ ์‹ค์–ด๋„ ํŠธ์œˆ์€ ๋ˆ๋‹ค(์†Œ์† ๋ฌธ์ž์—ด ๊ทธ๋Œ€๋กœ ํŒ์ •). ์‹ค์œผ๋ฉด ์ƒ์†ยท์œ ํšจ๊ธฐ๊ฐ„์ด ์‚ด์•„๋‚œ๋‹ค.\n */\n personnelClasses?: RefResourceClass[]\n equipmentClasses?: RefResourceClass[]\n assetClasses?: RefResourceClass[]\n /** ํ’ˆ๋ชฉ ์ •์˜ยท๋“ฑ๊ธ‰ โ€” ํ‘œ์ค€ `MaterialDefinition` / `MaterialClass`. ์—†์œผ๋ฉด ๋‹จ์œ„ ํ™˜์‚ฐ์„ ํ•  ์ˆ˜ ์—†๋‹ค. */\n materialDefinitions?: RefMaterialDefinition[]\n materialClasses?: RefResourceClass[]\n}\n\nexport interface IngestedTwin {\n board: any // BoardDef(+layout+spaceId) โ€” ์ปค๋„ ์†Œ๋น„\n spaceContent: any // TwinSpace content โ€” ๋ทฐ ์†Œ๋น„\n warnings: IngestWarning[]\n}\n\n/**\n * ๋งˆ์Šคํ„ฐ โ†’ ํŠธ์œˆ ๊ตฌ์กฐ ๋งคํ•‘(์ˆœ์ˆ˜). ๋…ธ๋“œํƒ€์ž…์„ ์นดํƒˆ๋กœ๊ทธ๋กœ ๊ฒ€์ฆ(๋ชจ๋ฅด๋Š” ํƒ€์ž…์€ warning, ๋ฒ„๋ฆฌ์ง„ ์•Š์Œ โ€” ๋ฐ˜์˜ ์šฐ์„ ).\n * @param catalog DOMAIN_CATALOG (์ปค๋„ SSOT). ์—†์œผ๋ฉด ๊ฒ€์ฆ ์ƒ๋žต.\n */\n/**\n * IANA ์‹œ๊ฐ„๋Œ€ ์ด๋ฆ„ โ†’ **๊ทธ ์‹œ๊ฐ์˜** UTC ์˜คํ”„์…‹(๋ถ„). ์˜์กด์„ฑ ์—†์ด `Intl` ๋กœ ํ‘ผ๋‹ค.\n *\n * `Intl.DateTimeFormat` ์˜ `longOffset` ์€ `\"GMT-07:00\"` ์ฒ˜๋Ÿผ ๋‚˜์˜ค๊ณ , ์ด๊ฒƒ์€ **์ผ๊ด‘์ ˆ์•ฝ์‹œ๊ฐ„์„ ๋ฐ˜์˜ํ•œ**\n * ๊ฐ’์ด๋‹ค. ๊ทธ๋ž˜์„œ 8์›”์˜ `America/Tijuana` ๋Š” โˆ’420(PDT), 1์›”์€ โˆ’480(PST)์ด ๋œ๋‹ค.\n *\n * **ํ•œ๊ณ„๋ฅผ ๋ฐํžŒ๋‹ค**: ์—ฌ๊ธฐ์„œ ๋‚˜์˜ค๋Š” ๊ฒƒ์€ **ํ•œ ์‹œ์ ์˜** ์˜คํ”„์…‹์ด๋‹ค. ์ปค๋„์€ ๊ณ ์ • ์˜คํ”„์…‹์œผ๋กœ ํ•˜๋ฃจ ์ค‘ ๋ถ„์„\n * ์ฝ์œผ๋ฏ€๋กœ, ๋ณด๋“œ๋ฅผ ๋งŒ๋“  ๊ณ„์ ˆ๊ณผ ๋‹ค๋ฅธ ๊ณ„์ ˆ์„ ๊ธธ๊ฒŒ ์˜ˆ์ธกํ•˜๋ฉด ํ•œ ์‹œ๊ฐ„ ์–ด๊ธ‹๋‚œ๋‹ค. ํ‘œ์ค€์— ์ถฉ์‹คํ•œ ๋ ๋ชจ์Šต์€\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ์ ˆ๋Œ€ ๊ตฌ๊ฐ„(`StartDateTime`/`FinishDateTime`)์„ ๊ณ„์‚ฐํ•ด ๋„ฃ๋Š” ๊ฒƒ์ด๊ณ , ๊ทธ๋•Œ ์ด ํ•จ์ˆ˜๋Š” ์‚ฌ๋ผ์ง„๋‹ค.\n *\n * ๋ชจ๋ฅด๋Š” ์ด๋ฆ„์—๋Š” **0 ์„ ๋‹ตํ•˜์ง€ ์•Š๋Š”๋‹ค**(`undefined`) โ€” 0 ์€ \"UTC ๋ผ๊ณ  ์„ ์–ธํ–ˆ๋‹ค\" ๋Š” ๋œป์ด๊ณ , ๋ชจ๋ฅด๋Š” ๊ฒƒ์„\n * ๊ทธ๋ ‡๊ฒŒ ๋ฐ”๊พธ๋ฉด ํŒ์ •์ด ์กฐ์šฉํžˆ ํ‹€๋ฆฐ๋‹ค.\n */\nexport function utcOffsetOf(timezone?: string, at: Date = new Date()): number | undefined {\n if (!timezone) return undefined\n try {\n const parts = new Intl.DateTimeFormat('en-US', { timeZone: timezone, timeZoneName: 'longOffset' }).formatToParts(at)\n const name = parts.find(p => p.type === 'timeZoneName')?.value ?? ''\n if (name === 'GMT') return 0 // UTC ๊ณ„์—ด์€ ์˜คํ”„์…‹ ํ‘œ๊ธฐ๊ฐ€ ์—†๋‹ค\n const m = /^GMT([+-])(\\d{1,2})(?::(\\d{2}))?$/.exec(name)\n if (!m) return undefined\n const sign = m[1] === '-' ? -1 : 1\n return sign * (Number(m[2]) * 60 + Number(m[3] ?? 0))\n } catch {\n return undefined // ์•Œ ์ˆ˜ ์—†๋Š” ์ด๋ฆ„ โ€” Intl ์ด ๋˜์ง„๋‹ค\n }\n}\n\n\n/* โ”€โ”€ ์ธ์ œ์ŠคํŠธ ๊ฒฝ๊ณ  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ธ์ œ์ŠคํŠธ๋Š” ๊ตฌ์กฐ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด๋„ ํŠธ์œˆ์„ ๋งŒ๋“ค์–ด ์ค€๋‹ค(๋ง‰์ง€ ์•Š๋Š” ๊ฒƒ์ด ์˜ณ๋‹ค โ€” ๋ถ€๋ถ„์ ์œผ๋กœ๋ผ๋„ ์„ธ์šฐ๊ณ \n * ๊ณ ์ณ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์ด ์ด ์‹œ์Šคํ…œ์˜ ๋ฐฉ์‹์ด๋‹ค). ๊ทธ๋ž˜์„œ **๊ฒฝ๊ณ ๊ฐ€ ์œ ์ผํ•œ ์‹ ํ˜ธ**์ธ๋ฐ, ๊ทธ ๊ฒฝ๊ณ ๋ฅผ ํ™”๋ฉด์ด ํ•˜๋‚˜๋„\n * ๋ณด์—ฌ์ฃผ์ง€ ์•Š๊ณ  ์žˆ์—ˆ๋‹ค: ์œ ํ†ต๊ฐ€๊ณต ์ฐฝ๊ณ  ํ…œํ”Œ๋ฆฟ์€ ์ปค๋„์ด ๋ชจ๋ฅด๋Š” ์ž๋ฆฌ ํƒ€์ž…(`vas-station`)์œผ๋กœ ํŠธ์œˆ์„\n * ๋งŒ๋“ค๋ฉด์„œ ๊ฒฝ๊ณ ๋ฅผ ๋ƒˆ์ง€๋งŒ, ์œ„์ž๋“œ๋Š” ๊ทธ๊ฒƒ์„ ๋ฒ„๋ ธ๊ณ  ์‚ฌ์šฉ์ž๋Š” ์•„๋ฌด ๋ง ์—†์ด ๋ง‰ํžˆ๋Š” ํŠธ์œˆ์„ ๋ฐ›์•˜๋‹ค.\n *\n * ๋ฌธ์žฅ์ด ์•„๋‹ˆ๋ผ ์ฝ”๋“œ๋กœ ์‹ค์–ด ๋ณด๋‚ธ๋‹ค. ์˜ˆ์ „ ๊ฒฝ๊ณ ๋Š” ํ”„๋กœ์ฆˆ์˜€๊ณ  ๊ทธ์ค‘ ํ•˜๋‚˜์—๋Š” ํ•œ๊ธ€์ด ์„ž์—ฌ ์žˆ์—ˆ๋‹ค\n * (`โ€” ์นดํƒˆ๋กœ๊ทธ์— ์—†์Œ`) โ€” ๋‹ค์„ฏ ์–ธ์–ด ํ™”๋ฉด์— ๊ทธ๋Œ€๋กœ ๋‚ด๋ณด๋‚ด๋ฉด ์ด๋ฒˆ์— ๊ฑท์–ด๋‚ธ ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ ๋‹ค.\n * ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ์ด๋ฏธ ์“ฐ๋Š” ๊ทœ์•ฝ๊ณผ ๊ฐ™์€ ๋ชจ์–‘์ด๋‹ค: ์ฃผ์˜ ์‹ ํ˜ธ(kind+params)ยท์ปค๋งจ๋“œ ๊ฑฐ์ ˆ(errorCode+params)ยท\n * ๋งŒ๋งŒํ•จ ํŒ์ •(code+์˜์–ด canonical message).\n *\n * code ์–ธ์–ด ์ค‘๋ฆฝ โ€” ํ™”๋ฉด์ด `twin.ingest.<code>` ๋กœ ์‚ฌ๋žŒ ๋ง์„ ๋งŒ๋“ ๋‹ค\n * params ๋ฌธ์žฅ์— ๋ผ์šธ ๊ฐ’ โ€” ๋ฒˆ์—ญ์ด ์–ธ์–ด๋งˆ๋‹ค ์–ด์ˆœ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๊ฒŒ\n * message ์˜์–ด canonical โ€” ๋กœ๊ทธ์— ๋‚จ๊ณ , ๋ฒˆ์—ญ์ด ์—†์„ ๋•Œ ๊ทธ๋Œ€๋กœ ๋ณด์ธ๋‹ค(๋นˆ์นธ๋ณด๋‹ค ๋‚ซ๋‹ค)\n *\n * **์—ฌ๊ธฐ ์‚ฌ๋Š” ์ด์œ **: ์ด ํŒŒ์ผ์ด ๊ฒฝ๊ณ ์˜ ์ƒ์‚ฐ์ž์ด๊ณ , ํ…Œ์ŠคํŠธ๊ฐ€ ์†Œ์Šค์—์„œ ์ง์ ‘ ์ฝ๋Š” ๋ชจ๋“ˆ์ด๋ผ\n * ๋Ÿฐํƒ€์ž„ ์ƒ๋Œ€ import ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๋‹ค(์ด ์ €์žฅ์†Œ์˜ ๊ทœ์•ฝ โ€” ๊ทธ๋Ÿฐ ๋ชจ๋“ˆ์€ ์ž๊ธฐ์™„๊ฒฐ์ด๋‹ค).\n * โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n/** ์ธ์ œ์ŠคํŠธ๊ฐ€ ์•Œ๋ฆฌ๋Š” ํ•œ ๊ฐ€์ง€. */\nexport interface IngestWarning {\n /** ์–ธ์–ด ์ค‘๋ฆฝ ์ฝ”๋“œ. ํ™”๋ฉด์€ `twin.ingest.<code>` ๋กœ ๋ Œ๋”ํ•œ๋‹ค. */\n code: string\n /** ๋ฌธ์žฅ์— ๋ผ์šธ ๊ฐ’. ๋ฒˆ์—ญ์ด ์–ด์ˆœ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๊ฒŒ ์ด๋ฆ„์œผ๋กœ ๋„˜๊ธด๋‹ค. */\n params?: Record<string, string | number>\n /** ์˜์–ด canonical ๋ฌธ์žฅ โ€” ๋กœ๊ทธยทํด๋ฐฑ์šฉ. ๋ฒˆ์—ญ์ด ์—†์–ด๋„ ์ฝ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. */\n message: string\n}\n\n/** ์ปค๋„ ์นดํƒˆ๋กœ๊ทธ๊ฐ€ ๋ชจ๋ฅด๋Š” ์ž๋ฆฌ ํƒ€์ž… โ€” ๊ทธ ์ž๋ฆฌ๋Š” ํ๋ฆ„์— ์ฐธ์—ฌํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค. */\nexport const unknownLocationType = (system: string, type: string, id: string): IngestWarning => ({\n code: 'unknown-location-type',\n params: { system, type, id },\n message: `\"${type}\" is not a known ${system} location type (${id}) โ€” the kernel may not include this location in the flow`\n})\n\n/** ์‹œ๊ฐ„๋Œ€ ๋ฌธ์ž์—ด์„ ๋ชป ์ฝ์—ˆ๋‹ค โ€” ์‹œ๊ฐ ํ•ด์„์ด UTC ๋กœ ๋–จ์–ด์ง„๋‹ค(์กฐ์šฉํžˆ ํ˜„์ง€ ์‹œ๊ฐ์œผ๋กœ ๊ฐ€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค). */\nexport const unknownTimezone = (timezone: string): IngestWarning => ({\n code: 'unknown-timezone',\n params: { timezone },\n message: `space timezone \"${timezone}\" is not a known IANA zone โ€” the twin will read times as UTC`\n})\n\n/** ์ž‘์—… ์ •์˜์— ์†Œ์š”์‹œ๊ฐ„ยทํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋‹ค โ€” ์ปค๋„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋ˆ๋‹ค. */\nexport const operationWithoutDuration = (operation: string): IngestWarning => ({\n code: 'operation-without-duration',\n params: { operation },\n message: `operation \"${operation}\" has no duration or parameters โ€” kernel defaults will be used`\n})\n\n/** ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ‘œํ˜„์ด ์—†๋‹ค โ€” ํ˜„์žฅ์ด ํ™”๋ฉด์— ๋œจ์ง€ ์•Š๋Š”๋‹ค. */\nexport const noViewableRepresentation = (): IngestWarning => ({\n code: 'no-viewable-representation',\n message: 'the space has no viewable representation (no representations and no geo) โ€” add one, or provide geo/board'\n})\n\n/** ํ•ฉ์น˜๋Š” ๊ณต๊ฐ„์— ๊ฐ™์€ id ์˜ ๋žœ๋“œ๋งˆํฌ๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค โ€” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์ด ํ•˜๋‚˜๋กœ ์ ‘ํ˜”์„ ์ˆ˜ ์žˆ๋‹ค. */\nexport const landmarkIdsMerged = (spaceId: string, ids: readonly string[]): IngestWarning => ({\n code: 'landmark-ids-merged',\n params: { spaceId, ids: ids.join(', '), count: ids.length },\n message: `landmark ids already present in space \"${spaceId}\" โ€” merged: ${ids.join(', ')}`\n})\n\n/** ๋กœ๊ทธ ํ•œ ์ค„ โ€” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์˜์–ด canonical ๋ฌธ์žฅ์„ ์“ด๋‹ค. */\nexport const describeWarnings = (warnings: readonly IngestWarning[]): string =>\n warnings.map(w => `${w.code}: ${w.message}`).join(' | ')\n\n/**\n * ์„œ๋ฒ„๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฑ„์šด ๋…ธ๋ธŒ๋“ค โ€” ์‚ฌ์šฉ์ž๊ฐ€ ์ค€ ์  ์—†๋Š” ๊ฐ’์œผ๋กœ ํŠธ์œˆ์ด ๋งŒ๋“ค์–ด์กŒ์Œ์„ ์•Œ๋ฆฐ๋‹ค.\n *\n * ์กฐ์šฉํžˆ ์ฑ„์šฐ๋ฉด ๋‚˜์ค‘์— \"์™œ ์ด ์ˆ˜์น˜์ธ๊ฐ€\" ๋ฅผ ์•„๋ฌด๋„ ๋‹ตํ•  ์ˆ˜ ์—†๋‹ค. ๋ง‰์„ ์ผ์€ ์•„๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’์€ ํ…œํ”Œ๋ฆฟ์ด\n * ํ™•์‹ ์„ ๊ฐ–๊ณ  ์„ ์–ธํ•œ ๊ฐ’์ด๋‹ค) โ€” ๋‹ค๋งŒ ๋ฐํžŒ๋‹ค.\n */\nexport const knobDefaultsFilled = (keys: readonly string[]): IngestWarning => ({\n code: 'knob-defaults-filled',\n params: { keys: keys.join(', '), count: keys.length },\n message: `values you did not provide were filled from the template defaults: ${keys.join(', ')}`\n})\n\nexport function masterToTwin(master: ReferenceMaster, catalog?: any): IngestedTwin {\n const warnings: IngestWarning[] = []\n const known: string[] = catalog?.[master.system]?.locationTypes ?? []\n\n const locationEntries = master.locations.filter(l => l.role === 'location' || l.role === 'both')\n const areaLocs = master.locations.filter(l => l.role === 'area' || l.role === 'both')\n\n const locations = locationEntries.map(l => {\n if (known.length && !known.includes(l.type)) warnings.push(unknownLocationType(master.system, l.type, l.id))\n // gs1Id(์ •์‹ ์ •์ฒด์„ฑ)๋ฅผ ๋ณด๋“œ ๋…ธ๋“œ๋กœ ํ†ต๊ณผ โ€” ๊ฒฐํ•ฉ(tag)/์ถ”์ ์ด GS1 ๋กœ(ยงJ). ๋กœ์ปฌ id ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€(name/xref).\n return { id: l.id, type: l.type, capacity: l.capacity ?? 0, ...(l.parallelism !== undefined ? { parallelism: l.parallelism } : {}), ...(l.level ? { level: l.level } : {}), parentId: l.parentId, gs1Id: l.gs1Id }\n })\n\n const equipment = (master.equipment ?? []).map(e => ({\n id: e.id, kind: e.kind, homeLocation: e.homeLocationId, mtbfMs: e.mtbfMs, mttrMs: e.mttrMs, gs1Id: e.gs1Id,\n ...(e.window ? { window: e.window } : {}),\n /* ์†์„ฑ์€ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ์ด๋™์‹œ๊ฐ„ ์ถ”์ •๊ธฐ๊ฐ€ kind ๋ณ„ ์†๋„๋ฅผ ์—ฌ๊ธฐ์„œ ์ฝ๋Š”๋‹ค(๋‹จ์œ„ ์ฝ”๋“œ ๊ทธ๋Œ€๋กœ). */\n ...(e.properties?.length ? { properties: e.properties } : {}), ...(e.workCalendar?.length ? { workCalendar: e.workCalendar } : {}), ...(e.testSpecificationIds?.length ? { testSpecificationIds: e.testSpecificationIds } : {}),\n /* ์œ ํšจ ๊ธฐ๊ฐ„๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ํŒ์ •์€ ์ปค๋„์ด ์ž๊ธฐ ์‹œ๊ณ„๋กœ ํ•œ๋‹ค(ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ฏธ๋ฆฌ ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค). */\n ...(e.effectiveStart ? { effectiveStart: e.effectiveStart } : {}), ...(e.effectiveEnd ? { effectiveEnd: e.effectiveEnd } : {})\n }))\n\n // ์ขŒํ‘œ(layout) โ€” footprint ์ค‘์‹ฌ. ์—†์œผ๋ฉด ์ƒ๋žต(coordinate-free ์œ ์ง€).\n const layout: Record<string, { x: number; y: number }> = {}\n for (const l of locationEntries) if (l.footprint) layout[l.id] = { x: l.footprint.x + l.footprint.w / 2, y: l.footprint.y + l.footprint.h / 2 }\n\n const spaceId = master.space.spaceId ?? `${master.source}-site`\n /*\n * ์‹œ๊ฐ ๊ธฐ์ค€์„ ์ปค๋„์ด ์ฝ์„ ํ˜•ํƒœ๋กœ ํ‘ผ๋‹ค โ€” ์ปค๋„์€ zero-dep ์ด๋ผ ์‹œ๊ฐ„๋Œ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋“ค์ด์ง€ ์•Š๊ณ \n * **๋ถ„ ์˜คํ”„์…‹**๋งŒ ๋ฐ›๋Š”๋‹ค(๊ณ„์•ฝ `BoardDef.utcOffsetMinutes`). ํ‘ธ๋Š” ์ผ์€ ํ˜ธ์ŠคํŠธ์˜ ๋ชซ์ด๋‹ค.\n *\n * ์„ ์–ธ์ด ์—†์œผ๋ฉด **ํ•„๋“œ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ทธ๋Ÿฌ๋ฉด ์ปค๋„์ด UTC ๋กœ ์ฝ๊ณ , ๊ทธ ๊ธฐ๋ณธ๊ฐ’์€ ๊ณ„์•ฝ์— ๋ฐํ˜€์ ธ ์žˆ๋‹ค.\n * ์—ฌ๊ธฐ์„œ 0 ์„ ๋„ฃ์œผ๋ฉด \"UTC ๋ผ๊ณ  ์„ ์–ธํ–ˆ๋‹ค\" ์™€ \"์„ ์–ธํ•˜์ง€ ์•Š์•˜๋‹ค\" ๊ฐ€ ๊ตฌ๋ณ„๋˜์ง€ ์•Š๋Š”๋‹ค.\n */\n const utcOffsetMinutes = utcOffsetOf(master.space.timezone)\n if (master.space.timezone && utcOffsetMinutes === undefined) {\n warnings.push(unknownTimezone(String(master.space.timezone)))\n }\n /*\n * ์˜คํผ๋ ˆ์ด์…˜ ๋ช…์„ธ๋ฅผ board ์— ํ†ต๊ณผ์‹œํ‚จ๋‹ค โ€” ์ปค๋„์ด `loadOperations` ๋กœ ์†Œ๋น„ํ•œ๋‹ค(BoardDef ํ™•์žฅ ํ•„๋“œ,\n * ๋ชจ๋ฅด๋Š” ์ปค๋„์€ ๋ฌด์‹œ). ์—ฌ๊ธฐ์„œ ๊ฐ’์„ ์†๋Œ€์ง€ ์•Š๋Š”๋‹ค: ๊ธฐ๊ฐ„์€ ํ‘œ์ค€ ํ‘œ๊ธฐ(ISO 8601)๋กœ ์ปค๋„๊นŒ์ง€ ๊ทธ๋Œ€๋กœ ๊ฐ„๋‹ค.\n */\n const operations = master.operations\n if (operations?.length) {\n for (const o of operations) {\n if (!o.duration && !o.parameters?.length) warnings.push(operationWithoutDuration(o.key))\n }\n }\n /* ์‚ฌ๋žŒ๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๋“ฑ๊ธ‰ยท๊ต๋Œ€ ๊ทธ๋Œ€๋กœ ์ปค๋„๊นŒ์ง€ ๊ฐ„๋‹ค(๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค). */\n const persons = master.persons?.map(p => ({ id: p.id, personnelClassIds: p.personnelClassIds, ...(p.window ? { window: p.window } : {}), ...(p.workCalendar?.length ? { workCalendar: p.workCalendar } : {}), ...(p.homeLocationId ? { homeLocation: p.homeLocationId } : {}), ...(p.properties?.length ? { properties: p.properties } : {}), ...(p.testSpecificationIds?.length ? { testSpecificationIds: p.testSpecificationIds } : {}), ...(p.effectiveStart ? { effectiveStart: p.effectiveStart } : {}), ...(p.effectiveEnd ? { effectiveEnd: p.effectiveEnd } : {}) }))\n /* ์ž์‚ฐ๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๋“ฑ๊ธ‰ยท์ž๋ฆฌ ๊ทธ๋Œ€๋กœ ์ปค๋„๊นŒ์ง€. */\n const assets = master.assets?.map(a => ({ id: a.id, assetClassIds: a.assetClassIds, homeLocation: a.homeLocationId, gs1Id: a.gs1Id, ...(a.properties?.length ? { properties: a.properties } : {}), ...(a.testSpecificationIds?.length ? { testSpecificationIds: a.testSpecificationIds } : {}), ...(a.effectiveStart ? { effectiveStart: a.effectiveStart } : {}), ...(a.effectiveEnd ? { effectiveEnd: a.effectiveEnd } : {}) }))\n /* ํ’ˆ๋ชฉ ์ •์˜ยท๋“ฑ๊ธ‰๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค(ํ™˜์‚ฐ ๊ณ„์ˆ˜๋Š” ์ปค๋„์ด ์ฝ๋Š”๋‹ค). */\n const materialDefinitions = master.materialDefinitions?.map(d => ({\n id: d.id,\n ...(d.name ? { description: d.name } : {}),\n ...(d.materialClassIds?.length ? { materialClassIds: d.materialClassIds } : {}),\n ...(d.properties?.length ? { properties: d.properties } : {}),\n ...(d.testSpecificationIds?.length ? { testSpecificationIds: d.testSpecificationIds } : {}),\n ...(d.effectiveStart ? { effectiveStart: d.effectiveStart } : {}),\n ...(d.effectiveEnd ? { effectiveEnd: d.effectiveEnd } : {})\n }))\n const board = {\n locations, equipment, layout, spaceId,\n /* ์ƒ์‚ฐ ์ •์˜๋„ ์†๋Œ€์ง€ ์•Š๊ณ  ํ†ต๊ณผ โ€” ๊ฒฝ๊ณ„์—์„œ ์–ดํœ˜๋ฅผ ๊ฐˆ์ง€ ์•Š๋Š”๋‹ค(์ปค๋„์ด ๊ทธ๋Œ€๋กœ ์†Œ๋น„ํ•œ๋‹ค). */\n ...(master.productionSpec ? { productionSpec: master.productionSpec } : {}),\n ...(materialDefinitions?.length ? { materialDefinitions } : {}),\n ...(master.materialClasses?.length ? { materialClasses: master.materialClasses } : {}),\n ...(utcOffsetMinutes !== undefined ? { utcOffsetMinutes } : {}),\n ...(operations?.length ? { operations } : {}),\n ...(master.personnelClasses?.length ? { personnelClasses: master.personnelClasses } : {}),\n ...(master.equipmentClasses?.length ? { equipmentClasses: master.equipmentClasses } : {}),\n ...(master.assetClasses?.length ? { assetClasses: master.assetClasses } : {}),\n ...(persons?.length ? { persons } : {}),\n ...(assets?.length ? { assets } : {})\n }\n\n const areas = areaLocs.map(l => ({\n id: l.id, type: l.type, name: l.name ?? l.id, parentId: l.parentId,\n x: l.footprint?.x ?? 0, y: l.footprint?.y ?? 0, w: l.footprint?.w ?? 10, h: l.footprint?.h ?? 10\n }))\n // ์ธ์ œ์ŠคํŠธ ํ˜„์žฅ ๋ฌผ์งˆํ™”(space facet #4) โ€” ํ‘œํ˜„์ด ์—†๊ณ  geo ๊ฐ€ ์žˆ์œผ๋ฉด ๊ธฐ๋ณธ map ํ‘œํ˜„ ํ•ฉ์„ฑ.\n // \"์ธ์ œ์ŠคํŠธํ•˜๋ฉด ์•Œ์•„๋ณผ ํ˜„์žฅ(๋‚ด place)์ด ๋œฌ๋‹ค\"๋Š” ๊ณต๊ฐ„ ์ค‘์‹ฌ ์ •์ˆ˜ ๋ณด์žฅ(zero-to-twin): ์ปค๋„ฅํ„ฐ/ํ…œํ”Œ๋ฆฟ์ด\n // ํ‘œํ˜„์„ ์•ˆ ์ค˜๋„ geo ๋งŒ ์žˆ์œผ๋ฉด ์œ„์„ฑ ์ง€๋„๋กœ ์ฐฉ์ง€. (area ํด๋ฆฌ๊ณค ๋ฌผ์งˆํ™”๋Š” ์ขŒํ‘œ ํˆฌ์˜ ํ•„์š” โ†’ space #3.)\n const geo = master.space.geo\n const givenReps = master.space.representations ?? []\n const representations =\n givenReps.length > 0\n ? givenReps\n : geo\n ? [{ id: 'r-map', type: 'map', name: '์œ„์„ฑ ์ง€๋„', primary: true, center: { lat: geo.lat, lon: geo.lon }, zoom: 17 }]\n : []\n if (representations.length === 0) {\n warnings.push(noViewableRepresentation())\n }\n const spaceContent = {\n width: master.space.width, depth: master.space.depth, unit: master.space.unit ?? 'm',\n geo, representations, primaryId: master.space.primaryId ?? representations[0]?.id,\n areas, landmarks: []\n }\n\n return { board, spaceContent, warnings }\n}\n"]}
@@ -6,7 +6,7 @@ export declare class TwinReferenceResolver {
6
6
  /** ๋“ฑ๋ก๋œ ํŠธ์œˆ ํ…œํ”Œ๋ฆฟ(ํŒŒ๋ผ๋ฏธํ„ฐํ™” ์•„ํ‚คํƒ€์ž…) ๋ชฉ๋ก โ€” ๋…ธ๋ธŒ ์Šคํ‚ค๋งˆ ํฌํ•จ(ํด๋ผ์ด์–ธํŠธ ํผ์šฉ). */
7
7
  twinTemplates(_context: ResolverContext): Promise<any[]>;
8
8
  /** ํ…œํ”Œ๋ฆฟ + ๋…ธ๋ธŒ โ†’ ํ•ฉ์„ฑ ๋งˆ์Šคํ„ฐ โ†’ ์ธ์ œ์ŠคํŠธ(+๊ธฐ๋™+์‹œ๋‚˜๋ฆฌ์˜ค). ๋ ˆํผ๋Ÿฐ์Šค import ์™€ ๊ฐ™์€ ๊ฒฝ๋กœ, ์›์ฒœ๋งŒ ํ•ฉ์„ฑ. */
9
- createFromTemplate(templateId: string, params: any, context: ResolverContext, start?: boolean): Promise<any>;
9
+ createFromTemplate(templateId: string, params: any, context: ResolverContext, start?: boolean, spaceId?: string): Promise<any>;
10
10
  twinReferences(context: ResolverContext): Promise<any[]>;
11
11
  referenceAdapterTypes(): string[];
12
12
  /**
@@ -29,7 +29,7 @@ export declare class TwinReferenceResolver {
29
29
  * P1 ์€ ๋Œ€๊ฐœ N=1(virtual/๋‹จ์ผ). start ๋ฉด ๊ฐ ์ธ์Šคํ„ด์Šค ๊ธฐ๋™. ๋ผ์ด๋ธŒ ํ”ผ๋“œยทmode ๋Š” face2-inbound-live ์†Œ์œ .
30
30
  */
31
31
  /** ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ๋…ธ์ถœํ•˜๋Š” ์‚ฌ์ดํŠธ/๊ณต์žฅ ๋ฐœ๊ฒฌ โ€” ํŠธ์œˆ ์ƒ์„ฑ ์‹œ "์–ด๋А ๊ณต์žฅ" ์„ ํƒ์šฉ(ยง2.2). */
32
- discoverReferenceSites(source: string, context: ResolverContext): Promise<any[]>;
32
+ discoverReferenceSites(source: string, context: ResolverContext): Promise<any>;
33
33
  /**
34
34
  * ํŠธ์œˆ ์ƒ์„ฑ โ€” ๋ ˆํผ๋Ÿฐ์Šค์—์„œ ์‚ฌ์ดํŠธ ๋ฐœ๊ฒฌ โ†’ (siteIds ์žˆ์œผ๋ฉด ๊ทธ ๊ณต์žฅ๋งŒ) โ†’ fetchMaster โ†’ provision. ์‚ฌ์ดํŠธ๋ณ„ resilient.
35
35
  * ์—ฌ๋Ÿฌ ๊ณต์žฅ์„ ๊ด€ํ• ํ•˜๋Š” ์†Œ์Šค๋Š” siteIds ๋กœ "์–ด๋А ๊ณต์žฅ"์„ ๊ณจ๋ผ ์ƒ์„ฑ(1:N, ยง2.1ยทยง2.2).