@things-factory/headless-twin 10.0.15 โ†’ 10.0.17

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 (478) hide show
  1. package/dist-server/engine/attention-digest.d.ts +4 -4
  2. package/dist-server/engine/attention-digest.js +7 -7
  3. package/dist-server/engine/attention-digest.js.map +1 -1
  4. package/dist-server/engine/canonical-ingest.d.ts +11 -2
  5. package/dist-server/engine/canonical-ingest.js +108 -9
  6. package/dist-server/engine/canonical-ingest.js.map +1 -1
  7. package/dist-server/engine/command-routing.js +1 -1
  8. package/dist-server/engine/command-routing.js.map +1 -1
  9. package/dist-server/engine/declared-stimulus.js +1 -1
  10. package/dist-server/engine/declared-stimulus.js.map +1 -1
  11. package/dist-server/engine/energy-topology.js +1 -1
  12. package/dist-server/engine/energy-topology.js.map +1 -1
  13. package/dist-server/engine/ingest-dedupe.d.ts +38 -0
  14. package/dist-server/engine/ingest-dedupe.js +145 -0
  15. package/dist-server/engine/ingest-dedupe.js.map +1 -0
  16. package/dist-server/engine/ingest-health.d.ts +90 -10
  17. package/dist-server/engine/ingest-health.js +125 -16
  18. package/dist-server/engine/ingest-health.js.map +1 -1
  19. package/dist-server/engine/integration-probes.d.ts +3 -3
  20. package/dist-server/engine/integration-probes.js +6 -6
  21. package/dist-server/engine/integration-probes.js.map +1 -1
  22. package/dist-server/engine/kpi-baseline.js +4 -4
  23. package/dist-server/engine/kpi-baseline.js.map +1 -1
  24. package/dist-server/engine/kpi-fold.d.ts +122 -12
  25. package/dist-server/engine/kpi-fold.js +247 -18
  26. package/dist-server/engine/kpi-fold.js.map +1 -1
  27. package/dist-server/engine/kpi-query.d.ts +11 -11
  28. package/dist-server/engine/kpi-query.js +185 -28
  29. package/dist-server/engine/kpi-query.js.map +1 -1
  30. package/dist-server/engine/live-feed-registry.d.ts +1 -1
  31. package/dist-server/engine/live-feed-registry.js +1 -1
  32. package/dist-server/engine/live-feed-registry.js.map +1 -1
  33. package/dist-server/engine/load-meter.d.ts +1 -1
  34. package/dist-server/engine/load-meter.js.map +1 -1
  35. package/dist-server/engine/local-declarations.d.ts +7 -7
  36. package/dist-server/engine/local-declarations.js +9 -9
  37. package/dist-server/engine/local-declarations.js.map +1 -1
  38. package/dist-server/engine/log.d.ts +1 -1
  39. package/dist-server/engine/log.js +1 -1
  40. package/dist-server/engine/log.js.map +1 -1
  41. package/dist-server/engine/measured-estimator.js +1 -1
  42. package/dist-server/engine/measured-estimator.js.map +1 -1
  43. package/dist-server/engine/measured-yield.js +1 -1
  44. package/dist-server/engine/measured-yield.js.map +1 -1
  45. package/dist-server/engine/model-basis.d.ts +1 -1
  46. package/dist-server/engine/model-basis.js +1 -1
  47. package/dist-server/engine/model-basis.js.map +1 -1
  48. package/dist-server/engine/model-gap.d.ts +3 -3
  49. package/dist-server/engine/model-gap.js +1 -1
  50. package/dist-server/engine/model-gap.js.map +1 -1
  51. package/dist-server/engine/model-vocabulary.js +1 -1
  52. package/dist-server/engine/model-vocabulary.js.map +1 -1
  53. package/dist-server/engine/oee-accumulator.d.ts +4 -4
  54. package/dist-server/engine/oee-accumulator.js +3 -3
  55. package/dist-server/engine/oee-accumulator.js.map +1 -1
  56. package/dist-server/engine/property-effects.js +2 -2
  57. package/dist-server/engine/property-effects.js.map +1 -1
  58. package/dist-server/engine/read-time.d.ts +22 -0
  59. package/dist-server/engine/read-time.js +81 -0
  60. package/dist-server/engine/read-time.js.map +1 -0
  61. package/dist-server/engine/restart-policy.js +1 -1
  62. package/dist-server/engine/restart-policy.js.map +1 -1
  63. package/dist-server/engine/runtime-key.js +1 -1
  64. package/dist-server/engine/runtime-key.js.map +1 -1
  65. package/dist-server/engine/spec-coverage.d.ts +2 -2
  66. package/dist-server/engine/spec-coverage.js +1 -1
  67. package/dist-server/engine/spec-coverage.js.map +1 -1
  68. package/dist-server/engine/stage-path.d.ts +4 -4
  69. package/dist-server/engine/stage-path.js +1 -1
  70. package/dist-server/engine/stage-path.js.map +1 -1
  71. package/dist-server/engine/state-axes.d.ts +1 -1
  72. package/dist-server/engine/state-axes.js +2 -2
  73. package/dist-server/engine/state-axes.js.map +1 -1
  74. package/dist-server/engine/travel-estimator.d.ts +2 -2
  75. package/dist-server/engine/travel-estimator.js +1 -1
  76. package/dist-server/engine/travel-estimator.js.map +1 -1
  77. package/dist-server/engine/twin-engine.d.ts +237 -54
  78. package/dist-server/engine/twin-engine.js +672 -192
  79. package/dist-server/engine/twin-engine.js.map +1 -1
  80. package/dist-server/engine/warm-start.d.ts +2 -2
  81. package/dist-server/engine/warm-start.js +5 -5
  82. package/dist-server/engine/warm-start.js.map +1 -1
  83. package/dist-server/index.js +1 -1
  84. package/dist-server/index.js.map +1 -1
  85. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js +1 -1
  86. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +1 -1
  87. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js +3 -3
  88. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +1 -1
  89. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js +2 -2
  90. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +1 -1
  91. package/dist-server/migrations/1786300000000-IndexEventTypeByTime.d.ts +5 -0
  92. package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js +54 -0
  93. package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +1 -0
  94. package/dist-server/migrations/1786400000000-IndexEventCreatedAt.d.ts +5 -0
  95. package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js +44 -0
  96. package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +1 -0
  97. package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.d.ts +6 -0
  98. package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js +84 -0
  99. package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +1 -0
  100. package/dist-server/migrations/index.js +7 -1
  101. package/dist-server/migrations/index.js.map +1 -1
  102. package/dist-server/routes.d.ts +1 -0
  103. package/dist-server/routes.js +69 -5
  104. package/dist-server/routes.js.map +1 -1
  105. package/dist-server/service/index.d.ts +2 -2
  106. package/dist-server/service/index.js +27 -24
  107. package/dist-server/service/index.js.map +1 -1
  108. package/dist-server/service/reference/control-routing.d.ts +1 -1
  109. package/dist-server/service/reference/control-routing.js +1 -1
  110. package/dist-server/service/reference/control-routing.js.map +1 -1
  111. package/dist-server/service/reference/discovery-result.d.ts +2 -2
  112. package/dist-server/service/reference/discovery-result.js +3 -3
  113. package/dist-server/service/reference/discovery-result.js.map +1 -1
  114. package/dist-server/service/reference/hook-contract.d.ts +43 -0
  115. package/dist-server/service/reference/hook-contract.js +59 -0
  116. package/dist-server/service/reference/hook-contract.js.map +1 -0
  117. package/dist-server/service/reference/ingest-space.d.ts +1 -1
  118. package/dist-server/service/reference/ingest-space.js +4 -4
  119. package/dist-server/service/reference/ingest-space.js.map +1 -1
  120. package/dist-server/service/reference/knob-defaults.d.ts +1 -1
  121. package/dist-server/service/reference/knob-defaults.js +4 -4
  122. package/dist-server/service/reference/knob-defaults.js.map +1 -1
  123. package/dist-server/service/reference/reference-adapter.d.ts +116 -9
  124. package/dist-server/service/reference/reference-adapter.js +27 -0
  125. package/dist-server/service/reference/reference-adapter.js.map +1 -1
  126. package/dist-server/service/reference/reference-hook.d.ts +20 -0
  127. package/dist-server/service/reference/reference-hook.js +133 -0
  128. package/dist-server/service/reference/reference-hook.js.map +1 -0
  129. package/dist-server/service/reference/reference-live.d.ts +2 -2
  130. package/dist-server/service/reference/reference-live.js +76 -13
  131. package/dist-server/service/reference/reference-live.js.map +1 -1
  132. package/dist-server/service/reference/reference-master.d.ts +14 -14
  133. package/dist-server/service/reference/reference-master.js +34 -12
  134. package/dist-server/service/reference/reference-master.js.map +1 -1
  135. package/dist-server/service/reference/reference-resolver.d.ts +1 -1
  136. package/dist-server/service/reference/reference-resolver.js +10 -10
  137. package/dist-server/service/reference/reference-resolver.js.map +1 -1
  138. package/dist-server/service/reference/twin-reference.d.ts +3 -3
  139. package/dist-server/service/reference/twin-reference.js.map +1 -1
  140. package/dist-server/service/twin-attention/twin-attention-query.d.ts +1 -1
  141. package/dist-server/service/twin-attention/twin-attention-query.js +1 -1
  142. package/dist-server/service/twin-attention/twin-attention-query.js.map +1 -1
  143. package/dist-server/service/twin-audit/command-audit.d.ts +1 -1
  144. package/dist-server/service/twin-audit/command-audit.js.map +1 -1
  145. package/dist-server/service/twin-audit/twin-audit-event.d.ts +1 -1
  146. package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -1
  147. package/dist-server/service/twin-audit/twin-audit-query.js +1 -1
  148. package/dist-server/service/twin-audit/twin-audit-query.js.map +1 -1
  149. package/dist-server/service/twin-control/twin-control-mutation.js +1 -1
  150. package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
  151. package/dist-server/service/twin-event/twin-event-keys.d.ts +1 -1
  152. package/dist-server/service/twin-event/twin-event-keys.js +2 -2
  153. package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
  154. package/dist-server/service/twin-event/twin-event-type.d.ts +1 -0
  155. package/dist-server/service/twin-event/twin-event-type.js +8 -1
  156. package/dist-server/service/twin-event/twin-event-type.js.map +1 -1
  157. package/dist-server/service/twin-event/twin-event.d.ts +2 -2
  158. package/dist-server/service/twin-event/twin-event.js +32 -4
  159. package/dist-server/service/twin-event/twin-event.js.map +1 -1
  160. package/dist-server/service/twin-forecast/forecast-metrics.js +1 -1
  161. package/dist-server/service/twin-forecast/forecast-metrics.js.map +1 -1
  162. package/dist-server/service/twin-forecast/gap-analytics.d.ts +1 -1
  163. package/dist-server/service/twin-forecast/gap-analytics.js.map +1 -1
  164. package/dist-server/service/twin-forecast/twin-forecast-query.js +29 -11
  165. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
  166. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.d.ts +1 -1
  167. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js +1 -1
  168. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +1 -1
  169. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js +1 -1
  170. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +1 -1
  171. package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
  172. package/dist-server/service/twin-journal/event-type-split-shape.d.ts +50 -0
  173. package/dist-server/service/twin-journal/event-type-split-shape.js +111 -0
  174. package/dist-server/service/twin-journal/event-type-split-shape.js.map +1 -0
  175. package/dist-server/service/twin-journal/event-type-split.d.ts +15 -0
  176. package/dist-server/service/twin-journal/event-type-split.js +102 -0
  177. package/dist-server/service/twin-journal/event-type-split.js.map +1 -0
  178. package/dist-server/service/twin-journal/journal-order.d.ts +15 -0
  179. package/dist-server/service/twin-journal/journal-order.js +17 -0
  180. package/dist-server/service/twin-journal/journal-order.js.map +1 -0
  181. package/dist-server/service/twin-journal/twin-journal-query.d.ts +5 -5
  182. package/dist-server/service/twin-journal/twin-journal-query.js +232 -21
  183. package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
  184. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +27 -1
  185. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +59 -3
  186. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
  187. package/dist-server/service/twin-metrics/twin-metrics-query.js +14 -1
  188. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
  189. package/dist-server/service/twin-model/axis-journal-evidence.js +1 -1
  190. package/dist-server/service/twin-model/axis-journal-evidence.js.map +1 -1
  191. package/dist-server/service/twin-model/epcis-coverage.js +34 -3
  192. package/dist-server/service/twin-model/epcis-coverage.js.map +1 -1
  193. package/dist-server/service/twin-model/iec61850-coverage.js +1 -1
  194. package/dist-server/service/twin-model/iec61850-coverage.js.map +1 -1
  195. package/dist-server/service/twin-model/isa95-coverage.d.ts +12 -9
  196. package/dist-server/service/twin-model/isa95-coverage.js +33 -9
  197. package/dist-server/service/twin-model/isa95-coverage.js.map +1 -1
  198. package/dist-server/service/twin-model/item-ref.js +2 -2
  199. package/dist-server/service/twin-model/item-ref.js.map +1 -1
  200. package/dist-server/service/twin-model/name-index.d.ts +1 -1
  201. package/dist-server/service/twin-model/name-index.js +1 -1
  202. package/dist-server/service/twin-model/name-index.js.map +1 -1
  203. package/dist-server/service/twin-model/project-structure.d.ts +1 -1
  204. package/dist-server/service/twin-model/project-structure.js +3 -3
  205. package/dist-server/service/twin-model/project-structure.js.map +1 -1
  206. package/dist-server/service/twin-model/twin-equipment.d.ts +1 -1
  207. package/dist-server/service/twin-model/twin-equipment.js +1 -1
  208. package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
  209. package/dist-server/service/twin-model/twin-lineage-query.js +16 -5
  210. package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
  211. package/dist-server/service/twin-model/twin-location.d.ts +1 -1
  212. package/dist-server/service/twin-model/twin-location.js.map +1 -1
  213. package/dist-server/service/twin-model/twin-model-item-query.d.ts +3 -3
  214. package/dist-server/service/twin-model/twin-model-item-query.js +14 -14
  215. package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
  216. package/dist-server/service/twin-model/twin-model-mutation.d.ts +2 -2
  217. package/dist-server/service/twin-model/twin-model-mutation.js +4 -4
  218. package/dist-server/service/twin-model/twin-model-mutation.js.map +1 -1
  219. package/dist-server/service/twin-model/twin-model-query.js +47 -26
  220. package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
  221. package/dist-server/service/twin-model/twin-model-tree-query.js +22 -0
  222. package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
  223. package/dist-server/service/twin-model/twin-operation.d.ts +1 -1
  224. package/dist-server/service/twin-model/twin-operation.js +1 -1
  225. package/dist-server/service/twin-model/twin-operation.js.map +1 -1
  226. package/dist-server/service/twin-space/move-space.js +2 -2
  227. package/dist-server/service/twin-space/move-space.js.map +1 -1
  228. package/dist-server/service/twin-space/representation-role.d.ts +2 -0
  229. package/dist-server/service/twin-space/representation-role.js +18 -0
  230. package/dist-server/service/twin-space/representation-role.js.map +1 -0
  231. package/dist-server/service/twin-space/space-integrity.d.ts +1 -1
  232. package/dist-server/service/twin-space/space-integrity.js.map +1 -1
  233. package/dist-server/service/twin-space/twin-space-representation.d.ts +2 -0
  234. package/dist-server/service/twin-space/twin-space-representation.js +16 -0
  235. package/dist-server/service/twin-space/twin-space-representation.js.map +1 -1
  236. package/dist-server/service/twin-space/twin-space-resolver.d.ts +2 -2
  237. package/dist-server/service/twin-space/twin-space-resolver.js +36 -7
  238. package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
  239. package/dist-server/service/twin-structure/twin-structure.js +3 -3
  240. package/dist-server/service/twin-structure/twin-structure.js.map +1 -1
  241. package/dist-server/service/twin-subject/event-subjects.d.ts +43 -0
  242. package/dist-server/service/twin-subject/event-subjects.js +137 -0
  243. package/dist-server/service/twin-subject/event-subjects.js.map +1 -0
  244. package/dist-server/service/twin-subject/index.d.ts +9 -0
  245. package/dist-server/service/twin-subject/index.js +16 -0
  246. package/dist-server/service/twin-subject/index.js.map +1 -0
  247. package/dist-server/service/twin-subject/item-resolver.d.ts +10 -0
  248. package/dist-server/service/twin-subject/item-resolver.js +93 -0
  249. package/dist-server/service/twin-subject/item-resolver.js.map +1 -0
  250. package/dist-server/service/twin-subject/subject-query-shape.d.ts +22 -0
  251. package/dist-server/service/twin-subject/subject-query-shape.js +88 -0
  252. package/dist-server/service/twin-subject/subject-query-shape.js.map +1 -0
  253. package/dist-server/service/twin-subject/twin-subject-backfill.d.ts +23 -0
  254. package/dist-server/service/twin-subject/twin-subject-backfill.js +159 -0
  255. package/dist-server/service/twin-subject/twin-subject-backfill.js.map +1 -0
  256. package/dist-server/service/twin-subject/twin-subject-event.d.ts +14 -0
  257. package/dist-server/service/twin-subject/twin-subject-event.js +111 -0
  258. package/dist-server/service/twin-subject/twin-subject-event.js.map +1 -0
  259. package/dist-server/service/twin-subject/twin-subject-fast-path.d.ts +39 -0
  260. package/dist-server/service/twin-subject/twin-subject-fast-path.js +295 -0
  261. package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +1 -0
  262. package/dist-server/service/twin-subject/twin-subject-query.d.ts +27 -0
  263. package/dist-server/service/twin-subject/twin-subject-query.js +232 -0
  264. package/dist-server/service/twin-subject/twin-subject-query.js.map +1 -0
  265. package/dist-server/service/twin-subject/twin-subject-writer.d.ts +27 -0
  266. package/dist-server/service/twin-subject/twin-subject-writer.js +166 -0
  267. package/dist-server/service/twin-subject/twin-subject-writer.js.map +1 -0
  268. package/dist-server/service/twin-target/twin-target-resolver.js +1 -1
  269. package/dist-server/service/twin-target/twin-target-resolver.js.map +1 -1
  270. package/dist-shared/entity-delta.d.ts +1 -1
  271. package/dist-shared/entity-delta.js +3 -3
  272. package/dist-shared/entity-delta.js.map +1 -1
  273. package/dist-shared/touched-items.js +2 -2
  274. package/dist-shared/touched-items.js.map +1 -1
  275. package/dist-shared/twin-level.js +1 -1
  276. package/dist-shared/twin-level.js.map +1 -1
  277. package/package.json +3 -3
  278. package/server/engine/attention-digest.ts +9 -9
  279. package/server/engine/canonical-ingest.ts +141 -14
  280. package/server/engine/command-routing.ts +1 -1
  281. package/server/engine/declared-stimulus.ts +1 -1
  282. package/server/engine/energy-topology.ts +1 -1
  283. package/server/engine/ingest-dedupe.ts +149 -0
  284. package/server/engine/ingest-health.ts +171 -22
  285. package/server/engine/integration-probes.ts +7 -7
  286. package/server/engine/kpi-baseline.ts +4 -4
  287. package/server/engine/kpi-fold.ts +395 -27
  288. package/server/engine/kpi-query.ts +212 -46
  289. package/server/engine/live-feed-registry.ts +1 -1
  290. package/server/engine/load-meter.ts +1 -1
  291. package/server/engine/local-declarations.ts +13 -13
  292. package/server/engine/log.ts +1 -1
  293. package/server/engine/measured-estimator.ts +1 -1
  294. package/server/engine/measured-yield.ts +1 -1
  295. package/server/engine/model-basis.ts +2 -2
  296. package/server/engine/model-gap.ts +3 -3
  297. package/server/engine/model-vocabulary.ts +1 -1
  298. package/server/engine/oee-accumulator.ts +4 -4
  299. package/server/engine/property-effects.ts +2 -2
  300. package/server/engine/read-time.ts +77 -0
  301. package/server/engine/restart-policy.ts +1 -1
  302. package/server/engine/runtime-key.ts +1 -1
  303. package/server/engine/spec-coverage.ts +3 -3
  304. package/server/engine/stage-path.ts +5 -5
  305. package/server/engine/state-axes.ts +2 -2
  306. package/server/engine/travel-estimator.ts +2 -2
  307. package/server/engine/twin-engine.ts +745 -202
  308. package/server/engine/warm-start.ts +6 -6
  309. package/server/index.ts +1 -1
  310. package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +1 -1
  311. package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +3 -3
  312. package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +2 -2
  313. package/server/migrations/1786300000000-IndexEventTypeByTime.ts +48 -0
  314. package/server/migrations/1786400000000-IndexEventCreatedAt.ts +38 -0
  315. package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +93 -0
  316. package/server/migrations/index.ts +7 -1
  317. package/server/routes.ts +68 -5
  318. package/server/service/index.ts +4 -1
  319. package/server/service/reference/control-routing.ts +1 -1
  320. package/server/service/reference/discovery-result.ts +3 -3
  321. package/server/service/reference/hook-contract.ts +103 -0
  322. package/server/service/reference/ingest-space.ts +4 -4
  323. package/server/service/reference/knob-defaults.ts +4 -4
  324. package/server/service/reference/reference-adapter.ts +145 -10
  325. package/server/service/reference/reference-hook.ts +145 -0
  326. package/server/service/reference/reference-live.ts +80 -14
  327. package/server/service/reference/reference-master.ts +39 -17
  328. package/server/service/reference/reference-resolver.ts +10 -10
  329. package/server/service/reference/twin-reference.ts +3 -3
  330. package/server/service/twin-attention/twin-attention-query.ts +1 -1
  331. package/server/service/twin-audit/command-audit.ts +1 -1
  332. package/server/service/twin-audit/twin-audit-event.ts +2 -2
  333. package/server/service/twin-audit/twin-audit-query.ts +1 -1
  334. package/server/service/twin-control/twin-control-mutation.ts +1 -1
  335. package/server/service/twin-event/twin-event-keys.ts +2 -2
  336. package/server/service/twin-event/twin-event-type.ts +18 -1
  337. package/server/service/twin-event/twin-event.ts +32 -6
  338. package/server/service/twin-forecast/forecast-metrics.ts +1 -1
  339. package/server/service/twin-forecast/gap-analytics.ts +1 -1
  340. package/server/service/twin-forecast/twin-forecast-query.ts +30 -11
  341. package/server/service/twin-ingest-window/twin-ingest-window-query.ts +1 -1
  342. package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +1 -1
  343. package/server/service/twin-instance/twin-instance.ts +4 -4
  344. package/server/service/twin-journal/event-type-split-shape.ts +112 -0
  345. package/server/service/twin-journal/event-type-split.ts +144 -0
  346. package/server/service/twin-journal/journal-order.ts +20 -0
  347. package/server/service/twin-journal/twin-journal-query.ts +224 -20
  348. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +57 -3
  349. package/server/service/twin-metrics/twin-metrics-query.ts +14 -1
  350. package/server/service/twin-model/axis-journal-evidence.ts +1 -1
  351. package/server/service/twin-model/epcis-coverage.ts +34 -3
  352. package/server/service/twin-model/iec61850-coverage.ts +1 -1
  353. package/server/service/twin-model/isa95-coverage.ts +43 -16
  354. package/server/service/twin-model/item-ref.ts +2 -2
  355. package/server/service/twin-model/name-index.ts +1 -1
  356. package/server/service/twin-model/project-structure.ts +4 -4
  357. package/server/service/twin-model/twin-equipment.ts +2 -2
  358. package/server/service/twin-model/twin-lineage-query.ts +16 -5
  359. package/server/service/twin-model/twin-location.ts +1 -1
  360. package/server/service/twin-model/twin-model-item-query.ts +14 -14
  361. package/server/service/twin-model/twin-model-mutation.ts +4 -4
  362. package/server/service/twin-model/twin-model-query.ts +47 -26
  363. package/server/service/twin-model/twin-model-tree-query.ts +25 -1
  364. package/server/service/twin-model/twin-operation.ts +2 -2
  365. package/server/service/twin-space/move-space.ts +3 -3
  366. package/server/service/twin-space/representation-role.ts +15 -0
  367. package/server/service/twin-space/space-integrity.ts +1 -1
  368. package/server/service/twin-space/twin-space-representation.ts +37 -0
  369. package/server/service/twin-space/twin-space-resolver.ts +39 -7
  370. package/server/service/twin-structure/twin-structure.ts +3 -3
  371. package/server/service/twin-subject/event-subjects.ts +155 -0
  372. package/server/service/twin-subject/index.ts +10 -0
  373. package/server/service/twin-subject/item-resolver.ts +92 -0
  374. package/server/service/twin-subject/subject-query-shape.ts +84 -0
  375. package/server/service/twin-subject/twin-subject-backfill.ts +196 -0
  376. package/server/service/twin-subject/twin-subject-event.ts +101 -0
  377. package/server/service/twin-subject/twin-subject-fast-path.ts +346 -0
  378. package/server/service/twin-subject/twin-subject-query.ts +210 -0
  379. package/server/service/twin-subject/twin-subject-writer.ts +189 -0
  380. package/server/service/twin-target/twin-target-resolver.ts +1 -1
  381. package/shared/entity-delta.ts +3 -3
  382. package/shared/touched-items.ts +2 -2
  383. package/shared/twin-level.ts +1 -1
  384. package/test/adopt-structure-live.test.ts +3 -3
  385. package/test/aggregate-not-findone.test.ts +112 -0
  386. package/test/attention-digest.test.ts +6 -6
  387. package/test/axis-read.test.ts +2 -2
  388. package/test/boot-resume.test.ts +20 -7
  389. package/test/broadcast-period.test.ts +2 -2
  390. package/test/broadcast-queue-overflow.test.ts +244 -0
  391. package/test/canonical-ingest-vocabularies.test.ts +179 -7
  392. package/test/canonical-quantity-door.test.ts +2 -2
  393. package/test/checkpoint-refuses-empty.test.ts +2 -2
  394. package/test/connector-capability-declaration.test.ts +88 -0
  395. package/test/control-capability.test.ts +1 -1
  396. package/test/cursor-stall-not-read-failure.test.ts +2 -2
  397. package/test/declaration-reaches-model.test.ts +5 -5
  398. package/test/declared-stimulus.test.ts +4 -4
  399. package/test/discovery-result.test.ts +2 -2
  400. package/test/entity-delta.test.ts +4 -4
  401. package/test/event-subjects.test.ts +147 -0
  402. package/test/event-time-column.test.ts +3 -3
  403. package/test/event-type-split.test.ts +155 -0
  404. package/test/fold-gap-speaks.test.ts +53 -0
  405. package/test/forecast-metrics.test.ts +1 -1
  406. package/test/forecast-tuning.test.ts +1 -1
  407. package/test/ingest-health-engine.test.ts +2 -2
  408. package/test/ingest-health-wiring.test.ts +7 -5
  409. package/test/ingest-health.test.ts +6 -6
  410. package/test/ingest-history.test.ts +2 -2
  411. package/test/ingest-idempotent.test.ts +132 -0
  412. package/test/ingest-space.test.ts +3 -3
  413. package/test/integration-probes.test.ts +3 -3
  414. package/test/integration-runner.test.ts +1 -1
  415. package/test/item-ref.test.ts +1 -1
  416. package/test/journal-order-axis.test.ts +80 -0
  417. package/test/journal-read-discipline.test.ts +16 -6
  418. package/test/journal-retention.test.ts +171 -29
  419. package/test/journal-sort-axis.test.ts +1 -1
  420. package/test/journal-write-door.test.ts +3 -3
  421. package/test/journal-write-trend.test.ts +1 -1
  422. package/test/kernel-kind-guard.test.ts +3 -3
  423. package/test/knob-defaults.test.ts +1 -1
  424. package/test/kpi-baseline-db.test.ts +2 -2
  425. package/test/kpi-fold.test.ts +185 -14
  426. package/test/kpi-query-bench.test.ts +3 -3
  427. package/test/live-cursor-wiring.test.ts +6 -6
  428. package/test/live-kernel-facts.test.ts +11 -11
  429. package/test/live-mirror-parity.test.ts +3 -3
  430. package/test/load-meter.test.ts +1 -1
  431. package/test/local-declarations.test.ts +10 -10
  432. package/test/log-stamp.test.ts +1 -1
  433. package/test/measured-yield.test.ts +2 -2
  434. package/test/merge-streams.test.ts +70 -0
  435. package/test/mirror-resumes-from-checkpoint.test.ts +13 -13
  436. package/test/model-basis.test.ts +2 -2
  437. package/test/model-gap.test.ts +4 -4
  438. package/test/model-vocabulary.test.ts +2 -2
  439. package/test/move-space.test.ts +1 -1
  440. package/test/oee-accumulator.test.ts +2 -2
  441. package/test/operational-vocabulary.test.ts +2 -2
  442. package/test/project-structure-db.test.ts +2 -2
  443. package/test/projection-reaches-screen.test.ts +2 -2
  444. package/test/property-effects.test.ts +3 -3
  445. package/test/read-failure-ledger.test.ts +106 -0
  446. package/test/read-failure-visible.test.ts +7 -7
  447. package/test/read-time.test.ts +118 -0
  448. package/test/reference-grounding.test.ts +1 -1
  449. package/test/reference-hook.test.ts +86 -0
  450. package/test/registry-key-guard.test.ts +1 -1
  451. package/test/rename-twin.test.ts +81 -0
  452. package/test/restart-policy.test.ts +3 -3
  453. package/test/resync-origin-site.test.ts +3 -3
  454. package/test/revision-axis.test.ts +14 -8
  455. package/test/runtime-key.test.ts +3 -3
  456. package/test/snapshot-freshness.test.ts +4 -4
  457. package/test/source-outcome-audit.test.ts +1 -1
  458. package/test/space-integrity.test.ts +1 -1
  459. package/test/space-representation.test.ts +66 -0
  460. package/test/space-scope-includes-stopped.test.ts +55 -0
  461. package/test/spec-coverage.test.ts +1 -1
  462. package/test/standard-coverage.test.ts +19 -21
  463. package/test/status-tally.test.ts +1 -1
  464. package/test/structure-revision-db.test.ts +7 -7
  465. package/test/subject-fast-path.test.ts +148 -0
  466. package/test/subject-read-model.test.ts +175 -0
  467. package/test/touched-items.test.ts +2 -2
  468. package/test/twin-audit.test.ts +1 -1
  469. package/test/twin-event-keys.test.ts +1 -1
  470. package/test/twin-model-item-db.test.ts +5 -5
  471. package/test/twin-model-tree-db.test.ts +35 -2
  472. package/test/twin-origin-resync.test.ts +1 -1
  473. package/test/warm-start-seam.test.ts +1 -1
  474. package/test/warm-start.test.ts +6 -6
  475. package/test/withheld-door.test.ts +2 -2
  476. package/test/yield-loop.test.ts +4 -4
  477. package/tsconfig.shared.tsbuildinfo +1 -1
  478. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"energy-topology.js","sourceRoot":"","sources":["../../server/engine/energy-topology.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ์ „๋ ฅ ๊ณ„ํ†ต๋„ โ€” **์„ ์–ธ๋œ ๊ฒƒ๋งŒ ๊ทธ๋ฆฐ๋‹ค.** ์ˆœ์ˆ˜.\n *\n * โ”€โ”€ ์™œ ํ•„์š”ํ•œ๊ฐ€ (2026-08-18) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ๋ถ„๊ธฐ๋ณ„ ๋ง‰๋Œ€๋Š” ใ€Œ์–ด๋””๊ฐ€ ๋งŽ์ด ์“ฐ๋‚˜ใ€์— ๋‹ตํ•˜์ง€๋งŒ **์–ด๋””์— ๊ฑธ๋ ค ์žˆ๋‚˜**์— ๋‹ตํ•˜์ง€ ๋ชปํ•œ๋‹ค. ์‹ค์ œ๋กœ ๋ถ€๋”ชํžŒ\n * ์„ธ ๊ฐ€์ง€๊ฐ€ ์ „๋ถ€ ๊ณ„ํ†ต ์งˆ๋ฌธ์ด์—ˆ๋‹ค:\n * ยท ใ€Œํ•˜์œ„ ๊ณ„๋Ÿ‰์ด ๋ฎ์ง€ ์•Š๋Š” 327 kWhใ€ โ€” ๊ทธ ๋ชซ์ด ์ˆ˜์ „ ์ง๊ฒฐ ๋ถ€ํ•˜์ธ์ง€, ๊ณ„๋Ÿ‰ ์—†๋Š” ๊ตฌ๊ฐ„์ธ์ง€ ํ‘œ๋กœ๋Š” ๋ชจ๋ฅธ๋‹ค.\n * ยท ์ปค๋„ฅํ„ฐ๋Š” ๊ฒฐ์„ ์„ ๋ชจ๋ฅด๋Š” ๋ถ€ํ•˜๋ฅผ **์ˆ˜์ „์— ๋งค๋‹จ๋‹ค**(์ •์งํ•œ ์„ ํƒ). ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ์‚ฌ์‹ค์ด ํ™”๋ฉด์— ์—†์—ˆ๋‹ค.\n * ยท ใ€Œ๊ณ„๋Ÿ‰๊ธฐ๋ฅผ ์–ด๋””์— ๋” ๋‹ฌ์•„์•ผ ํ•˜๋‚˜ใ€ โ€” ์–ด๋‘์šด ๊ตฌ๊ฐ„์ด ๋ณด์—ฌ์•ผ ๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค.\n *\n * โ”€โ”€ ๋ฌด์—‡์„ ๊ทธ๋ฆฌ์ง€ ์•Š๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * **๋ณดํ˜ธ ๊ณ„ํ†ต ๋‹จ์„ ๋„(SLD)๊ฐ€ ์•„๋‹ˆ๋‹ค.** ์ฐจ๋‹จ๊ธฐ ์ •๊ฒฉยท๋ณดํ˜ธ ํ˜‘์กฐยท์ƒ(phase)ยท๊ฒฐ์„  ๋ฐฉ์‹์€ ๋ชจ๋ธ์— ์—†๊ณ , ๊ทธ๋Ÿด๋“ฏํ•œ\n * ๋‹จ์„ ๋„๋ฅผ ๊ทธ๋ฆฌ๋ฉด ๊ฐ–์ง€ ์•Š์€ ๊ณตํ•™์  ์ถฉ์‹ค๋„๋ฅผ ์ฃผ์žฅํ•˜๊ฒŒ ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์€ **ํŠธ์œˆ์ด ์„ ์–ธํ•œ ๊ด€๊ณ„**\n * (์ž๋ฆฌ์˜ ๊ณ„์ธต + ์„ค๋น„์˜ ์†Œ์†)์™€ **๊ณ„๋Ÿ‰์ด ์‹ค์ œ๋กœ ๋ฎ๋Š” ๋ฒ”์œ„**๋ฟ์ด๋‹ค. ํ•œ๊ณ„๋Š” ์†Œ๋น„์ฒ˜๊ฐ€ ํ™”๋ฉด์— ์ ๋Š”๋‹ค.\n *\n * โ”€โ”€ ์กฐ์šฉํžˆ ๋น ๋œจ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋Š” ์„ค๋น„, ๊ณ„๋Ÿ‰๊ธฐ๊ฐ€ ์—†๋Š” ์ž๋ฆฌ, ๊ณ„๋Ÿ‰์ด ๋ฎ์ง€ ์•Š๋Š” ๋ชซ์€ **๊ฐ์ž ์ž๊ธฐ ์นธ์œผ๋กœ** ๋‚˜์˜จ๋‹ค. ๊ทธ๋ฆผ์—์„œ\n * ์‚ฌ๋ผ์ง€๋ฉด ์‚ฌ์šฉ์ž๋Š” ์ž๊ธฐ ํ˜„์žฅ์ด ๋‹ค ๊ทธ๋ ค์กŒ๋‹ค๊ณ  ๋ฏฟ๋Š”๋‹ค.\n */\nimport { EMS_LOCATION_TYPES, electricalUpstreamOf } from '@operato/twin-kernel'\n\n/** ๊ณ„ํ†ต์˜ ํ•œ ๊ตฌ๊ฐ„(์ˆ˜์ „ยท๋ถ„๊ธฐยท๊ตฌ์—ญ) โ€” ์ž๋ฆฌ ํ•˜๋‚˜๊ฐ€ ๊ณง ๊ตฌ๊ฐ„์ด๋‹ค. */\nexport interface TopologySegment {\n id: string\n /** ์นดํƒˆ๋กœ๊ทธ ์ž๋ฆฌ ํƒ€์ž…(`incoming`ยท`feeder`ยท`submeter-zone`). */\n type: string\n label?: string\n /** ์ด ์ž๋ฆฌ์— ๋‹ฌ๋ฆฐ ๊ณ„๋Ÿ‰ ์ง€์  id ๋“ค โ€” ๋น„์–ด ์žˆ์œผ๋ฉด **์–ด๋‘์šด ๊ตฌ๊ฐ„**์ด๋‹ค(๊ฐ’์„ ์•Œ ๊ธธ์ด ์—†๋‹ค). */\n meters: string[]\n /** ์ด ๊ตฌ๊ฐ„์˜ ์ „๋ ฅ๋Ÿ‰๊ณผ ๊ทผ๊ฑฐ โ€” ํด๋“œ๊ฐ€ ๋‚ธ ๊ฒƒ๋งŒ ์‹ฃ๋Š”๋‹ค(์šฐ๋ฆฌ๊ฐ€ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค). */\n kWh?: number\n basis?: 'measured' | 'apportioned'\n /**\n * **ํ”ผํฌ๊ฐ€ ์ฐํžŒ ์ˆœ๊ฐ„** ์ด ๊ตฌ๊ฐ„์ด ์–ผ๋งˆ์˜€๋‚˜(kW) โ€” ์š”๊ธˆ์ด ๊ฑธ๋ฆฐ ์ˆ˜๋‹ค.\n *\n * ์ „๋ ฅ๋Ÿ‰์ด ํฐ ๊ตฌ๊ฐ„๊ณผ ํ”ผํฌ๋ฅผ ๋งŒ๋“  ๊ตฌ๊ฐ„์€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค(ํ•˜๋ฃจ ์ข…์ผ ์กฐ๊ธˆ์”ฉ ์“ฐ๋Š” ๋ถ€ํ•˜ vs ์ž ๊น ํฌ๊ฒŒ ์“ฐ๋Š” ๋ถ€ํ•˜).\n * ๊ทธ๋ฆผ์— ๋‘˜์„ ํ•จ๊ป˜ ๋‘๋ฉด ใ€Œ์–ด๋А ๋ถ„๊ธฐ๋ฅผ ๊นŽ์•„์•ผ ํ”ผํฌ๊ฐ€ ๋‚ด๋ ค๊ฐ€๋‚˜ใ€๊ฐ€ ๋ฐ”๋กœ ์ฝํžŒ๋‹ค.\n */\n peakKW?: number\n /** ์ด ์ž๋ฆฌ์— ๋งค๋‹ฌ๋ฆฐ ๋ถ€ํ•˜(์„ค๋น„) โ€” ์ข…๋ฅ˜๋ฅผ ๊ทธ๋Œ€๋กœ ์‹ฃ๋Š”๋‹ค. */\n loads: { id: string; kind: string }[]\n /**\n * ๊ณ„ํ†ต ์„ค๋น„(์ฐจ๋‹จ๊ธฐยทํƒœ์–‘๊ด‘ยท์ถ•์ „์ง€) โ€” ๋ถ€ํ•˜๊ฐ€ ์•„๋‹ˆ๋ผ ๊ณ„ํ†ต์˜ ์ผ๋ถ€๋‹ค.\n *\n * `live` ๋Š” **์ง€๊ธˆ ๊ฐ’**์ด๋‹ค(๊ตฌ๊ฐ„ ๊ฐ’์ด ์•„๋‹ˆ๋‹ค): ํƒœ์–‘๊ด‘์ด ์ง€๊ธˆ ๋ช‡ kW ๋ฅผ ๋งŒ๋“ค๊ณ , ์ถ•์ „์ง€๊ฐ€ ์–ผ๋งˆ๋ฅผ ๋‚ด๋ณด๋‚ด๋ฉฐ\n * ์ถฉ์ „์œจ์ด ์–ผ๋งˆ์ธ๊ฐ€. ์›์ฒœ์ด ๋ณด๋‚ด ์ฃผ๋Š” ์‚ฌ์‹ค์ด๋ผ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค โ€” ๋ณด๋‚ด์ง€ ์•Š์€ ํ•„๋“œ๋Š” ์—†๋‹ค.\n *\n * ์‹œ๊ฐ(`measuredAt`)์„ ํ•จ๊ป˜ ๋‚˜๋ฅธ๋‹ค: ๊ณ„์ธก์ด ๋Š๊ธฐ๋ฉด **๋ฉˆ์ถ˜ ๊ฐ’์„ ์ง€๊ธˆ ๊ฐ’์œผ๋กœ ๊ทธ๋ฆฌ๊ฒŒ** ๋˜๊ณ , ๊ทธ๊ฒƒ์ด ํ™”๋ฉด์ด\n * ๋‚ผ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๋‚˜์œ ๊ฑฐ์ง“์ด๋‹ค(๊ฐ’์ด ๊ทธ๋Ÿด๋“ฏํ• ์ˆ˜๋ก ์œ„ํ—˜ํ•˜๋‹ค).\n */\n gear: {\n id: string\n kind: string\n live?: { generatedKW?: number; exportKW?: number; chargeKW?: number; dischargeKW?: number; soc?: number; measuredAt?: string }\n }[]\n children: TopologySegment[]\n}\n\nexport interface EnergyTopology {\n roots: TopologySegment[]\n /**\n * ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋Š” ์„ค๋น„ โ€” ์ง‘์ด ์—†๊ฑฐ๋‚˜, ์—†๋Š” ์ž๋ฆฌ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ์ˆจ๊ธฐ๋ฉด ๊ทธ๋ฆผ์˜ ์„ค๋น„ ์ˆ˜๊ฐ€ ๋ชจ๋ธ๊ณผ ๋‹ฌ๋ผ์ง„๋‹ค.\n */\n unplaced: { id: string; kind: string }[]\n /** ๊ณ„๋Ÿ‰๊ธฐ๊ฐ€ ์—†๋Š” ์ž๋ฆฌ id ๋“ค โ€” ใ€Œ์—ฌ๊ธฐ์— ๋‹ฌ๋ฉด ๋ฌด์—‡์„ ์•Œ ์ˆ˜ ์žˆ๋‚˜ใ€์˜ ๋‹ต์ด ๋˜๋Š” ๋ชฉ๋ก์ด๋‹ค. */\n unmetered: string[]\n /**\n * ๊ฒฐ์„ ์„ ๋ชจ๋ฅด๋Š” ๋ถ€ํ•˜๊ฐ€ ๋งค๋‹ฌ๋ฆฐ ์ž๋ฆฌ โ€” ์ปค๋„ฅํ„ฐ๊ฐ€ ใ€Œ์–ด๋А ๋ถ„๊ธฐ๊ฐ€ ์ด ์„ค๋น„์— ์ „๊ธฐ๋ฅผ ์ฃผ๋Š”์ง€ ๋ชจ๋ฅธ๋‹คใ€๊ณ  ํŒ๋‹จํ•ด\n * ์ˆ˜์ „์— ๋งค๋‹จ ๊ฒฝ์šฐ๋‹ค. ๊ทธ ์ž๋ฆฌ์˜ ๋ชซ์ด ๋ถ„๊ธฐ๋กœ ๋‚ด๋ ค๊ฐ€์ง€ ์•Š๋Š” ์ด์œ ๊ฐ€ ์ด๊ฒƒ์ด๋‹ค.\n */\n loadsOnIncoming: number\n}\n\n/**\n * ์ด ์„ค๋น„์˜ **์ง€๊ธˆ ๊ฐ’** โ€” ์Šค๋ƒ…์ƒท์—์„œ ๊ทธ ์„ค๋น„๋ฅผ ์ฐพ์•„ ์—๋„ˆ์ง€ ์ถ•์˜ ๊ฐ’๋งŒ ์˜ฎ๊ธด๋‹ค.\n *\n * ์ข…๋ฅ˜๊ฐ€ ์•„๋Š” ํ•„๋“œ๋งŒ ์˜ฎ๊ธด๋‹ค: ํƒœ์–‘๊ด‘์— ์ถฉ์ „์œจ์„ ๋ถ™์ด๊ฑฐ๋‚˜ ์ถ•์ „์ง€์— ๋ฐœ์ „๋Ÿ‰์„ ๋ถ™์ด๋ฉด, ํ™”๋ฉด์€ ๊ทธ๊ฒƒ์„ ์‚ฌ์‹ค๋กœ\n * ๊ทธ๋ฆฌ๊ณ  ์‚ฌ๋žŒ์€ ๊ทธ ์„ค๋น„๊ฐ€ ๊ทธ๋Ÿฐ ์ผ์„ ํ•œ๋‹ค๊ณ  ์ฝ๋Š”๋‹ค(์ปค๋„์ด ์ข…๋ฅ˜๋ณ„๋กœ ํ•„๋“œ๋ฅผ ๊ฐ€๋ ค ๋ฐ›๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ทœ์œจ).\n */\nfunction liveOf(\n state: readonly any[] | undefined | null,\n id: string,\n kind: string\n): { live: NonNullable<TopologySegment['gear'][number]['live']> } | undefined {\n const e = (state ?? []).find(x => String(x?.id ?? '') === id)\n if (!e) return undefined\n const num = (v: unknown): number | undefined => (Number.isFinite(Number(v)) ? Number(v) : undefined)\n const live: NonNullable<TopologySegment['gear'][number]['live']> = {}\n if (kind === 'pv-array') {\n const g = num(e.generatedKW)\n const x = num(e.exportKW)\n if (g !== undefined) live.generatedKW = g\n if (x !== undefined) live.exportKW = x\n } else if (kind === 'battery') {\n const soc = num(e.soc)\n const dis = num(e.dischargeKW)\n const cha = num(e.chargeKW)\n if (soc !== undefined) live.soc = soc\n if (dis !== undefined) live.dischargeKW = dis\n if (cha !== undefined) live.chargeKW = cha\n }\n if (!Object.keys(live).length) return undefined\n /* ๊ฐ’์ด ์žˆ์œผ๋ฉด ์‹œ๊ฐ๋„ ํ•จ๊ป˜ โ€” ์—†์œผ๋ฉด ๋ถ™์ด์ง€ ์•Š๋Š”๋‹ค(๋ชจ๋ฅด๋Š” ์‹œ๊ฐ์„ ์ง€๊ธˆ์œผ๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค). */\n if (e.measuredAt) live.measuredAt = String(e.measuredAt)\n return { live }\n}\n\nconst ELECTRICAL = new Set(EMS_LOCATION_TYPES as readonly string[])\n/** ๋ถ€ํ•˜๊ฐ€ ์•„๋‹Œ ๊ณ„ํ†ต ์„ค๋น„ โ€” ์ด๊ฒƒ๋“ค์˜ ์†Œ๋น„๋ฅผ ๋ถ€ํ•˜๋กœ ์„ธ๋ฉด ์ด๋Ÿ‰์ด ์ด์ค‘์œผ๋กœ ๋‚˜๋‰œ๋‹ค. */\nconst GEAR = new Set(['meter', 'breaker', 'pv-array', 'battery'])\n\n/**\n * ๋ชจ๋ธ + ํด๋“œ ๊ฒฐ๊ณผ โ†’ ๊ณ„ํ†ต ํŠธ๋ฆฌ.\n *\n * @param model ํŠธ์œˆ ๋ชจ๋ธ(์ž๋ฆฌ ๊ณ„์ธต `parentId`, ์„ค๋น„ ์†Œ์† `homeLocation`).\n * @param energy ํด๋“œ๊ฐ€ ๋‚ธ ๋ถ„๊ธฐ๋ณ„ ๋ชซ(์žˆ์œผ๋ฉด ๋…ธ๋“œ์— ์‹ฃ๋Š”๋‹ค โ€” ์—†์œผ๋ฉด ๊ฐ’ ์—†์ด ๊ตฌ์กฐ๋งŒ ๊ทธ๋ฆฐ๋‹ค).\n */\nexport function buildEnergyTopology(\n model: { locations?: any[]; equipment?: any[] } | undefined | null,\n energy?: { byFeeder?: { key: string; kWh: number; basis?: 'measured' | 'apportioned'; peakKW?: number }[] } | null,\n /**\n * ์ง€๊ธˆ์˜ ์„ค๋น„ ์ƒํƒœ(์Šค๋ƒ…์ƒท์˜ `equipment`) โ€” ๋ฐœ์ „ยท์ €์žฅ์˜ **์ง€๊ธˆ ๊ฐ’**์„ ๊ธฐํ˜ธ ์˜†์— ์ ๊ธฐ ์œ„ํ•ด์„œ๋‹ค.\n *\n * ์—†์œผ๋ฉด ๊ฐ’ ์—†์ด ๊ตฌ์กฐ๋งŒ ๊ทธ๋ฆฐ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ฐ’์„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค: ์›์ฒœ์ด ๋ณด๋‚ด์ง€ ์•Š์€ ๊ฒƒ์€ ๋ชจ๋ฅด๋Š” ๊ฒƒ์ด๋‹ค.\n */\n equipmentState?: readonly any[] | null\n): EnergyTopology {\n const locations: any[] = (model?.locations ?? []).filter(n => n?.id && ELECTRICAL.has(String(n.type)))\n const byId = new Map<string, TopologySegment>()\n for (const n of locations) {\n byId.set(String(n.id), {\n id: String(n.id),\n type: String(n.type),\n ...(n.name ? { label: String(n.name) } : {}),\n meters: [],\n loads: [],\n gear: [],\n children: []\n })\n }\n\n const share = new Map((energy?.byFeeder ?? []).map(f => [f.key, f]))\n for (const [id, segment] of byId) {\n const s = share.get(id)\n if (s) {\n segment.kWh = s.kWh\n if (s.basis) segment.basis = s.basis\n if (typeof s.peakKW === 'number') segment.peakKW = s.peakKW\n }\n }\n\n /* ์„ค๋น„๋ฅผ ์ž๊ธฐ ์ž๋ฆฌ์— ๋ถ™์ธ๋‹ค โ€” ๊ณ„๋Ÿ‰๊ธฐ๋Š” ใ€Œ์ด ๊ตฌ๊ฐ„์„ ์žฐ๋‹คใ€๋Š” ๋œป์ด๋ผ ๋”ฐ๋กœ ๋ชจ์€๋‹ค. */\n const unplaced: { id: string; kind: string }[] = []\n let loadsOnIncoming = 0\n for (const e of (model?.equipment ?? []) as any[]) {\n if (!e?.id) continue\n const kind = String(e.kind ?? '')\n const home = String(e.homeLocation ?? e.homeLocationId ?? '')\n const at = byId.get(home)\n if (!at) {\n /* ์ „๊ธฐ ๊ณ„ํ†ต ๋ฐ–์˜ ์ž๋ฆฌ์— ์‚ฌ๋Š” ์„ค๋น„๋„ ์—ฌ๊ธฐ์„œ๋Š” ใ€Œ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅธ๋‹คใ€๋กœ ๋ชจ์€๋‹ค โ€” ์ด ๊ทธ๋ฆผ์˜ ์ถ•์€ ๊ณ„ํ†ต์ด๋‹ค. */\n unplaced.push({ id: String(e.id), kind })\n continue\n }\n if (kind === 'meter') at.meters.push(String(e.id))\n else if (GEAR.has(kind)) at.gear.push({ id: String(e.id), kind, ...(liveOf(equipmentState, String(e.id), kind) ?? {}) })\n else {\n at.loads.push({ id: String(e.id), kind })\n if (at.type === 'incoming') loadsOnIncoming++\n }\n }\n\n /*\n * ๊ณ„์ธต์„ ์ž‡๋Š” ๊ฒƒ์€ **์ „๊ธฐ ์ƒ๋ฅ˜**๋‹ค โ€” ๊ณต๊ฐ„ ๋ถ€๋ชจ(๊ณต์žฅยท๊ตฌ์—ญ)๋Š” ์ด ์ถ•์ด ์•„๋‹ˆ๋‹ค. ์ƒ๋ฅ˜์˜ ๋œป์€ ์ปค๋„์ด ์ฝ๋Š”๋‹ค\n * (์˜› ์„ธ๋Œ€๋Š” ๊ทธ ์•ˆ์—์„œ ํก์ˆ˜๋œ๋‹ค) โ€” ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ํŒ์ •ํ•˜๋ฉด ํ™”๋ฉด๊ณผ ๊ณ„์‚ฐ์ด ๋‹ค๋ฅธ ๊ณ„ํ†ต์„ ๋งํ•˜๊ฒŒ ๋œ๋‹ค.\n */\n const roots: TopologySegment[] = []\n const all = model?.locations ?? []\n for (const n of locations) {\n const segment = byId.get(String(n.id))!\n const up = electricalUpstreamOf(all as any, String(n.id))\n const parent = up ? byId.get(up) : undefined\n if (parent && parent !== segment) parent.children.push(segment)\n else roots.push(segment)\n }\n\n const unmetered = [...byId.values()].filter(n => !n.meters.length).map(n => n.id)\n return { roots, unplaced, unmetered, loadsOnIncoming }\n}\n"]}
1
+ {"version":3,"file":"energy-topology.js","sourceRoot":"","sources":["../../server/engine/energy-topology.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ์ „๋ ฅ ๊ณ„ํ†ต๋„ โ€” **์„ ์–ธ๋œ ๊ฒƒ๋งŒ ๊ทธ๋ฆฐ๋‹ค.** ์ˆœ์ˆ˜.\n *\n * โ”€โ”€ ์™œ ํ•„์š”ํ•œ๊ฐ€ (2026-08-18) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ๋ถ„๊ธฐ๋ณ„ ๋ง‰๋Œ€๋Š” ใ€Œ์–ด๋””๊ฐ€ ๋งŽ์ด ์“ฐ๋‚˜ใ€์— ๋‹ตํ•˜์ง€๋งŒ **์–ด๋””์— ๊ฑธ๋ ค ์žˆ๋‚˜**์— ๋‹ตํ•˜์ง€ ๋ชปํ•œ๋‹ค. ์‹ค์ œ๋กœ ๋ถ€๋”ชํžŒ\n * ์„ธ ๊ฐ€์ง€๊ฐ€ ์ „๋ถ€ ๊ณ„ํ†ต ์งˆ๋ฌธ์ด์—ˆ๋‹ค:\n * ยท ใ€Œํ•˜์œ„ ๊ณ„๋Ÿ‰์ด ๋ฎ์ง€ ์•Š๋Š” 327 kWhใ€ โ€” ๊ทธ ๋ชซ์ด ์ˆ˜์ „ ์ง๊ฒฐ ๋ถ€ํ•˜์ธ์ง€, ๊ณ„๋Ÿ‰ ์—†๋Š” ๊ตฌ๊ฐ„์ธ์ง€ ํ‘œ๋กœ๋Š” ๋ชจ๋ฅธ๋‹ค.\n * ยท ์ปค๋„ฅํ„ฐ๋Š” ๊ฒฐ์„ ์„ ๋ชจ๋ฅด๋Š” ๋ถ€ํ•˜๋ฅผ **์ˆ˜์ „์— ๋งค๋‹จ๋‹ค**(์ •์งํ•œ ์„ ํƒ). ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ์‚ฌ์‹ค์ด ํ™”๋ฉด์— ์—†์—ˆ๋‹ค.\n * ยท ใ€Œ๊ณ„๋Ÿ‰๊ธฐ๋ฅผ ์–ด๋””์— ๋” ๋‹ฌ์•„์•ผ ํ•˜๋‚˜ใ€ โ€” ์–ด๋‘์šด ๊ตฌ๊ฐ„์ด ๋ณด์—ฌ์•ผ ๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค.\n *\n * โ”€โ”€ ๋ฌด์—‡์„ ๊ทธ๋ฆฌ์ง€ ์•Š๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * **๋ณดํ˜ธ ๊ณ„ํ†ต ๋‹จ์„ ๋„(SLD)๊ฐ€ ์•„๋‹ˆ๋‹ค.** ์ฐจ๋‹จ๊ธฐ ์ •๊ฒฉยท๋ณดํ˜ธ ํ˜‘์กฐยท์ƒ(phase)ยท๊ฒฐ์„  ๋ฐฉ์‹์€ ๋ชจ๋ธ์— ์—†๊ณ , ๊ทธ๋Ÿด๋“ฏํ•œ\n * ๋‹จ์„ ๋„๋ฅผ ๊ทธ๋ฆฌ๋ฉด ๊ฐ–์ง€ ์•Š์€ ๊ณตํ•™์  ์ถฉ์‹ค๋„๋ฅผ ์ฃผ์žฅํ•˜๊ฒŒ ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์€ **ํŠธ์œˆ์ด ์„ ์–ธํ•œ ๊ด€๊ณ„**\n * (์ž๋ฆฌ์˜ ๊ณ„์ธต + ์„ค๋น„์˜ ์†Œ์†)์™€ **๊ณ„๋Ÿ‰์ด ์‹ค์ œ๋กœ ๋ฎ๋Š” ๋ฒ”์œ„**๋ฟ์ด๋‹ค. ํ•œ๊ณ„๋Š” ์†Œ๋น„์ฒ˜๊ฐ€ ํ™”๋ฉด์— ์ ๋Š”๋‹ค.\n *\n * โ”€โ”€ ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋น ๋œจ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋Š” ์„ค๋น„, ๊ณ„๋Ÿ‰๊ธฐ๊ฐ€ ์—†๋Š” ์ž๋ฆฌ, ๊ณ„๋Ÿ‰์ด ๋ฎ์ง€ ์•Š๋Š” ๋ชซ์€ **๊ฐ์ž ์ž๊ธฐ ์นธ์œผ๋กœ** ๋‚˜์˜จ๋‹ค. ๊ทธ๋ฆผ์—์„œ\n * ์‚ฌ๋ผ์ง€๋ฉด ์‚ฌ์šฉ์ž๋Š” ์ž๊ธฐ ํ˜„์žฅ์ด ๋‹ค ๊ทธ๋ ค์กŒ๋‹ค๊ณ  ๋ฏฟ๋Š”๋‹ค.\n */\nimport { EMS_LOCATION_TYPES, electricalUpstreamOf } from '@operato/twin-kernel'\n\n/** ๊ณ„ํ†ต์˜ ํ•œ ๊ตฌ๊ฐ„(์ˆ˜์ „ยท๋ถ„๊ธฐยท๊ตฌ์—ญ) โ€” ์ž๋ฆฌ ํ•˜๋‚˜๊ฐ€ ๊ณง ๊ตฌ๊ฐ„์ด๋‹ค. */\nexport interface TopologySegment {\n id: string\n /** ์นดํƒˆ๋กœ๊ทธ ์ž๋ฆฌ ํƒ€์ž…(`incoming`ยท`feeder`ยท`submeter-zone`). */\n type: string\n label?: string\n /** ์ด ์ž๋ฆฌ์— ๋‹ฌ๋ฆฐ ๊ณ„๋Ÿ‰ ์ง€์  id ๋“ค โ€” ๋น„์–ด ์žˆ์œผ๋ฉด **์–ด๋‘์šด ๊ตฌ๊ฐ„**์ด๋‹ค(๊ฐ’์„ ์•Œ ๊ธธ์ด ์—†๋‹ค). */\n meters: string[]\n /** ์ด ๊ตฌ๊ฐ„์˜ ์ „๋ ฅ๋Ÿ‰๊ณผ ๊ทผ๊ฑฐ โ€” ํด๋“œ๊ฐ€ ๋‚ธ ๊ฒƒ๋งŒ ์‹ฃ๋Š”๋‹ค(์šฐ๋ฆฌ๊ฐ€ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค). */\n kWh?: number\n basis?: 'measured' | 'apportioned'\n /**\n * **ํ”ผํฌ๊ฐ€ ์ฐํžŒ ์ˆœ๊ฐ„** ์ด ๊ตฌ๊ฐ„์ด ์–ผ๋งˆ์˜€๋‚˜(kW) โ€” ์š”๊ธˆ์ด ๊ฑธ๋ฆฐ ์ˆ˜๋‹ค.\n *\n * ์ „๋ ฅ๋Ÿ‰์ด ํฐ ๊ตฌ๊ฐ„๊ณผ ํ”ผํฌ๋ฅผ ๋งŒ๋“  ๊ตฌ๊ฐ„์€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค(ํ•˜๋ฃจ ์ข…์ผ ์กฐ๊ธˆ์”ฉ ์“ฐ๋Š” ๋ถ€ํ•˜ vs ์ž ๊น ํฌ๊ฒŒ ์“ฐ๋Š” ๋ถ€ํ•˜).\n * ๊ทธ๋ฆผ์— ๋‘˜์„ ํ•จ๊ป˜ ๋‘๋ฉด ใ€Œ์–ด๋А ๋ถ„๊ธฐ๋ฅผ ๊นŽ์•„์•ผ ํ”ผํฌ๊ฐ€ ๋‚ด๋ ค๊ฐ€๋‚˜ใ€๊ฐ€ ๋ฐ”๋กœ ์ฝํžŒ๋‹ค.\n */\n peakKW?: number\n /** ์ด ์ž๋ฆฌ์— ๋งค๋‹ฌ๋ฆฐ ๋ถ€ํ•˜(์„ค๋น„) โ€” ์ข…๋ฅ˜๋ฅผ ๊ทธ๋Œ€๋กœ ์‹ฃ๋Š”๋‹ค. */\n loads: { id: string; kind: string }[]\n /**\n * ๊ณ„ํ†ต ์„ค๋น„(์ฐจ๋‹จ๊ธฐยทํƒœ์–‘๊ด‘ยท์ถ•์ „์ง€) โ€” ๋ถ€ํ•˜๊ฐ€ ์•„๋‹ˆ๋ผ ๊ณ„ํ†ต์˜ ์ผ๋ถ€๋‹ค.\n *\n * `live` ๋Š” **์ง€๊ธˆ ๊ฐ’**์ด๋‹ค(๊ตฌ๊ฐ„ ๊ฐ’์ด ์•„๋‹ˆ๋‹ค): ํƒœ์–‘๊ด‘์ด ์ง€๊ธˆ ๋ช‡ kW ๋ฅผ ๋งŒ๋“ค๊ณ , ์ถ•์ „์ง€๊ฐ€ ์–ผ๋งˆ๋ฅผ ๋‚ด๋ณด๋‚ด๋ฉฐ\n * ์ถฉ์ „์œจ์ด ์–ผ๋งˆ์ธ๊ฐ€. ์›์ฒœ์ด ๋ณด๋‚ด ์ฃผ๋Š” ์‚ฌ์‹ค์ด๋ผ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค โ€” ๋ณด๋‚ด์ง€ ์•Š์€ ํ•„๋“œ๋Š” ์—†๋‹ค.\n *\n * ์‹œ๊ฐ(`measuredAt`)์„ ํ•จ๊ป˜ ๋‚˜๋ฅธ๋‹ค: ๊ณ„์ธก์ด ๋Š๊ธฐ๋ฉด **๋ฉˆ์ถ˜ ๊ฐ’์„ ์ง€๊ธˆ ๊ฐ’์œผ๋กœ ๊ทธ๋ฆฌ๊ฒŒ** ๋˜๊ณ , ๊ทธ๊ฒƒ์ด ํ™”๋ฉด์ด\n * ๋‚ผ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๋‚˜์œ ๊ฑฐ์ง“์ด๋‹ค(๊ฐ’์ด ๊ทธ๋Ÿด๋“ฏํ• ์ˆ˜๋ก ์œ„ํ—˜ํ•˜๋‹ค).\n */\n gear: {\n id: string\n kind: string\n live?: { generatedKW?: number; exportKW?: number; chargeKW?: number; dischargeKW?: number; soc?: number; measuredAt?: string }\n }[]\n children: TopologySegment[]\n}\n\nexport interface EnergyTopology {\n roots: TopologySegment[]\n /**\n * ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋Š” ์„ค๋น„ โ€” ์ง‘์ด ์—†๊ฑฐ๋‚˜, ์—†๋Š” ์ž๋ฆฌ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ์ˆจ๊ธฐ๋ฉด ๊ทธ๋ฆผ์˜ ์„ค๋น„ ์ˆ˜๊ฐ€ ๋ชจ๋ธ๊ณผ ๋‹ฌ๋ผ์ง„๋‹ค.\n */\n unplaced: { id: string; kind: string }[]\n /** ๊ณ„๋Ÿ‰๊ธฐ๊ฐ€ ์—†๋Š” ์ž๋ฆฌ id ๋“ค โ€” ใ€Œ์—ฌ๊ธฐ์— ๋‹ฌ๋ฉด ๋ฌด์—‡์„ ์•Œ ์ˆ˜ ์žˆ๋‚˜ใ€์˜ ๋‹ต์ด ๋˜๋Š” ๋ชฉ๋ก์ด๋‹ค. */\n unmetered: string[]\n /**\n * ๊ฒฐ์„ ์„ ๋ชจ๋ฅด๋Š” ๋ถ€ํ•˜๊ฐ€ ๋งค๋‹ฌ๋ฆฐ ์ž๋ฆฌ โ€” ์ปค๋„ฅํ„ฐ๊ฐ€ ใ€Œ์–ด๋А ๋ถ„๊ธฐ๊ฐ€ ์ด ์„ค๋น„์— ์ „๊ธฐ๋ฅผ ์ฃผ๋Š”์ง€ ๋ชจ๋ฅธ๋‹คใ€๊ณ  ํŒ๋‹จํ•ด\n * ์ˆ˜์ „์— ๋งค๋‹จ ๊ฒฝ์šฐ๋‹ค. ๊ทธ ์ž๋ฆฌ์˜ ๋ชซ์ด ๋ถ„๊ธฐ๋กœ ๋‚ด๋ ค๊ฐ€์ง€ ์•Š๋Š” ์ด์œ ๊ฐ€ ์ด๊ฒƒ์ด๋‹ค.\n */\n loadsOnIncoming: number\n}\n\n/**\n * ์ด ์„ค๋น„์˜ **์ง€๊ธˆ ๊ฐ’** โ€” ์Šค๋ƒ…์ƒท์—์„œ ๊ทธ ์„ค๋น„๋ฅผ ์ฐพ์•„ ์—๋„ˆ์ง€ ์ถ•์˜ ๊ฐ’๋งŒ ์˜ฎ๊ธด๋‹ค.\n *\n * ์ข…๋ฅ˜๊ฐ€ ์•„๋Š” ํ•„๋“œ๋งŒ ์˜ฎ๊ธด๋‹ค: ํƒœ์–‘๊ด‘์— ์ถฉ์ „์œจ์„ ๋ถ™์ด๊ฑฐ๋‚˜ ์ถ•์ „์ง€์— ๋ฐœ์ „๋Ÿ‰์„ ๋ถ™์ด๋ฉด, ํ™”๋ฉด์€ ๊ทธ๊ฒƒ์„ ์‚ฌ์‹ค๋กœ\n * ๊ทธ๋ฆฌ๊ณ  ์‚ฌ๋žŒ์€ ๊ทธ ์„ค๋น„๊ฐ€ ๊ทธ๋Ÿฐ ์ผ์„ ํ•œ๋‹ค๊ณ  ์ฝ๋Š”๋‹ค(์ปค๋„์ด ์ข…๋ฅ˜๋ณ„๋กœ ํ•„๋“œ๋ฅผ ๊ฐ€๋ ค ๋ฐ›๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ทœ์œจ).\n */\nfunction liveOf(\n state: readonly any[] | undefined | null,\n id: string,\n kind: string\n): { live: NonNullable<TopologySegment['gear'][number]['live']> } | undefined {\n const e = (state ?? []).find(x => String(x?.id ?? '') === id)\n if (!e) return undefined\n const num = (v: unknown): number | undefined => (Number.isFinite(Number(v)) ? Number(v) : undefined)\n const live: NonNullable<TopologySegment['gear'][number]['live']> = {}\n if (kind === 'pv-array') {\n const g = num(e.generatedKW)\n const x = num(e.exportKW)\n if (g !== undefined) live.generatedKW = g\n if (x !== undefined) live.exportKW = x\n } else if (kind === 'battery') {\n const soc = num(e.soc)\n const dis = num(e.dischargeKW)\n const cha = num(e.chargeKW)\n if (soc !== undefined) live.soc = soc\n if (dis !== undefined) live.dischargeKW = dis\n if (cha !== undefined) live.chargeKW = cha\n }\n if (!Object.keys(live).length) return undefined\n /* ๊ฐ’์ด ์žˆ์œผ๋ฉด ์‹œ๊ฐ๋„ ํ•จ๊ป˜ โ€” ์—†์œผ๋ฉด ๋ถ™์ด์ง€ ์•Š๋Š”๋‹ค(๋ชจ๋ฅด๋Š” ์‹œ๊ฐ์„ ์ง€๊ธˆ์œผ๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค). */\n if (e.measuredAt) live.measuredAt = String(e.measuredAt)\n return { live }\n}\n\nconst ELECTRICAL = new Set(EMS_LOCATION_TYPES as readonly string[])\n/** ๋ถ€ํ•˜๊ฐ€ ์•„๋‹Œ ๊ณ„ํ†ต ์„ค๋น„ โ€” ์ด๊ฒƒ๋“ค์˜ ์†Œ๋น„๋ฅผ ๋ถ€ํ•˜๋กœ ์„ธ๋ฉด ์ด๋Ÿ‰์ด ์ด์ค‘์œผ๋กœ ๋‚˜๋‰œ๋‹ค. */\nconst GEAR = new Set(['meter', 'breaker', 'pv-array', 'battery'])\n\n/**\n * ๋ชจ๋ธ + ํด๋“œ ๊ฒฐ๊ณผ โ†’ ๊ณ„ํ†ต ํŠธ๋ฆฌ.\n *\n * @param model ํŠธ์œˆ ๋ชจ๋ธ(์ž๋ฆฌ ๊ณ„์ธต `parentId`, ์„ค๋น„ ์†Œ์† `homeLocation`).\n * @param energy ํด๋“œ๊ฐ€ ๋‚ธ ๋ถ„๊ธฐ๋ณ„ ๋ชซ(์žˆ์œผ๋ฉด ๋…ธ๋“œ์— ์‹ฃ๋Š”๋‹ค โ€” ์—†์œผ๋ฉด ๊ฐ’ ์—†์ด ๊ตฌ์กฐ๋งŒ ๊ทธ๋ฆฐ๋‹ค).\n */\nexport function buildEnergyTopology(\n model: { locations?: any[]; equipment?: any[] } | undefined | null,\n energy?: { byFeeder?: { key: string; kWh: number; basis?: 'measured' | 'apportioned'; peakKW?: number }[] } | null,\n /**\n * ์ง€๊ธˆ์˜ ์„ค๋น„ ์ƒํƒœ(์Šค๋ƒ…์ƒท์˜ `equipment`) โ€” ๋ฐœ์ „ยท์ €์žฅ์˜ **์ง€๊ธˆ ๊ฐ’**์„ ๊ธฐํ˜ธ ์˜†์— ์ ๊ธฐ ์œ„ํ•ด์„œ๋‹ค.\n *\n * ์—†์œผ๋ฉด ๊ฐ’ ์—†์ด ๊ตฌ์กฐ๋งŒ ๊ทธ๋ฆฐ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ฐ’์„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค: ์›์ฒœ์ด ๋ณด๋‚ด์ง€ ์•Š์€ ๊ฒƒ์€ ๋ชจ๋ฅด๋Š” ๊ฒƒ์ด๋‹ค.\n */\n equipmentState?: readonly any[] | null\n): EnergyTopology {\n const locations: any[] = (model?.locations ?? []).filter(n => n?.id && ELECTRICAL.has(String(n.type)))\n const byId = new Map<string, TopologySegment>()\n for (const n of locations) {\n byId.set(String(n.id), {\n id: String(n.id),\n type: String(n.type),\n ...(n.name ? { label: String(n.name) } : {}),\n meters: [],\n loads: [],\n gear: [],\n children: []\n })\n }\n\n const share = new Map((energy?.byFeeder ?? []).map(f => [f.key, f]))\n for (const [id, segment] of byId) {\n const s = share.get(id)\n if (s) {\n segment.kWh = s.kWh\n if (s.basis) segment.basis = s.basis\n if (typeof s.peakKW === 'number') segment.peakKW = s.peakKW\n }\n }\n\n /* ์„ค๋น„๋ฅผ ์ž๊ธฐ ์ž๋ฆฌ์— ๋ถ™์ธ๋‹ค โ€” ๊ณ„๋Ÿ‰๊ธฐ๋Š” ใ€Œ์ด ๊ตฌ๊ฐ„์„ ์žฐ๋‹คใ€๋Š” ๋œป์ด๋ผ ๋”ฐ๋กœ ๋ชจ์€๋‹ค. */\n const unplaced: { id: string; kind: string }[] = []\n let loadsOnIncoming = 0\n for (const e of (model?.equipment ?? []) as any[]) {\n if (!e?.id) continue\n const kind = String(e.kind ?? '')\n const home = String(e.homeLocation ?? e.homeLocationId ?? '')\n const at = byId.get(home)\n if (!at) {\n /* ์ „๊ธฐ ๊ณ„ํ†ต ๋ฐ–์˜ ์ž๋ฆฌ์— ์‚ฌ๋Š” ์„ค๋น„๋„ ์—ฌ๊ธฐ์„œ๋Š” ใ€Œ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅธ๋‹คใ€๋กœ ๋ชจ์€๋‹ค โ€” ์ด ๊ทธ๋ฆผ์˜ ์ถ•์€ ๊ณ„ํ†ต์ด๋‹ค. */\n unplaced.push({ id: String(e.id), kind })\n continue\n }\n if (kind === 'meter') at.meters.push(String(e.id))\n else if (GEAR.has(kind)) at.gear.push({ id: String(e.id), kind, ...(liveOf(equipmentState, String(e.id), kind) ?? {}) })\n else {\n at.loads.push({ id: String(e.id), kind })\n if (at.type === 'incoming') loadsOnIncoming++\n }\n }\n\n /*\n * ๊ณ„์ธต์„ ์ž‡๋Š” ๊ฒƒ์€ **์ „๊ธฐ ์ƒ๋ฅ˜**๋‹ค โ€” ๊ณต๊ฐ„ ๋ถ€๋ชจ(๊ณต์žฅยท๊ตฌ์—ญ)๋Š” ์ด ์ถ•์ด ์•„๋‹ˆ๋‹ค. ์ƒ๋ฅ˜์˜ ๋œป์€ ์ปค๋„์ด ์ฝ๋Š”๋‹ค\n * (์˜› ์„ธ๋Œ€๋Š” ๊ทธ ์•ˆ์—์„œ ํก์ˆ˜๋œ๋‹ค) โ€” ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ํŒ์ •ํ•˜๋ฉด ํ™”๋ฉด๊ณผ ๊ณ„์‚ฐ์ด ๋‹ค๋ฅธ ๊ณ„ํ†ต์„ ๋งํ•˜๊ฒŒ ๋œ๋‹ค.\n */\n const roots: TopologySegment[] = []\n const all = model?.locations ?? []\n for (const n of locations) {\n const segment = byId.get(String(n.id))!\n const up = electricalUpstreamOf(all as any, String(n.id))\n const parent = up ? byId.get(up) : undefined\n if (parent && parent !== segment) parent.children.push(segment)\n else roots.push(segment)\n }\n\n const unmetered = [...byId.values()].filter(n => !n.meters.length).map(n => n.id)\n return { roots, unplaced, unmetered, loadsOnIncoming }\n}\n"]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * ์ด ๋ด‰ํˆฌ๊ฐ€ ๋งํ•˜๋Š” ์‚ฌ์‹ค์˜ ์ •์ฒด โ€” ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ์‚ฌ์‹ค์ด๋‹ค.
3
+ *
4
+ * ๋Œ€์ƒ์ด๋‚˜ ์‹œ๊ฐ์„ ์•Œ ์ˆ˜ ์—†์œผ๋ฉด **์ •์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค**(`undefined`). ๊ทธ๋•Œ๋Š” ๊ฑฐ๋ฅด์ง€ ์•Š๊ณ  ํ†ต๊ณผ์‹œํ‚จ๋‹ค โ€”
5
+ * ๋ชจ๋ฅด๋Š” ๊ฒƒ์„ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์‚ฌ์‹ค์ด ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ง„๋‹ค. ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ์žƒ๋Š” ๊ฒƒ๋ณด๋‹ค ๋‘ ๋ฒˆ ์„ธ๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค.
6
+ */
7
+ export declare function factIdentity(envelope: any): string | undefined;
8
+ /**
9
+ * ์ตœ๊ทผ์— ๋ณธ ์ •์ฒด๋ฅผ ๊ธฐ์–ตํ•œ๋‹ค โ€” **ํฌ๊ธฐ์— ์ƒํ•œ์„ ๋‘”๋‹ค.**
10
+ *
11
+ * ์ „๋ถ€ ๊ธฐ์–ตํ•  ์ˆ˜๋Š” ์—†๋‹ค(ํŠธ์œˆ ํ•˜๋‚˜๊ฐ€ ์ˆ˜์ฒœ๋งŒ ์‚ฌ๊ฑด์„ ๊ฐ–๋Š”๋‹ค). ์ฐฝ์„ ๋„˜์œผ๋ฉด ์˜ค๋ž˜๋œ ๊ฒƒ๋ถ€ํ„ฐ ์žŠ๋Š”๋‹ค. ์ฐฝ ๋ฐ–์˜
12
+ * ์žฌ์ „์†ก์€ ๋‹ค์‹œ ํ†ต๊ณผํ•˜๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ์ ˆ๋Œ€๊ฐ’ ์‚ฌ์‹ค์ด๋ผ ์ƒํƒœ์— ํ•ด๊ฐ€ ์—†๊ณ  ์ง€๋‚œ ๊ธฐ๋ก์— ํ•œ ์ค„ ๋” ๋‚จ๋Š”๋‹ค.
13
+ * ์ฐฝ์„ ํฌ๊ฒŒ ์žก์œผ๋ฉด ๊ทธ๋งŒํผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์“ด๋‹ค โ€” ๊ทธ ๊ฐ’์„ ์—ฌ๊ธฐ์„œ ์ด๋ฆ„์œผ๋กœ ๋ชป ๋ฐ•๋Š”๋‹ค.
14
+ *
15
+ * **์žฌ๊ธฐ๋™์„ ๊ฑด๋„ˆ์ง€ ๋ชปํ•œ๋‹ค.** ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒˆ๋กœ ๋œจ๋ฉด ๊ธฐ์–ต์ด ๋น„์–ด ์žˆ์œผ๋ฏ€๋กœ, ์žฌ๊ธฐ๋™ ์งํ›„ ์ฒซ ์ฃผ๊ธฐ๊ฐ€ ๊ฐ™์€
16
+ * ๊ฐ’์„ ๋‹ค์‹œ ๋ณด๋‚ด๋ฉด ๊ฑธ๋Ÿฌ์ง€์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๊ฒƒ์„ ๋ง‰์œผ๋ ค๋ฉด ์ด ๊ธฐ์–ต์ด ์ €์žฅ๋ผ์•ผ ํ•˜๊ณ , ๊ทธ๊ฒƒ์€ ๋‹ค์Œ ๊ฑธ์Œ์ด๋‹ค.
17
+ * ์ง€๊ธˆ์€ ๊ทธ ์‚ฌ์‹ค์„ ์—ฌ๊ธฐ ์ ์–ด ๋‘”๋‹ค โ€” ์ ์–ด ๋‘์ง€ ์•Š์œผ๋ฉด ใ€Œ์ค‘๋ณต์€ ์ด์ œ ์—†๋‹คใ€๋กœ ์ฝํžŒ๋‹ค.
18
+ */
19
+ export declare class FactDeduper {
20
+ /** ๊ธฐ์–ตํ•˜๋Š” ์ •์ฒด์˜ ์ˆ˜ โ€” ์ฐฝ. */
21
+ static WINDOW: number;
22
+ private seen;
23
+ private order;
24
+ /** ์ด ์‚ฌ์‹ค์„ ๋ณธ ์ ์ด ์žˆ๋‚˜ โ€” ์—†์œผ๋ฉด ๊ธฐ์–ตํ•˜๊ณ  `false`. */
25
+ private known;
26
+ /**
27
+ * ์ฒ˜์Œ ๋ณด๋Š” ๊ฒƒ๋งŒ ๋Œ๋ ค์ค€๋‹ค โ€” ๊ทธ๋ฆฌ๊ณ  ๋ช‡ ๊ฐœ๋ฅผ ๋ฒ„๋ ธ๋Š”์ง€ ํ•จ๊ป˜ ๋‚ธ๋‹ค.
28
+ *
29
+ * ๋ฒ„๋ฆฐ ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋‚ด๋Š” ์ด์œ : ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋ฒ„๋ฆฌ๋ฉด ใ€Œ๋ณด๋‚ธ ์ˆ˜ใ€์™€ ใ€Œ๋ฐ˜์˜๋œ ์ˆ˜ใ€๊ฐ€ ์–ด๊ธ‹๋‚˜๋Š”๋ฐ ์•„๋ฌด๋„ ๊ทธ
30
+ * ์ด์œ ๋ฅผ ๋ชจ๋ฅธ๋‹ค. ๊ทธ ์ˆ˜๊ฐ€ ํฌ๋ฉด ๋ณด๋‚ด๋Š” ์ชฝ์ด ๋˜ํ’€์ด ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ , ๊ทธ๊ฒƒ์€ ๊ณ ์น  ์ผ์ด๋‹ค.
31
+ */
32
+ filter<T>(envelopes: readonly T[]): {
33
+ fresh: T[];
34
+ duplicates: number;
35
+ };
36
+ /** ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋Š” ์ •์ฒด์˜ ์ˆ˜ โ€” ๊ณ„๊ธฐ๊ฐ€ ์ฝ๋Š”๋‹ค. */
37
+ size(): number;
38
+ }
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ /*
3
+ * ๊ฐ™์€ ์‚ฌ์‹ค์„ ๋‘ ๋ฒˆ ๋ฐ›์œผ๋ฉด ํ•œ ๋ฒˆ๋งŒ ๋ฐ˜์˜ํ•œ๋‹ค โ€” **์œ ์ž… ๊ฒฝ๊ณ„ ํ•œ ๊ณณ์—์„œ.**
4
+ *
5
+ * โ”€โ”€ ์™œ ํ•„์š”ํ•œ๊ฐ€ (2026-08-26) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
6
+ * ์ง€๊ธˆ ์ค‘๋ณต์„ ๋ง‰๋Š” ๊ฒƒ์€ ์ปค๋„ฅํ„ฐ๋งˆ๋‹ค ๊ฐ์ž ํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ปค๋„ฅํ„ฐ๊ฐ€ ๊ทธ๊ฒƒ์„ ์žŠ์œผ๋ฉด ํŠธ์œˆ์ด ๊ทธ๋Œ€๋กœ ๋‘ ๋ฒˆ
7
+ * ์„ผ๋‹ค. ์‹ค์ œ๋กœ ๊ทธ๋žฌ๋‹ค: ํƒœ์–‘๊ด‘ ์ปค๋„ฅํ„ฐ๊ฐ€ 10์ดˆ๋งˆ๋‹ค ๋ฌผ์œผ๋ฉด์„œ 10๋ถ„๋งˆ๋‹ค ๋ฐ”๋€Œ๋Š” ๊ฐ’์„ ๋งค๋ฒˆ ๋‹ค์‹œ ๋ณด๋ƒˆ๊ณ ,
8
+ * ํ•œ ์ฃผ๊ธฐ์— 76๊ฑด์ด ๋˜ํ’€์ด๋๋‹ค(์ปค๋„ฅํ„ฐ์—์„œ ๊ณ ์ณ์„œ 2๊ฑด์ด ๋๋‹ค).
9
+ *
10
+ * ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ์›นํ›…์œผ๋กœ ๋ฐ›์„ ๋•Œ ๋” ์ž์ฃผ ๋‚œ๋‹ค. ๋ฐ€์–ด ์ฃผ๋Š” ๋ฐฉ์‹์€ ์žฌ์ „์†ก์ด ์ •์ƒ์ด๋‹ค โ€” ๊ทธ์ชฝ์ด ์‘๋‹ต์„
11
+ * ๋ชป ๋ฐ›์œผ๋ฉด ๊ฐ™์€ ๊ฒƒ์„ ๋‹ค์‹œ ๋ณด๋‚ธ๋‹ค.
12
+ *
13
+ * โ”€โ”€ ๋ฌด์—‡์ด ๋‘ ๋ฒˆ ์„ธ์–ด์ง€๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
14
+ * ์ ˆ๋Œ€๊ฐ’์œผ๋กœ ๋งํ•˜๋Š” ์‚ฌ์‹ค์€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜์˜ํ•ด๋„ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™๋‹ค(์ž”๋Ÿ‰ ยท ์ƒํƒœ ยท ์ ์‚ฐ ยท ์ˆœ๊ฐ„ kW). ๊ทธ๋Ÿฐ๋ฐ ์„ธ๋Š”
15
+ * ๊ฐ’์€ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค.
16
+ *
17
+ * ๊ตฌ๊ฐ„์˜ ํ‘œ๋ณธ ์ˆ˜ ยท ํ‰๊ท  ๋ถ€ํ•˜(ํ‘œ๋ณธ ์ˆ˜๋กœ ๋‚˜๋ˆˆ๋‹ค) ยท OEE ์นด์šดํ„ฐ ยท ์œ ์ž… ๊ณ„์ˆ˜
18
+ * ๊ทธ๋ฆฌ๊ณ  ์ง€๋‚œ ๊ธฐ๋ก์— ๊ฐ™์€ ์‚ฌ์‹ค์ด ๋‘ ์ค„๋กœ ๋‚จ๋Š”๋‹ค โ€” ๋‚˜์ค‘์— ๊ทธ ๊ธฐ๋ก์œผ๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋ฉด ๋˜ ๋‘ ๋ฒˆ ์„ผ๋‹ค
19
+ *
20
+ * โ”€โ”€ ์ •์ฒด๋ฅผ ๋ฌด์—‡์œผ๋กœ ๋ณด๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
21
+ * ๋ด‰ํˆฌ์˜ `eventId` ๋กœ๋Š” ํŒ๋‹จํ•  ์ˆ˜ ์—†๋‹ค. ๋ณด๋‚ธ ์ชฝ์ด ๋งค๋ฒˆ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ์ˆœ๋ฒˆ์ด๊ณ (`โ€ฆ-energy-1` ์ฒ˜๋Ÿผ ํ˜ธ์ถœ๋งˆ๋‹ค
22
+ * 1๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ์ž‘ํ•œ๋‹ค), ๊ฐ™์€ ์‚ฌ์‹ค์„ ๋‘ ๋ฒˆ ๋ณด๋‚ด๋ฉด ๋‹ค๋ฅธ ๋ฒˆํ˜ธ๊ฐ€ ๋ถ™๋Š”๋‹ค. ๋‹ค๋ฅธ ์‚ฌ์‹ค์— ๊ฐ™์€ ๋ฒˆํ˜ธ๊ฐ€ ๋ถ™๋Š” ์ผ๋„
23
+ * ์ƒ๊ธด๋‹ค.
24
+ *
25
+ * ๊ทธ๋ž˜์„œ **์‚ฌ์‹ค ์ž์ฒด๋กœ** ํŒ๋‹จํ•œ๋‹ค.
26
+ *
27
+ * ๋ฌด์—‡์— ๋Œ€ํ•œ ๊ฒƒ์ธ๊ฐ€ ์„ค๋น„ ยท ๊ณ„๋Ÿ‰ ์ง€์  ยท ๋ฌผํ’ˆ ยท ์ž‘์—… ยท ์˜ค๋” ยท ์ž๋ฆฌ
28
+ * ์–ด๋–ค ์ข…๋ฅ˜์ธ๊ฐ€ ์‚ฌ๊ฑด ์ข…๋ฅ˜(eventType)
29
+ * ์–ธ์ œ ์žฐ ๊ฒƒ์ธ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ์ด ์ค€ ์‹œ๊ฐ
30
+ *
31
+ * ์ด ์…‹์ด ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ์‚ฌ์‹ค์ด๋‹ค. ํƒœ์–‘๊ด‘ ์ปค๋„ฅํ„ฐ๊ฐ€ `collectedAt` ์œผ๋กœ ํŒ๋‹จํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์ด๊ณ , ๊ทธ๊ฒƒ์„
32
+ * ์ปค๋„ฅํ„ฐ๋งˆ๋‹ค ํ•˜์ง€ ์•Š๋„๋ก ์—ฌ๊ธฐ๋กœ ์˜ฌ๋ฆฐ๋‹ค.
33
+ *
34
+ * โ”€โ”€ ์ •ํ™•ํžˆ ๊ฐ™์€ ๊ฒƒ๋งŒ ๋ฒ„๋ฆฐ๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
35
+ * ๋Šฆ๊ฒŒ ๋„์ฐฉํ•œ ์˜› ์‚ฌ์‹ค์€ ๋ฒ„๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๊ฒƒ์ด ์™”๋‹ค๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ์‚ฌ์‹ค์ด๊ณ , ์ƒํƒœ์— ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š” ๊ฒƒ์€
36
+ * ์ปค๋„์˜ ์ˆœ์„œ ํŒ๋‹จ์ด ์ด๋ฏธ ๋งก๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์€ **์ •์ฒด๊ฐ€ ์™„์ „ํžˆ ๊ฐ™์€ ๊ฒƒ**๋ฟ์ด๋‹ค.
37
+ */
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FactDeduper = void 0;
40
+ exports.factIdentity = factIdentity;
41
+ /** ์‹œ๊ฐ์„ ๋ฐ€๋ฆฌ์ดˆ๋กœ โ€” ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ์ด ์ค€ ์‹œ๊ฐ์ด ๋จผ์ €, ์—†์œผ๋ฉด ๋ด‰ํˆฌ์˜ ์‹œ๊ฐ. */
42
+ function timeOf(envelope) {
43
+ for (const v of [envelope?.data?.at, envelope?.data?.eventTime, envelope?.eventTime]) {
44
+ const t = Date.parse(String(v ?? ''));
45
+ if (Number.isFinite(t))
46
+ return t;
47
+ }
48
+ return undefined;
49
+ }
50
+ /**
51
+ * ์ด ๋ด‰ํˆฌ๊ฐ€ ๋งํ•˜๋Š” ๋Œ€์ƒ โ€” ์–ดํœ˜๋งˆ๋‹ค ์ด๋ฆ„์ด ๋‹ค๋ฅด๋ฏ€๋กœ ์•„๋Š” ์ด๋ฆ„์„ ๋ชจ๋‘ ๋ณธ๋‹ค.
52
+ *
53
+ * ์ˆœ์„œ๊ฐ€ ๋œป์„ ๊ฐ–๋Š”๋‹ค: ์ฃผ์ฒด๋ฅผ ๋จผ์ € ๋ณธ๋‹ค. ์„ค๋น„ ์‚ฌ์‹ค์€ ใ€Œ์ง€๊ธˆ ๋ถ™์–ด ์žˆ๋Š” ์ž‘์—…ใ€์„ ํ•จ๊ป˜ ์‹ฃ๊ณ , ์ž‘์—… ์‚ฌ์‹ค์€
54
+ * ใ€Œ์†Œ์† ์˜ค๋”ใ€๋ฅผ ํ•จ๊ป˜ ์‹ฃ๋Š”๋‹ค. ์•„๋ฌด ์ด๋ฆ„์ด๋‚˜ ๋จผ์ € ๋ณด๋ฉด ์ฐธ์กฐ๋ฅผ ์ฃผ์ฒด๋กœ ์ฝ๋Š”๋‹ค(์Šน๊ฒฉ ํ‚ค์—์„œ ๊ฒช์€ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค).
55
+ */
56
+ function targetOf(envelope) {
57
+ const d = envelope?.data ?? {};
58
+ const first = (...vals) => {
59
+ for (const v of vals) {
60
+ const s = String(v ?? '').trim();
61
+ if (s)
62
+ return s;
63
+ }
64
+ return undefined;
65
+ };
66
+ return first(d.meterId, d.equipmentId, d.moverId, d.taskId, d.orderId, d.personId, d.assetId, d.locationId, d.epcList?.[0], d.parentID, d.quantityList?.[0]?.epcClass, d.transformationID);
67
+ }
68
+ /**
69
+ * ์ด ๋ด‰ํˆฌ๊ฐ€ ๋งํ•˜๋Š” ์‚ฌ์‹ค์˜ ์ •์ฒด โ€” ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ์‚ฌ์‹ค์ด๋‹ค.
70
+ *
71
+ * ๋Œ€์ƒ์ด๋‚˜ ์‹œ๊ฐ์„ ์•Œ ์ˆ˜ ์—†์œผ๋ฉด **์ •์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค**(`undefined`). ๊ทธ๋•Œ๋Š” ๊ฑฐ๋ฅด์ง€ ์•Š๊ณ  ํ†ต๊ณผ์‹œํ‚จ๋‹ค โ€”
72
+ * ๋ชจ๋ฅด๋Š” ๊ฒƒ์„ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์‚ฌ์‹ค์ด ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ง„๋‹ค. ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ์žƒ๋Š” ๊ฒƒ๋ณด๋‹ค ๋‘ ๋ฒˆ ์„ธ๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค.
73
+ */
74
+ function factIdentity(envelope) {
75
+ const type = String(envelope?.eventType ?? '').trim();
76
+ if (!type)
77
+ return undefined;
78
+ const target = targetOf(envelope);
79
+ if (!target)
80
+ return undefined;
81
+ const at = timeOf(envelope);
82
+ if (at === undefined)
83
+ return undefined;
84
+ return `${type}|${target}|${at}`;
85
+ }
86
+ /**
87
+ * ์ตœ๊ทผ์— ๋ณธ ์ •์ฒด๋ฅผ ๊ธฐ์–ตํ•œ๋‹ค โ€” **ํฌ๊ธฐ์— ์ƒํ•œ์„ ๋‘”๋‹ค.**
88
+ *
89
+ * ์ „๋ถ€ ๊ธฐ์–ตํ•  ์ˆ˜๋Š” ์—†๋‹ค(ํŠธ์œˆ ํ•˜๋‚˜๊ฐ€ ์ˆ˜์ฒœ๋งŒ ์‚ฌ๊ฑด์„ ๊ฐ–๋Š”๋‹ค). ์ฐฝ์„ ๋„˜์œผ๋ฉด ์˜ค๋ž˜๋œ ๊ฒƒ๋ถ€ํ„ฐ ์žŠ๋Š”๋‹ค. ์ฐฝ ๋ฐ–์˜
90
+ * ์žฌ์ „์†ก์€ ๋‹ค์‹œ ํ†ต๊ณผํ•˜๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ์ ˆ๋Œ€๊ฐ’ ์‚ฌ์‹ค์ด๋ผ ์ƒํƒœ์— ํ•ด๊ฐ€ ์—†๊ณ  ์ง€๋‚œ ๊ธฐ๋ก์— ํ•œ ์ค„ ๋” ๋‚จ๋Š”๋‹ค.
91
+ * ์ฐฝ์„ ํฌ๊ฒŒ ์žก์œผ๋ฉด ๊ทธ๋งŒํผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์“ด๋‹ค โ€” ๊ทธ ๊ฐ’์„ ์—ฌ๊ธฐ์„œ ์ด๋ฆ„์œผ๋กœ ๋ชป ๋ฐ•๋Š”๋‹ค.
92
+ *
93
+ * **์žฌ๊ธฐ๋™์„ ๊ฑด๋„ˆ์ง€ ๋ชปํ•œ๋‹ค.** ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒˆ๋กœ ๋œจ๋ฉด ๊ธฐ์–ต์ด ๋น„์–ด ์žˆ์œผ๋ฏ€๋กœ, ์žฌ๊ธฐ๋™ ์งํ›„ ์ฒซ ์ฃผ๊ธฐ๊ฐ€ ๊ฐ™์€
94
+ * ๊ฐ’์„ ๋‹ค์‹œ ๋ณด๋‚ด๋ฉด ๊ฑธ๋Ÿฌ์ง€์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๊ฒƒ์„ ๋ง‰์œผ๋ ค๋ฉด ์ด ๊ธฐ์–ต์ด ์ €์žฅ๋ผ์•ผ ํ•˜๊ณ , ๊ทธ๊ฒƒ์€ ๋‹ค์Œ ๊ฑธ์Œ์ด๋‹ค.
95
+ * ์ง€๊ธˆ์€ ๊ทธ ์‚ฌ์‹ค์„ ์—ฌ๊ธฐ ์ ์–ด ๋‘”๋‹ค โ€” ์ ์–ด ๋‘์ง€ ์•Š์œผ๋ฉด ใ€Œ์ค‘๋ณต์€ ์ด์ œ ์—†๋‹คใ€๋กœ ์ฝํžŒ๋‹ค.
96
+ */
97
+ class FactDeduper {
98
+ constructor() {
99
+ this.seen = new Set();
100
+ this.order = [];
101
+ }
102
+ /** ๊ธฐ์–ตํ•˜๋Š” ์ •์ฒด์˜ ์ˆ˜ โ€” ์ฐฝ. */
103
+ static { this.WINDOW = 20_000; }
104
+ /** ์ด ์‚ฌ์‹ค์„ ๋ณธ ์ ์ด ์žˆ๋‚˜ โ€” ์—†์œผ๋ฉด ๊ธฐ์–ตํ•˜๊ณ  `false`. */
105
+ known(identity) {
106
+ if (this.seen.has(identity))
107
+ return true;
108
+ this.seen.add(identity);
109
+ this.order.push(identity);
110
+ if (this.order.length > FactDeduper.WINDOW) {
111
+ const gone = this.order.splice(0, this.order.length - FactDeduper.WINDOW);
112
+ for (const g of gone)
113
+ this.seen.delete(g);
114
+ }
115
+ return false;
116
+ }
117
+ /**
118
+ * ์ฒ˜์Œ ๋ณด๋Š” ๊ฒƒ๋งŒ ๋Œ๋ ค์ค€๋‹ค โ€” ๊ทธ๋ฆฌ๊ณ  ๋ช‡ ๊ฐœ๋ฅผ ๋ฒ„๋ ธ๋Š”์ง€ ํ•จ๊ป˜ ๋‚ธ๋‹ค.
119
+ *
120
+ * ๋ฒ„๋ฆฐ ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋‚ด๋Š” ์ด์œ : ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋ฒ„๋ฆฌ๋ฉด ใ€Œ๋ณด๋‚ธ ์ˆ˜ใ€์™€ ใ€Œ๋ฐ˜์˜๋œ ์ˆ˜ใ€๊ฐ€ ์–ด๊ธ‹๋‚˜๋Š”๋ฐ ์•„๋ฌด๋„ ๊ทธ
121
+ * ์ด์œ ๋ฅผ ๋ชจ๋ฅธ๋‹ค. ๊ทธ ์ˆ˜๊ฐ€ ํฌ๋ฉด ๋ณด๋‚ด๋Š” ์ชฝ์ด ๋˜ํ’€์ด ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ , ๊ทธ๊ฒƒ์€ ๊ณ ์น  ์ผ์ด๋‹ค.
122
+ */
123
+ filter(envelopes) {
124
+ const fresh = [];
125
+ let duplicates = 0;
126
+ for (const e of envelopes) {
127
+ const id = factIdentity(e);
128
+ if (id === undefined) {
129
+ fresh.push(e);
130
+ continue;
131
+ }
132
+ if (this.known(id))
133
+ duplicates++;
134
+ else
135
+ fresh.push(e);
136
+ }
137
+ return { fresh, duplicates };
138
+ }
139
+ /** ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋Š” ์ •์ฒด์˜ ์ˆ˜ โ€” ๊ณ„๊ธฐ๊ฐ€ ์ฝ๋Š”๋‹ค. */
140
+ size() {
141
+ return this.seen.size;
142
+ }
143
+ }
144
+ exports.FactDeduper = FactDeduper;
145
+ //# sourceMappingURL=ingest-dedupe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-dedupe.js","sourceRoot":"","sources":["../../server/engine/ingest-dedupe.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;;;AAgDH,oCAQC;AAtDD,gDAAgD;AAChD,SAAS,MAAM,CAAC,QAAa;IAC3B,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;QACrF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACrC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;GAKG;AACH,SAAS,QAAQ,CAAC,QAAa;IAC7B,MAAM,CAAC,GAAG,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAA;IAC9B,MAAM,KAAK,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;QACnC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;YAChC,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAA;QACjB,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC,CAAA;IACD,OAAO,KAAK,CACV,CAAC,CAAC,OAAO,EACT,CAAC,CAAC,WAAW,EACb,CAAC,CAAC,OAAO,EACT,CAAC,CAAC,MAAM,EACR,CAAC,CAAC,OAAO,EACT,CAAC,CAAC,QAAQ,EACV,CAAC,CAAC,OAAO,EACT,CAAC,CAAC,UAAU,EACZ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EACd,CAAC,CAAC,QAAQ,EACV,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAC7B,CAAC,CAAC,gBAAgB,CACnB,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,QAAa;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACrD,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACjC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC3B,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACtC,OAAO,GAAG,IAAI,IAAI,MAAM,IAAI,EAAE,EAAE,CAAA;AAClC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAa,WAAW;IAAxB;QAIU,SAAI,GAAG,IAAI,GAAG,EAAU,CAAA;QACxB,UAAK,GAAa,EAAE,CAAA;IAuC9B,CAAC;IA3CC,sBAAsB;aACf,WAAM,GAAG,MAAM,AAAT,CAAS;IAKtB,wCAAwC;IAChC,KAAK,CAAC,QAAgB;QAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAA;QACxC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACvB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACzB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;YACzE,KAAK,MAAM,CAAC,IAAI,IAAI;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC3C,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAI,SAAuB;QAC/B,MAAM,KAAK,GAAQ,EAAE,CAAA;QACrB,IAAI,UAAU,GAAG,CAAC,CAAA;QAClB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAA;YAC1B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACb,SAAQ;YACV,CAAC;YACD,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAAE,UAAU,EAAE,CAAA;;gBAC3B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACpB,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;IAC9B,CAAC;IAED,+BAA+B;IAC/B,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;IACvB,CAAC;;AA3CH,kCA4CC","sourcesContent":["/*\n * ๊ฐ™์€ ์‚ฌ์‹ค์„ ๋‘ ๋ฒˆ ๋ฐ›์œผ๋ฉด ํ•œ ๋ฒˆ๋งŒ ๋ฐ˜์˜ํ•œ๋‹ค โ€” **์œ ์ž… ๊ฒฝ๊ณ„ ํ•œ ๊ณณ์—์„œ.**\n *\n * โ”€โ”€ ์™œ ํ•„์š”ํ•œ๊ฐ€ (2026-08-26) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ง€๊ธˆ ์ค‘๋ณต์„ ๋ง‰๋Š” ๊ฒƒ์€ ์ปค๋„ฅํ„ฐ๋งˆ๋‹ค ๊ฐ์ž ํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ปค๋„ฅํ„ฐ๊ฐ€ ๊ทธ๊ฒƒ์„ ์žŠ์œผ๋ฉด ํŠธ์œˆ์ด ๊ทธ๋Œ€๋กœ ๋‘ ๋ฒˆ\n * ์„ผ๋‹ค. ์‹ค์ œ๋กœ ๊ทธ๋žฌ๋‹ค: ํƒœ์–‘๊ด‘ ์ปค๋„ฅํ„ฐ๊ฐ€ 10์ดˆ๋งˆ๋‹ค ๋ฌผ์œผ๋ฉด์„œ 10๋ถ„๋งˆ๋‹ค ๋ฐ”๋€Œ๋Š” ๊ฐ’์„ ๋งค๋ฒˆ ๋‹ค์‹œ ๋ณด๋ƒˆ๊ณ ,\n * ํ•œ ์ฃผ๊ธฐ์— 76๊ฑด์ด ๋˜ํ’€์ด๋๋‹ค(์ปค๋„ฅํ„ฐ์—์„œ ๊ณ ์ณ์„œ 2๊ฑด์ด ๋๋‹ค).\n *\n * ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ์›นํ›…์œผ๋กœ ๋ฐ›์„ ๋•Œ ๋” ์ž์ฃผ ๋‚œ๋‹ค. ๋ฐ€์–ด ์ฃผ๋Š” ๋ฐฉ์‹์€ ์žฌ์ „์†ก์ด ์ •์ƒ์ด๋‹ค โ€” ๊ทธ์ชฝ์ด ์‘๋‹ต์„\n * ๋ชป ๋ฐ›์œผ๋ฉด ๊ฐ™์€ ๊ฒƒ์„ ๋‹ค์‹œ ๋ณด๋‚ธ๋‹ค.\n *\n * โ”€โ”€ ๋ฌด์—‡์ด ๋‘ ๋ฒˆ ์„ธ์–ด์ง€๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ ˆ๋Œ€๊ฐ’์œผ๋กœ ๋งํ•˜๋Š” ์‚ฌ์‹ค์€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜์˜ํ•ด๋„ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™๋‹ค(์ž”๋Ÿ‰ ยท ์ƒํƒœ ยท ์ ์‚ฐ ยท ์ˆœ๊ฐ„ kW). ๊ทธ๋Ÿฐ๋ฐ ์„ธ๋Š”\n * ๊ฐ’์€ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค.\n *\n * ๊ตฌ๊ฐ„์˜ ํ‘œ๋ณธ ์ˆ˜ ยท ํ‰๊ท  ๋ถ€ํ•˜(ํ‘œ๋ณธ ์ˆ˜๋กœ ๋‚˜๋ˆˆ๋‹ค) ยท OEE ์นด์šดํ„ฐ ยท ์œ ์ž… ๊ณ„์ˆ˜\n * ๊ทธ๋ฆฌ๊ณ  ์ง€๋‚œ ๊ธฐ๋ก์— ๊ฐ™์€ ์‚ฌ์‹ค์ด ๋‘ ์ค„๋กœ ๋‚จ๋Š”๋‹ค โ€” ๋‚˜์ค‘์— ๊ทธ ๊ธฐ๋ก์œผ๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋ฉด ๋˜ ๋‘ ๋ฒˆ ์„ผ๋‹ค\n *\n * โ”€โ”€ ์ •์ฒด๋ฅผ ๋ฌด์—‡์œผ๋กœ ๋ณด๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ๋ด‰ํˆฌ์˜ `eventId` ๋กœ๋Š” ํŒ๋‹จํ•  ์ˆ˜ ์—†๋‹ค. ๋ณด๋‚ธ ์ชฝ์ด ๋งค๋ฒˆ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ์ˆœ๋ฒˆ์ด๊ณ (`โ€ฆ-energy-1` ์ฒ˜๋Ÿผ ํ˜ธ์ถœ๋งˆ๋‹ค\n * 1๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ์ž‘ํ•œ๋‹ค), ๊ฐ™์€ ์‚ฌ์‹ค์„ ๋‘ ๋ฒˆ ๋ณด๋‚ด๋ฉด ๋‹ค๋ฅธ ๋ฒˆํ˜ธ๊ฐ€ ๋ถ™๋Š”๋‹ค. ๋‹ค๋ฅธ ์‚ฌ์‹ค์— ๊ฐ™์€ ๋ฒˆํ˜ธ๊ฐ€ ๋ถ™๋Š” ์ผ๋„\n * ์ƒ๊ธด๋‹ค.\n *\n * ๊ทธ๋ž˜์„œ **์‚ฌ์‹ค ์ž์ฒด๋กœ** ํŒ๋‹จํ•œ๋‹ค.\n *\n * ๋ฌด์—‡์— ๋Œ€ํ•œ ๊ฒƒ์ธ๊ฐ€ ์„ค๋น„ ยท ๊ณ„๋Ÿ‰ ์ง€์  ยท ๋ฌผํ’ˆ ยท ์ž‘์—… ยท ์˜ค๋” ยท ์ž๋ฆฌ\n * ์–ด๋–ค ์ข…๋ฅ˜์ธ๊ฐ€ ์‚ฌ๊ฑด ์ข…๋ฅ˜(eventType)\n * ์–ธ์ œ ์žฐ ๊ฒƒ์ธ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ์ด ์ค€ ์‹œ๊ฐ\n *\n * ์ด ์…‹์ด ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ์‚ฌ์‹ค์ด๋‹ค. ํƒœ์–‘๊ด‘ ์ปค๋„ฅํ„ฐ๊ฐ€ `collectedAt` ์œผ๋กœ ํŒ๋‹จํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์ด๊ณ , ๊ทธ๊ฒƒ์„\n * ์ปค๋„ฅํ„ฐ๋งˆ๋‹ค ํ•˜์ง€ ์•Š๋„๋ก ์—ฌ๊ธฐ๋กœ ์˜ฌ๋ฆฐ๋‹ค.\n *\n * โ”€โ”€ ์ •ํ™•ํžˆ ๊ฐ™์€ ๊ฒƒ๋งŒ ๋ฒ„๋ฆฐ๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ๋Šฆ๊ฒŒ ๋„์ฐฉํ•œ ์˜› ์‚ฌ์‹ค์€ ๋ฒ„๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๊ฒƒ์ด ์™”๋‹ค๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ์‚ฌ์‹ค์ด๊ณ , ์ƒํƒœ์— ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š” ๊ฒƒ์€\n * ์ปค๋„์˜ ์ˆœ์„œ ํŒ๋‹จ์ด ์ด๋ฏธ ๋งก๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์€ **์ •์ฒด๊ฐ€ ์™„์ „ํžˆ ๊ฐ™์€ ๊ฒƒ**๋ฟ์ด๋‹ค.\n */\n\n/** ์‹œ๊ฐ์„ ๋ฐ€๋ฆฌ์ดˆ๋กœ โ€” ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ์ด ์ค€ ์‹œ๊ฐ์ด ๋จผ์ €, ์—†์œผ๋ฉด ๋ด‰ํˆฌ์˜ ์‹œ๊ฐ. */\nfunction timeOf(envelope: any): number | undefined {\n for (const v of [envelope?.data?.at, envelope?.data?.eventTime, envelope?.eventTime]) {\n const t = Date.parse(String(v ?? ''))\n if (Number.isFinite(t)) return t\n }\n return undefined\n}\n\n/**\n * ์ด ๋ด‰ํˆฌ๊ฐ€ ๋งํ•˜๋Š” ๋Œ€์ƒ โ€” ์–ดํœ˜๋งˆ๋‹ค ์ด๋ฆ„์ด ๋‹ค๋ฅด๋ฏ€๋กœ ์•„๋Š” ์ด๋ฆ„์„ ๋ชจ๋‘ ๋ณธ๋‹ค.\n *\n * ์ˆœ์„œ๊ฐ€ ๋œป์„ ๊ฐ–๋Š”๋‹ค: ์ฃผ์ฒด๋ฅผ ๋จผ์ € ๋ณธ๋‹ค. ์„ค๋น„ ์‚ฌ์‹ค์€ ใ€Œ์ง€๊ธˆ ๋ถ™์–ด ์žˆ๋Š” ์ž‘์—…ใ€์„ ํ•จ๊ป˜ ์‹ฃ๊ณ , ์ž‘์—… ์‚ฌ์‹ค์€\n * ใ€Œ์†Œ์† ์˜ค๋”ใ€๋ฅผ ํ•จ๊ป˜ ์‹ฃ๋Š”๋‹ค. ์•„๋ฌด ์ด๋ฆ„์ด๋‚˜ ๋จผ์ € ๋ณด๋ฉด ์ฐธ์กฐ๋ฅผ ์ฃผ์ฒด๋กœ ์ฝ๋Š”๋‹ค(์Šน๊ฒฉ ํ‚ค์—์„œ ๊ฒช์€ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค).\n */\nfunction targetOf(envelope: any): string | undefined {\n const d = envelope?.data ?? {}\n const first = (...vals: unknown[]) => {\n for (const v of vals) {\n const s = String(v ?? '').trim()\n if (s) return s\n }\n return undefined\n }\n return first(\n d.meterId,\n d.equipmentId,\n d.moverId,\n d.taskId,\n d.orderId,\n d.personId,\n d.assetId,\n d.locationId,\n d.epcList?.[0],\n d.parentID,\n d.quantityList?.[0]?.epcClass,\n d.transformationID\n )\n}\n\n/**\n * ์ด ๋ด‰ํˆฌ๊ฐ€ ๋งํ•˜๋Š” ์‚ฌ์‹ค์˜ ์ •์ฒด โ€” ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ์‚ฌ์‹ค์ด๋‹ค.\n *\n * ๋Œ€์ƒ์ด๋‚˜ ์‹œ๊ฐ์„ ์•Œ ์ˆ˜ ์—†์œผ๋ฉด **์ •์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค**(`undefined`). ๊ทธ๋•Œ๋Š” ๊ฑฐ๋ฅด์ง€ ์•Š๊ณ  ํ†ต๊ณผ์‹œํ‚จ๋‹ค โ€”\n * ๋ชจ๋ฅด๋Š” ๊ฒƒ์„ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์‚ฌ์‹ค์ด ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ง„๋‹ค. ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ์žƒ๋Š” ๊ฒƒ๋ณด๋‹ค ๋‘ ๋ฒˆ ์„ธ๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค.\n */\nexport function factIdentity(envelope: any): string | undefined {\n const type = String(envelope?.eventType ?? '').trim()\n if (!type) return undefined\n const target = targetOf(envelope)\n if (!target) return undefined\n const at = timeOf(envelope)\n if (at === undefined) return undefined\n return `${type}|${target}|${at}`\n}\n\n/**\n * ์ตœ๊ทผ์— ๋ณธ ์ •์ฒด๋ฅผ ๊ธฐ์–ตํ•œ๋‹ค โ€” **ํฌ๊ธฐ์— ์ƒํ•œ์„ ๋‘”๋‹ค.**\n *\n * ์ „๋ถ€ ๊ธฐ์–ตํ•  ์ˆ˜๋Š” ์—†๋‹ค(ํŠธ์œˆ ํ•˜๋‚˜๊ฐ€ ์ˆ˜์ฒœ๋งŒ ์‚ฌ๊ฑด์„ ๊ฐ–๋Š”๋‹ค). ์ฐฝ์„ ๋„˜์œผ๋ฉด ์˜ค๋ž˜๋œ ๊ฒƒ๋ถ€ํ„ฐ ์žŠ๋Š”๋‹ค. ์ฐฝ ๋ฐ–์˜\n * ์žฌ์ „์†ก์€ ๋‹ค์‹œ ํ†ต๊ณผํ•˜๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ์ ˆ๋Œ€๊ฐ’ ์‚ฌ์‹ค์ด๋ผ ์ƒํƒœ์— ํ•ด๊ฐ€ ์—†๊ณ  ์ง€๋‚œ ๊ธฐ๋ก์— ํ•œ ์ค„ ๋” ๋‚จ๋Š”๋‹ค.\n * ์ฐฝ์„ ํฌ๊ฒŒ ์žก์œผ๋ฉด ๊ทธ๋งŒํผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์“ด๋‹ค โ€” ๊ทธ ๊ฐ’์„ ์—ฌ๊ธฐ์„œ ์ด๋ฆ„์œผ๋กœ ๋ชป ๋ฐ•๋Š”๋‹ค.\n *\n * **์žฌ๊ธฐ๋™์„ ๊ฑด๋„ˆ์ง€ ๋ชปํ•œ๋‹ค.** ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒˆ๋กœ ๋œจ๋ฉด ๊ธฐ์–ต์ด ๋น„์–ด ์žˆ์œผ๋ฏ€๋กœ, ์žฌ๊ธฐ๋™ ์งํ›„ ์ฒซ ์ฃผ๊ธฐ๊ฐ€ ๊ฐ™์€\n * ๊ฐ’์„ ๋‹ค์‹œ ๋ณด๋‚ด๋ฉด ๊ฑธ๋Ÿฌ์ง€์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๊ฒƒ์„ ๋ง‰์œผ๋ ค๋ฉด ์ด ๊ธฐ์–ต์ด ์ €์žฅ๋ผ์•ผ ํ•˜๊ณ , ๊ทธ๊ฒƒ์€ ๋‹ค์Œ ๊ฑธ์Œ์ด๋‹ค.\n * ์ง€๊ธˆ์€ ๊ทธ ์‚ฌ์‹ค์„ ์—ฌ๊ธฐ ์ ์–ด ๋‘”๋‹ค โ€” ์ ์–ด ๋‘์ง€ ์•Š์œผ๋ฉด ใ€Œ์ค‘๋ณต์€ ์ด์ œ ์—†๋‹คใ€๋กœ ์ฝํžŒ๋‹ค.\n */\nexport class FactDeduper {\n /** ๊ธฐ์–ตํ•˜๋Š” ์ •์ฒด์˜ ์ˆ˜ โ€” ์ฐฝ. */\n static WINDOW = 20_000\n\n private seen = new Set<string>()\n private order: string[] = []\n\n /** ์ด ์‚ฌ์‹ค์„ ๋ณธ ์ ์ด ์žˆ๋‚˜ โ€” ์—†์œผ๋ฉด ๊ธฐ์–ตํ•˜๊ณ  `false`. */\n private known(identity: string): boolean {\n if (this.seen.has(identity)) return true\n this.seen.add(identity)\n this.order.push(identity)\n if (this.order.length > FactDeduper.WINDOW) {\n const gone = this.order.splice(0, this.order.length - FactDeduper.WINDOW)\n for (const g of gone) this.seen.delete(g)\n }\n return false\n }\n\n /**\n * ์ฒ˜์Œ ๋ณด๋Š” ๊ฒƒ๋งŒ ๋Œ๋ ค์ค€๋‹ค โ€” ๊ทธ๋ฆฌ๊ณ  ๋ช‡ ๊ฐœ๋ฅผ ๋ฒ„๋ ธ๋Š”์ง€ ํ•จ๊ป˜ ๋‚ธ๋‹ค.\n *\n * ๋ฒ„๋ฆฐ ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋‚ด๋Š” ์ด์œ : ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋ฒ„๋ฆฌ๋ฉด ใ€Œ๋ณด๋‚ธ ์ˆ˜ใ€์™€ ใ€Œ๋ฐ˜์˜๋œ ์ˆ˜ใ€๊ฐ€ ์–ด๊ธ‹๋‚˜๋Š”๋ฐ ์•„๋ฌด๋„ ๊ทธ\n * ์ด์œ ๋ฅผ ๋ชจ๋ฅธ๋‹ค. ๊ทธ ์ˆ˜๊ฐ€ ํฌ๋ฉด ๋ณด๋‚ด๋Š” ์ชฝ์ด ๋˜ํ’€์ด ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ , ๊ทธ๊ฒƒ์€ ๊ณ ์น  ์ผ์ด๋‹ค.\n */\n filter<T>(envelopes: readonly T[]): { fresh: T[]; duplicates: number } {\n const fresh: T[] = []\n let duplicates = 0\n for (const e of envelopes) {\n const id = factIdentity(e)\n if (id === undefined) {\n fresh.push(e)\n continue\n }\n if (this.known(id)) duplicates++\n else fresh.push(e)\n }\n return { fresh, duplicates }\n }\n\n /** ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋Š” ์ •์ฒด์˜ ์ˆ˜ โ€” ๊ณ„๊ธฐ๊ฐ€ ์ฝ๋Š”๋‹ค. */\n size(): number {\n return this.seen.size\n }\n}\n"]}
@@ -12,7 +12,7 @@ export interface IngestWindow {
12
12
  * ๋งคํ•‘์€ ํ†ต๊ณผํ–ˆ์ง€๋งŒ **ํŠธ์œˆ์— ๋‹ฟ์ง€ ๋ชปํ•œ** ์ˆ˜ โ€” ์ฒ˜๋ฐฉ์€ ํŠธ์œˆ์„ ์„ธ์šฐ๋Š” ๊ฒƒ์ด๋‹ค.
13
13
  *
14
14
  * โ”€โ”€ ์™œ ๊ฑฐ๋ถ€์™€ ๋”ฐ๋กœ ์„ธ๋‚˜ (2026-08-20์— ๊ฒช์—ˆ๋‹ค) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
15
- * ํŠธ์œˆ์ด ๋ผ์ด๋ธŒ๋กœ ๋Œ์ง€ ์•Š์œผ๋ฉด ์ปค๋„์ด ๋ ˆ์ฝ”๋“œ๋ฅผ **์กฐ์šฉํžˆ ๋ฒ„๋ฆฐ๋‹ค**. ๊ทธ๋Ÿฐ๋ฐ ์žฅ๋ถ€๋Š” ๊ทธ๊ฒƒ์„ ใ€Œํ†ต๊ณผใ€๋กœ ์…Œ๋‹ค.
15
+ * ํŠธ์œˆ์ด ๋ผ์ด๋ธŒ๋กœ ๋Œ์ง€ ์•Š์œผ๋ฉด ์ปค๋„์ด ๋ ˆ์ฝ”๋“œ๋ฅผ **์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋ฒ„๋ฆฐ๋‹ค**. ๊ทธ๋Ÿฐ๋ฐ ์žฅ๋ถ€๋Š” ๊ทธ๊ฒƒ์„ ใ€Œํ†ต๊ณผใ€๋กœ ์…Œ๋‹ค.
16
16
  * ํ™”๋ฉด์ด ใ€Œ150 ๋“ค์–ด์˜ด ยท 150 ํ†ต๊ณผ ยท 100%ใ€๋ผ๊ณ  ๋งํ•˜๋Š” ๋™์•ˆ 150๊ฑด์€ ๋ฐ”๋‹ฅ์— ๋ฒ„๋ ค์ง€๊ณ  ์žˆ์—ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์ด
17
17
  * ๋ง‰์œผ๋ ค๋˜ ๋ฐ”๋กœ ๊ทธ๊ฒƒ์„ ์ด ๊ธฐ๋Šฅ์ด ์ €์ง€๋ฅธ ์…ˆ์ด๋‹ค.
18
18
  *
@@ -72,6 +72,26 @@ export interface IngestLedger {
72
72
  */
73
73
  lastUndeliveredAtMs: number;
74
74
  /** ์‚ฌ์œ ๋ณ„ ๋ˆ„์  ๊ฑด์ˆ˜์™€ **๋งˆ์ง€๋ง‰์œผ๋กœ ๊ทธ ์‚ฌ์œ ๊ฐ€ ๋‚œ ์‹œ๊ฐ** โ€” ๊ณ ์นœ ์‚ฌ์œ ๋Š” ์‹œ๊ฐ์ด ๋ฉˆ์ถ˜๋‹ค. */
75
+ /**
76
+ * **์–ด๋–ค ๊ธธ๋กœ ๋“ค์–ด์™”๋‚˜** โ€” ๊ฒฝ๋กœ๋งˆ๋‹ค ๊ฑด์ˆ˜์™€ ๋งˆ์ง€๋ง‰ ์‹œ๊ฐ.
77
+ *
78
+ * โ”€โ”€ ์™œ ํ•„์š”ํ•œ๊ฐ€ (2026-08-26) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
79
+ * ํŠธ์œˆ์ด ๊ฐ’์„ ๋ฐ›๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๊ณ„๊ธฐ๊ฐ€ ๋งํ•ด ์ฃผ๋Š”๋ฐ, **๋ฌด์—‡์„ ํ†ตํ•ด ๋ฐ›๋Š”์ง€๋Š” ์•„๋ฌด๋„ ๋งํ•˜์ง€ ์•Š์•˜๋‹ค.**
80
+ * ์ปค๋„ฅํ„ฐ๊ฐ€ ๋ฌผ์–ด์„œ ๋ฐ›๋Š”์ง€, ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ์ด ๋ฐ€์–ด ์ฃผ๋Š”์ง€, ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ๋„ฃ๋Š”์ง€, ๋ถ€ํ•˜ ๋„๊ตฌ๊ฐ€ ๋„ฃ๋Š”์ง€ โ€”
81
+ * ํ™”๋ฉด์—์„œ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค. ๊ทธ ๊ตฌ๋ณ„์ด ์—†์œผ๋ฉด ใ€Œํด๋ง์„ ์›นํ›…์œผ๋กœ ๋ฐ”๊ฟจ๋‹คใ€๋ฅผ ํ™•์ธํ•  ๋ฐฉ๋ฒ•๋„ ์—†๋‹ค.
82
+ */
83
+ bySource: Record<string, {
84
+ count: number;
85
+ lastAtMs: number;
86
+ }>;
87
+ /**
88
+ * **๊ฐ™์€ ์‚ฌ์‹ค์ด ๋‘ ๋ฒˆ ์™€์„œ ๋ฒ„๋ฆฐ ์ˆ˜** โ€” ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋ฒ„๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.
89
+ *
90
+ * ์ด ์ˆ˜๊ฐ€ ํฌ๋ฉด ๋ณด๋‚ด๋Š” ์ชฝ์ด ๋˜ํ’€์ด ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ , ๊ทธ๊ฒƒ์€ ๊ณ ์น  ์ผ์ด๋‹ค(ํƒœ์–‘๊ด‘ ์ปค๋„ฅํ„ฐ๊ฐ€ ํ•œ ์ฃผ๊ธฐ์—
91
+ * 76๊ฑด์„ ๋˜ํ’€์ด ๋ณด๋‚ด๋˜ ๊ฒƒ์„ ์ด ์ˆ˜๋กœ ๋ณผ ์ˆ˜ ์žˆ์—ˆ์–ด์•ผ ํ–ˆ๋‹ค).
92
+ */
93
+ duplicates: number;
94
+ lastDuplicateAtMs: number;
75
95
  byReason: Record<string, {
76
96
  count: number;
77
97
  lastAtMs: number;
@@ -79,8 +99,8 @@ export interface IngestLedger {
79
99
  /**
80
100
  * ์‚ฌ์œ  ์ข…๋ฅ˜๊ฐ€ ์ƒํ•œ์— ๋‹ฟ์•˜๋‚˜.
81
101
  *
82
- * **์ ‘ํžŒ ์ข…๋ฅ˜ ์ˆ˜๋Š” ์„ธ์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ทธ๊ฒƒ์„ ์„ธ๋ ค๋ฉด ์ด๋ฏธ ๋ณธ ์‚ฌ์œ ๋ฅผ ๋ชจ๋‘ ๊ธฐ์–ตํ•ด์•ผ ํ•˜๊ณ , ๊ทธ ์ง‘ํ•ฉ์ด
83
- * ๋ฐ”๋กœ ์ด ์ƒํ•œ์œผ๋กœ ๋ง‰์œผ๋ ค๋˜ ๋ฌดํ•œํ•œ ์ง‘ํ•ฉ์ด๋‹ค. ์ ‘ํžŒ **๊ฑด์ˆ˜**๋Š” `byReason[OTHER_REASON].count` ๊ฐ€ ๋‹ตํ•œ๋‹ค.
102
+ * **๋ชจ์€ ์ข…๋ฅ˜ ์ˆ˜๋Š” ์„ธ์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ทธ๊ฒƒ์„ ์„ธ๋ ค๋ฉด ์ด๋ฏธ ๋ณธ ์‚ฌ์œ ๋ฅผ ๋ชจ๋‘ ๊ธฐ์–ตํ•ด์•ผ ํ•˜๊ณ , ๊ทธ ์ง‘ํ•ฉ์ด
103
+ * ๋ฐ”๋กœ ์ด ์ƒํ•œ์œผ๋กœ ๋ง‰์œผ๋ ค๋˜ ๋ฌดํ•œํ•œ ์ง‘ํ•ฉ์ด๋‹ค. ๋ชจ์€ **๊ฑด์ˆ˜**๋Š” `byReason[OTHER_REASON].count` ๊ฐ€ ๋‹ตํ•œ๋‹ค.
84
104
  */
85
105
  reasonsCapped: boolean;
86
106
  /** ํ‘œ๋ณธ์„ ์ด๋ฏธ ๋œฌ ์‚ฌ์œ ๋“ค โ€” ๊ฐ™์€ ์‚ฌ์œ ๋ฅผ ๋‹ค์‹œ ์ง๋ ฌํ™”ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•œ ์ƒ‰์ธ(O(1) ์กฐํšŒ). */
@@ -94,12 +114,12 @@ export interface IngestLedger {
94
114
  /**
95
115
  * **์›๋ณธ์— ๋‹ฟ์ง€ ๋ชปํ•œ ์‚ฌ์‹ค** (2026-08-23) โ€” ใ€Œ๋ฐ›์€ ๊ฒƒ์ด ์—†๋‹คใ€์™€ **๋‹ค๋ฅธ ์‚ฌ์‹ค**์ด๋‹ค.
96
116
  *
97
- * โ”€โ”€ ๋ฌด์—‡์ด ์กฐ์šฉํ–ˆ๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
117
+ * โ”€โ”€ ๋ฌด์—‡์ด ์•„๋ฌด ์‹ ํ˜ธ๋„ ๋‚ด์ง€ ์•Š์•˜๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
98
118
  * ์‹ค ์›๋ณธ์ด ๋Š๊ฒผ์„ ๋•Œ(์ ‘์† ์‹œ๊ฐ„ ์ดˆ๊ณผ) ํŠธ์œˆ์˜ **์กฐํšŒ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ ์–ด๋””์—๋„** ๊ทธ ์‚ฌ์‹ค์ด ์—†์—ˆ๋‹ค.
99
119
  * `recordIngest` ๋Š” `onRecords` ๊ฐ€ ๋ถˆ๋ฆด ๋•Œ๋งŒ ๋„๋‹ฌํ•˜๊ณ , ์ฝ๊ธฐ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ๊ทธ ๋ฌธ์— ์˜ค์ง€ ์•Š๋Š”๋‹ค.
100
120
  * `TwinReference.lastError` ๋Š” ๋งˆ์Šคํ„ฐ ๋™๊ธฐยท์ ‘์† ์‹œํ—˜์—๋งŒ ์ ํžŒ๋‹ค.
101
121
  *
102
- * ๊ทธ๋ž˜์„œ ํ™”๋ฉด์ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ใ€Œ์ƒˆ ์‚ฌ์‹ค์ด ์—†๋‹คใ€๋ฟ์ด์—ˆ๊ณ , ๊ทธ๊ฒƒ์€ **ใ€Œ์›๋ณธ์ด ์กฐ์šฉํ•˜๋‹คใ€์™€ ๊ตฌ๋ณ„๋˜์ง€
122
+ * ๊ทธ๋ž˜์„œ ํ™”๋ฉด์ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ใ€Œ์ƒˆ ์‚ฌ์‹ค์ด ์—†๋‹คใ€๋ฟ์ด์—ˆ๊ณ , ๊ทธ๊ฒƒ์€ **ใ€Œ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ์—์„œ ๋“ค์–ด์˜จ ๊ฒƒ์ด ์—†๋‹คใ€์™€ ๊ตฌ๋ณ„๋˜์ง€
103
123
  * ์•Š๋Š”๋‹ค.** ์‹ค์ฆ ๋ฐ๋ชจ ์ค‘์— ์›๋ณธ์ด ๋Š๊ธฐ๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์›์ธ์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค.
104
124
  *
105
125
  * โ”€โ”€ ์™œ ใ€Œ๋ช‡ ๋ฒˆใ€๊ณผ ใ€Œ์–ธ์ œ๋ถ€ํ„ฐใ€๋ฅผ ํ•จ๊ป˜ ๋‘๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@@ -108,6 +128,17 @@ export interface IngestLedger {
108
128
  *
109
129
  * ์„ฑ๊ณตํ•˜๋ฉด ์ง€์šด๋‹ค โ€” ๊ณ ์ณ์ง„ ๋‹จ์ ˆ์ด ํ™”๋ฉด์— ๋‚จ์•„ ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ๋„ ๊ฑฐ์ง“์ด๋‹ค.
110
130
  */
131
+ /**
132
+ * ๋งˆ์ง€๋ง‰์œผ๋กœ ๋Š๊ฒผ๋‹ค๊ฐ€ ๋Œ์•„์˜จ ๊ฒƒ โ€” ์—†์œผ๋ฉด ๋Š๊ธด ์ ์ด ์—†๊ฑฐ๋‚˜ ์•„์ง ๋Œ์•„์˜ค์ง€ ์•Š์€ ๊ฒƒ์ด๋‹ค.
133
+ *
134
+ * ์‹คํŒจ ๊ธฐ๋ก(`readFailure`)์€ ๋Œ์•„์˜ค๋ฉด ์ง€์›Œ์ง„๋‹ค. ๊ทธ๊ฒƒ๋งŒ ์ง€์šฐ๋ฉด ใ€Œ๋Š๊ธด ์ ์ด ์žˆ์—ˆ๋‹คใ€๊ฐ€ ํ™”๋ฉด์—์„œ
135
+ * ์‚ฌ๋ผ์ง€๋ฏ€๋กœ, ๋Œ์•„์˜จ ์‚ฌ์‹ค์„ ๋”ฐ๋กœ ๋‚จ๊ธด๋‹ค.
136
+ */
137
+ lastRecovery?: {
138
+ atMs: number;
139
+ afterFailures: number;
140
+ downMs: number;
141
+ };
111
142
  readFailure?: {
112
143
  /** ์—ฐ์† ์‹คํŒจ ์ˆ˜ โ€” ์„ฑ๊ณต ํ•œ ๋ฒˆ์— 0 ์œผ๋กœ ๋Œ์•„๊ฐ„๋‹ค. */
113
144
  consecutive: number;
@@ -119,6 +150,8 @@ export interface IngestLedger {
119
150
  reason: string;
120
151
  /** ์–ด๋А ํ๋ฆ„์—์„œ ๋‚ฌ๋‚˜(์–ด๋Œ‘ํ„ฐ๊ฐ€ ๋งํ•ด ์ฃผ๋ฉด). ์›๋ณธ๋งˆ๋‹ค ํ๋ฆ„์ด ๋‹ค๋ฅด๋ฏ€๋กœ ์—ด๋ ค ์žˆ๋‹ค. */
121
152
  stream?: string;
153
+ /** ๋‹ค์Œ์— ๋‹ค์‹œ ๋ฌผ์„ ๋•Œ๊นŒ์ง€ ๋‚จ์€ ์‹œ๊ฐ„(ms) โ€” ์ปค๋„ฅํ„ฐ๊ฐ€ ๋ฌผ๋Ÿฌ์„ฐ์„ ๋•Œ๋งŒ ์žˆ๋‹ค. */
154
+ nextRetryMs?: number;
122
155
  };
123
156
  /**
124
157
  * **์ฝ์—ˆ๋Š”๋ฐ ์ฐฝ์„ ๋„˜๊ธธ ์ˆ˜ ์—†๋‹ค** (2026-08-24) โ€” ์œ„์™€ **๋‹ค๋ฅธ ์‚ฌ์‹ค**์ด๋‹ค.
@@ -152,7 +185,7 @@ export interface IngestLedger {
152
185
  * `unhandled` ๋ฆฌ๋“€์„œ๊ฐ€ **๋ฐ›์•˜๋Š”๋ฐ** ๋‹ด์„ ์ž๋ฆฌ๋ฅผ ๋ชฐ๋ž๋‹ค
153
186
  * ์—ฌ๊ธฐ ์ปค๋„ฅํ„ฐ๊ฐ€ **๋ณด์ง€๋งŒ ์ผ๋ถ€๋Ÿฌ ๋ณด๋‚ด์ง€ ์•Š์•˜๋‹ค** โ€” ์ด์œ ์™€ ํ•จ๊ป˜
154
187
  *
155
- * ๋‘˜ ๋‹ค ใ€Œ์‚ฌ์‹ค์ด ์กฐ์šฉํžˆ ์‚ฌ๋ผ์ง€์ง€ ์•Š๊ฒŒใ€ ์„ธ๋Š” ๊ฒƒ์ด๊ณ , ์ด์œ ๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ ์ž๋ฆฌ๋„ ๋‹ค๋ฅด๋‹ค.
188
+ * ๋‘˜ ๋‹ค ใ€Œ์‚ฌ์‹ค์ด ์˜ค๋ฅ˜ ์—†์ด ์‚ฌ๋ผ์ง€์ง€ ์•Š๊ฒŒใ€ ์„ธ๋Š” ๊ฒƒ์ด๊ณ , ์ด์œ ๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ ์ž๋ฆฌ๋„ ๋‹ค๋ฅด๋‹ค.
156
189
  *
157
190
  * ์ด์œ ๋ฅผ **๋ฌธ์ž์—ด๋กœ ๋ฐ›๋Š”๋‹ค**: ๋ฌด์—‡์„ ์™œ ์•ˆ ๋ฐ›๋Š”์ง€๋Š” ์›๋ณธ๋งˆ๋‹ค ๋‹ค๋ฅด๊ณ , ๊ณ„์•ฝ์ด ๊ทธ ๋ชฉ๋ก์„ ๋‹ซ์œผ๋ฉด ์ƒˆ ์›๋ณธ์„
158
191
  * ๋ถ™์ผ ๋•Œ๋งˆ๋‹ค ๊ณ„์•ฝ์„ ๊ณ ์น˜๊ฒŒ ๋œ๋‹ค(ํ๋ฆ„ ์—ด์‡ ์™€ ๊ฐ™์€ ๊ทœ์œจ).
@@ -181,12 +214,30 @@ export interface IngestLedger {
181
214
  * ์—ฐ์† ์‹คํŒจ์˜ ์‹œ์ž‘ ์‹œ๊ฐ์„ ์ง€ํ‚ค๋Š” ๊ฒƒ์ด ์ด ํ•จ์ˆ˜์˜ ์š”์ ์ด๋‹ค: ๋งค๋ฒˆ ์ƒˆ๋กœ ์ ์œผ๋ฉด ใ€Œ20๋ถ„์งธ ๋ชป ์ฝ๋Š”๋‹คใ€๋ฅผ
182
215
  * ๋งํ•  ์ˆ˜ ์—†๊ณ , ํ™”๋ฉด์€ ๋Š˜ ใ€Œ๋ฐฉ๊ธˆ ์‹คํŒจํ–ˆ๋‹คใ€๋งŒ ๋ณด๊ฒŒ ๋œ๋‹ค.
183
216
  */
184
- export declare function recordReadFailure(ledger: IngestLedger, reason: string, nowMs: number, stream?: string): void;
217
+ export declare function recordReadFailure(ledger: IngestLedger, reason: string, nowMs: number, stream?: string,
218
+ /**
219
+ * ๋‹ค์Œ์— ๋‹ค์‹œ ๋ฌผ์„ ๋•Œ๊นŒ์ง€ ๋‚จ์€ ์‹œ๊ฐ„(ms) โ€” ์ปค๋„ฅํ„ฐ๊ฐ€ ๋ฌผ๋Ÿฌ์„ฐ์œผ๋ฉด ๊ทธ ๊ฐ’์„ ์ค€๋‹ค (2026-08-27).
220
+ *
221
+ * ์ด๊ฒƒ์ด ์—†์œผ๋ฉด ํ™”๋ฉด์ด ใ€Œ๋‹ฟ์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋‹คใ€๊นŒ์ง€๋งŒ ๋งํ•˜๊ณ , ์‚ฌ๋žŒ์€ **์–ธ์ œ ๋‹ค์‹œ ์‹œ๋„ํ•˜๋Š”์ง€** ์•Œ ์ˆ˜
222
+ * ์—†๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๋Š”์ง€ ์†์„ ์จ์•ผ ํ•˜๋Š”์ง€ ํŒ๋‹จํ•˜์ง€ ๋ชปํ•œ๋‹ค.
223
+ *
224
+ * **์—ฐ๋‹ฌ์•„ ํšŸ์ˆ˜์™€ ์‹œ์ž‘ ์‹œ๊ฐ์€ ์ปค๋„ฅํ„ฐ๊ฐ€ ๋ณด๋‚ด์ง€ ์•Š๋Š”๋‹ค** โ€” ์ด ํ•จ์ˆ˜๊ฐ€ ์ด๋ฏธ ์„ผ๋‹ค. ๋‘ ๊ณณ์—์„œ ์„ธ๋ฉด
225
+ * ๊ฐˆ๋ผ์ง€๊ณ , ๊ฐˆ๋ผ์ง€๋ฉด ์–ด๋А ์ชฝ์ด ์‚ฌ์‹ค์ธ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.
226
+ */
227
+ nextRetryMs?: number): void;
228
+ /**
229
+ * **๋Š๊ฒผ๋‹ค๊ฐ€ ๋Œ์•„์™”๋‹ค** โ€” ๊ทธ ์‚ฌ์‹ค์„ ๋‚จ๊ธด๋‹ค (2026-08-27).
230
+ *
231
+ * ์‹คํŒจ ๊ธฐ๋ก๋งŒ ์ง€์šฐ๋ฉด ใ€Œ๋Š๊ธด ์ ์ด ์žˆ์—ˆ๋‹คใ€๊ฐ€ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง„๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ฐค์ƒˆ ๋‘ ์‹œ๊ฐ„ ๋Š๊ฒผ๋˜ ์—ฐ๊ฒฐ๊ณผ ํ•œ
232
+ * ๋ฒˆ๋„ ๋Š๊ธฐ์ง€ ์•Š์€ ์—ฐ๊ฒฐ์ด ์•„์นจ์— ๋˜‘๊ฐ™์ด ๋ณด์ธ๋‹ค. ๋ช‡ ๋ฒˆ ์‹คํŒจํ•œ ๋’ค์— ๋Œ์•„์™”๋Š”์ง€, ์–ผ๋งˆ๋‚˜ ๋Š๊ฒผ๋Š”์ง€๋ฅผ ํ•จ๊ป˜
233
+ * ๋‚จ๊ธด๋‹ค.
234
+ */
235
+ export declare function recordRecovered(ledger: IngestLedger, afterFailures: number, downMs: number, nowMs: number): void;
185
236
  /**
186
237
  * ์ฝ๊ธฐ๊ฐ€ ์„ฑ๊ณตํ–ˆ๋‹ค โ€” ๋‹จ์ ˆ ๊ธฐ๋ก์„ ์ง€์šด๋‹ค.
187
238
  *
188
239
  * **๋นˆ ์ฝ๊ธฐ๋„ ์„ฑ๊ณต์ด๋‹ค**: ์›๋ณธ์ด ใ€Œ์ƒˆ ๊ฒƒ์ด ์—†๋‹คใ€๊ณ  ๋‹ตํ•œ ๊ฒƒ์€ ๋‹ฟ์•˜๋‹ค๋Š” ๋œป์ด๋‹ค. ๊ทธ ๋‘˜์„ ๊ฐ™๊ฒŒ ๋‘๋ฉด
189
- * ์กฐ์šฉํ•œ ์›๋ณธ์ด ๋Š๊ธด ์›๋ณธ์œผ๋กœ ๋ณด์ธ๋‹ค(๊ณ ์น˜๋ ค๋˜ ๊ฒƒ์˜ ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์œผ๋กœ ํ‹€๋ฆฐ๋‹ค).
240
+ * ๋“ค์–ด์˜จ ๊ฒƒ์ด ์—†๋Š” ์—ฐ๊ฒฐ์ด ๋Š๊ธด ์›๋ณธ์œผ๋กœ ๋ณด์ธ๋‹ค(๊ณ ์น˜๋ ค๋˜ ๊ฒƒ์˜ ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์œผ๋กœ ํ‹€๋ฆฐ๋‹ค).
190
241
  */
191
242
  export declare function clearReadFailure(ledger: IngestLedger): void;
192
243
  /**
@@ -206,6 +257,15 @@ export declare function recordCursorStall(ledger: IngestLedger, reason: string,
206
257
  * ์ด์œ ๊ฐ€ ๊ฐ™๊ณ  ์ˆ˜๊ฐ€ ๋‹ฌ๋ผ์ง€๋ฉด **๋งˆ์ง€๋ง‰ ์ˆ˜๋กœ ๋ฎ๋Š”๋‹ค**: ์ด๊ฒƒ์€ ๋ˆ„์  ์‚ฌ๊ฑด์ด ์•„๋‹ˆ๋ผ **์ง€๊ธˆ ์„ธ์šฐ์ง€ ์•Š์€ ๊ฒƒ์˜
207
258
  * ์ˆ˜**๋‹ค. ์ฃผ๊ธฐ๋งˆ๋‹ค 8๊ฑด์ด๋ฉด 8์ด๊ณ , ๋”ํ•ด์„œ 800์ด ๋˜๋ฉด ๊ฑฐ์ง“์ด๋‹ค.
208
259
  */
260
+ /**
261
+ * ์–ด๋–ค ๊ธธ๋กœ ๋ช‡ ๊ฑด์ด ๋“ค์–ด์™”๋‚˜ โ€” ๊ฒฝ๋กœ ์ด๋ฆ„์€ ๋ถ€๋ฅด๋Š” ์ชฝ์ด ์ •ํ•œ๋‹ค.
262
+ *
263
+ * ์ด๋ฆ„์„ ์ž์œ  ๋ฌธ์ž์—ด๋กœ ๋‘๋Š” ์ด์œ : ๊ธธ์ด ๋Š˜์–ด๋‚œ๋‹ค(์ง€๊ธˆ์€ ๋ฌผ์–ด๋ณด๊ธฐยท์‹œ๋‚˜๋ฆฌ์˜คยท๋ถ€ํ•˜ ๋„๊ตฌ, ๋‹ค์Œ์€ ์›นํ›…).
264
+ * ์—ด๊ฑฐ๋กœ ๋ชป ๋ฐ•์œผ๋ฉด ์ƒˆ ๊ธธ์ด ์ƒ๊ธธ ๋•Œ ์ด ํŒŒ์ผ์„ ํ•จ๊ป˜ ๊ณ ์ณ์•ผ ํ•˜๊ณ , ์žŠ์œผ๋ฉด ๊ทธ ๊ธธ์ด ํ†ต๊ณ„์—์„œ ์‚ฌ๋ผ์ง„๋‹ค.
265
+ */
266
+ export declare function recordIngestSource(ledger: IngestLedger, source: string, count: number, nowMs: number): void;
267
+ /** ๊ฐ™์€ ์‚ฌ์‹ค์ด ๋‘ ๋ฒˆ ์™€์„œ ๋ฒ„๋ฆฐ ์ˆ˜ โ€” ์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ๋ฒ„๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. */
268
+ export declare function recordDuplicates(ledger: IngestLedger, count: number, nowMs: number): void;
209
269
  export declare function recordWithheld(ledger: IngestLedger, reason: string, count: number, nowMs: number): void;
210
270
  /** ์ฐฝ์„ ๋„˜๊ฒผ์œผ๋ฉด ์ง€์šด๋‹ค โ€” ํ’€๋ฆฐ ์ •์ฒด๊ฐ€ ํ™”๋ฉด์— ๋‚จ์•„ ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ๋„ ๊ฑฐ์ง“์ด๋‹ค. */
211
271
  export declare function clearCursorStall(ledger: IngestLedger): void;
@@ -227,7 +287,7 @@ export declare const TREND_LIMIT = 36;
227
287
  * (`unknown bizStep "PUTAWAY_X17"`, `โ€ฆX18`, โ€ฆ) ํ‚ค๊ฐ€ ๋ฌดํ•œํžˆ ๋Š˜์–ด๋‚œ๋‹ค. ์ดˆ๋‹น 1๋งŒ ๊ฑด ๊ทœ๋ชจ์—์„œ ์ด๊ฒƒ์€
228
288
  * ๋ฏธ๋ฏธํ•œ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ˆ„์ˆ˜๋‹ค.
229
289
  *
230
- * ๋„˜์น˜๋ฉด `OTHER_REASON` ํ•œ ์นธ์— ๋ชจ์œผ๊ณ  **๋ช‡ ์ข…์„ ์ ‘์—ˆ๋Š”์ง€ ํ•จ๊ป˜ ๋‚ธ๋‹ค**(์กฐ์šฉํžˆ ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค).
290
+ * ๋„˜์น˜๋ฉด `OTHER_REASON` ํ•œ ์นธ์— ๋ชจ์œผ๊ณ  **๋ช‡ ์ข…์„ ๋ชจ์•˜๋Š”์ง€ ํ•จ๊ป˜ ๋‚ธ๋‹ค**(์•Œ๋ฆฌ์ง€ ์•Š๊ณ  ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค).
231
291
  * 30์ข…์ด๋ฉด ๊ณ ์น  ๊ณณ์„ ์ฐพ๊ธฐ์— ์ถฉ๋ถ„ํ•˜๋‹ค โ€” ๋ชฉ๋ก์„ ํ›‘๋Š” ์ผ์ด ์•„๋‹ˆ๋ผ ๋งคํ•‘ ๋ช‡ ์ค„์„ ๊ณ ์น˜๋Š” ์ผ์ด๋‹ค.
232
292
  */
233
293
  export declare const REASON_LIMIT = 30;
@@ -326,6 +386,13 @@ export declare function syncVerdictOf(args: {
326
386
  nowMs?: number;
327
387
  /** ๋งˆ์ง€๋ง‰์œผ๋กœ **๋ฒ„๋ ค์ง„** ์‹œ๊ฐ. ํ•œ ๋ฒˆ๋„ ์—†์œผ๋ฉด `-1`. */
328
388
  lastUndeliveredAtMs?: number;
389
+ /**
390
+ * ์ง€๊ธˆ๊นŒ์ง€ ์ œ์‹œ๋œ ๋ˆ„์  ์ˆ˜ โ€” **ใ€Œ๋ฐ›๊ณ  ์žˆ๋Š” ์ค‘ใ€๊ณผ ใ€Œ์˜ค๋Š” ๊ฒƒ์ด ์—†๋‹คใ€๋ฅผ ๊ฐ€๋ฅด๋Š” ์‚ฌ์‹ค**์ด๋‹ค.
391
+ *
392
+ * ๋‹ฟ์€ ์‹œ๊ฐ(`lastAtMs`)์œผ๋กœ๋Š” ๊ฐ€๋ฅผ ์ˆ˜ ์—†๋‹ค: ๋นˆ ์ฝ๊ธฐ๋„ ๋‹ฟ์€ ๊ฒƒ์ด๋ฏ€๋กœ ๊ทธ ์‹œ๊ฐ์ด ์„ ๋‹ค. ์ฐฝ์ด ์•„์ง ๋‹ซํžˆ์ง€
393
+ * ์•Š์•˜์„ ๋•Œ ์ด ์ˆ˜๊ฐ€ 0 ์ด๋ฉด ์˜ค๋Š” ๊ฒƒ์ด ์—†๋Š” ๊ฒƒ์ด๊ณ , 0 ์ด ์•„๋‹ˆ๋ฉด ๋ฐ›๊ณ  ์žˆ๋Š” ์ค‘์ด๋‹ค.
394
+ */
395
+ offeredTotal?: number;
329
396
  threshold?: number;
330
397
  }): SyncVerdict;
331
398
  export interface IngestWindowView {
@@ -385,7 +452,7 @@ export interface IngestHealthView {
385
452
  *
386
453
  * ์ปค์„œ ์ •์ฒด(`cursorStall`)์™€ **์„ž์ด์ง€ ์•Š๋Š”๋‹ค**: ์ด์ชฝ์€ ๊ธฐ๋‹ค๋ฆฌ๋ฉด ํ’€๋ฆฌ๊ณ  ๊ทธ์ชฝ์€ ๊ธฐ๋‹ค๋ ค๋„ ์•ˆ ํ’€๋ฆฐ๋‹ค.
387
454
  *
388
- * ใ€Œ์œ ์ž… ์—†์Œใ€๊ณผ **๋‹ค๋ฅธ ํŒ์ •**์ด๋‹ค: ์œ ์ž… ์—†์Œ์€ ์›๋ณธ์ด ์กฐ์šฉํ•œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ๊ณ , ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ๋ฌป์ง€๋„
455
+ * ใ€Œ์œ ์ž… ์—†์Œใ€๊ณผ **๋‹ค๋ฅธ ํŒ์ •**์ด๋‹ค: ์œ ์ž… ์—†์Œ์€ ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ์—์„œ ๋“ค์–ด์˜จ ๊ฒƒ์ด ์—†๋Š” ๊ฒƒ์ผ ์ˆ˜ ์žˆ๊ณ , ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ๋ฌป์ง€๋„
389
456
  * ๋ชปํ•œ ๊ฒƒ์ด๋‹ค. ํ™”๋ฉด์€ ๋‘ ๋ฌธ์žฅ์„ ๋‹ค๋ฅด๊ฒŒ ๋งํ•ด์•ผ ํ•œ๋‹ค โ€” ์‹ค ์›๋ณธ์ด ๋Š๊ฒผ์„ ๋•Œ ์‚ฌ์šฉ์ž๊ฐ€ ์›์ธ์„ ์ฐพ์„ ์ˆ˜
390
457
  * ์žˆ๋Š”์ง€๊ฐ€ ๊ทธ ์ฐจ์ด๋‹ค.
391
458
  */
@@ -396,6 +463,19 @@ export interface IngestHealthView {
396
463
  lastAt: string;
397
464
  reason: string;
398
465
  stream?: string;
466
+ /** ๋‹ค์Œ์— ๋‹ค์‹œ ๋ฌผ์„ ๋•Œ๊นŒ์ง€ ๋‚จ์€ ์‹œ๊ฐ„(ms) โ€” ์ปค๋„ฅํ„ฐ๊ฐ€ ๋ฌผ๋Ÿฌ์„ฐ์„ ๋•Œ๋งŒ ์žˆ๋‹ค. */
467
+ nextRetryMs?: number;
468
+ };
469
+ /**
470
+ * ๋งˆ์ง€๋ง‰์œผ๋กœ ๋Š๊ฒผ๋‹ค๊ฐ€ ๋Œ์•„์˜จ ๊ฒƒ โ€” ์—†์œผ๋ฉด ๋Š๊ธด ์ ์ด ์—†๊ฑฐ๋‚˜ ์•„์ง ๋Œ์•„์˜ค์ง€ ์•Š์€ ๊ฒƒ์ด๋‹ค (2026-08-27).
471
+ *
472
+ * `readFailure` ๋Š” ๋Œ์•„์˜ค๋ฉด ์‚ฌ๋ผ์ง„๋‹ค. ์ด ์นธ์ด ์—†์œผ๋ฉด ๋ฐค์ƒˆ ๋Š๊ฒผ๋˜ ์—ฐ๊ฒฐ๊ณผ ํ•œ ๋ฒˆ๋„ ๋Š๊ธฐ์ง€ ์•Š์€ ์—ฐ๊ฒฐ์ด
473
+ * ์•„์นจ์— ๋˜‘๊ฐ™์ด ๋ณด์ธ๋‹ค.
474
+ */
475
+ lastRecovery?: {
476
+ at: string;
477
+ afterFailures: number;
478
+ downMs: number;
399
479
  };
400
480
  }
401
481
  /**