@things-factory/headless-twin 10.0.14 → 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 +137 -8
  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 +124 -9
  17. package/dist-server/engine/ingest-health.js +169 -15
  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 +243 -53
  78. package/dist-server/engine/twin-engine.js +690 -191
  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 +140 -8
  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 +88 -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 +22 -2
  152. package/dist-server/service/twin-event/twin-event-keys.js +37 -5
  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 +36 -1
  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 +15 -2
  196. package/dist-server/service/twin-model/isa95-coverage.js +32 -8
  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 +117 -28
  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 +170 -13
  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 +234 -20
  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 +764 -201
  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 +166 -9
  325. package/server/service/reference/reference-hook.ts +145 -0
  326. package/server/service/reference/reference-live.ts +92 -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 +37 -5
  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 +36 -1
  352. package/server/service/twin-model/iec61850-coverage.ts +1 -1
  353. package/server/service/twin-model/isa95-coverage.ts +45 -8
  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 +117 -28
  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 +43 -1
  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 +49 -3
  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 +95 -0
  476. package/test/yield-loop.test.ts +4 -4
  477. package/tsconfig.shared.tsbuildinfo +1 -1
  478. package/tsconfig.tsbuildinfo +1 -1
@@ -14,9 +14,9 @@ export interface AttentionDigestResult {
14
14
  /** 전첎 개수 — 레음의 "N걎 더" 가 읎 값에서 나옚닀(자륞 사싀을 밝힌닀). */
15
15
  attentionTotal: number;
16
16
  /**
17
- * 자늬별 최고 심각도 — **전량을 귌거로** 접는닀.
17
+ * 자늬별 최고 심각도 — **전량을 귌거로** 계산한닀.
18
18
  *
19
- * 상위 N 만윌로 접윌멎 20위 밖의 신혞륌 가진 자늬가 색을 잃는닀. 귞것읎 읎 요앜의 핵심 읎유닀:
19
+ * 상위 N 만윌로 계산하멎 20위 밖의 신혞륌 가진 자늬가 색을 잃는닀. 귞것읎 읎 요앜의 핵심 읎유닀:
20
20
  * 레음은 잘띌도 되지만 **지도 색은 잘띌선 안 된닀.**
21
21
  */
22
22
  severityByLocation: Record<string, string>;
@@ -27,7 +27,7 @@ export declare const compareAttentions: (a: AttentionLike, b: AttentionLike) =>
27
27
  * 신혞륌 요앜한닀.
28
28
  *
29
29
  * `limit` 읎 없거나 0 읎하멎 **자륎지 않는닀** — 자륎는 쪜읎 Ʞ볞읎멎 읎 값을 몚륎는 소비처가
30
- * 조용히 음부만 받는닀(요앜을 도입하닀 만드는 전형적읞 사고닀).
30
+ * 알늬지 않고 음부만 받는닀(요앜을 도입하닀 만드는 전형적읞 사고닀).
31
31
  */
32
32
  export declare function digestAttentions(attentions: readonly AttentionLike[] | undefined | null, limit?: number): AttentionDigestResult;
33
33
  /** 렌슈 하나가 낾 신혞 — 얎느 튞윈에서 왔는지와 핚께. */
@@ -45,7 +45,7 @@ export interface LensAttentions {
45
45
  * 같은 자늬 id 가 렌슈마닀 닀륞 것을 가늬킬 수 있닀.
46
46
  * ② **순서는 렌슈 순서가 아니띌 ꞉한 순서닀** — 앞 렌슈의 낮은 신혞가 ë’€ 렌슈의 심각한 신혞륌
47
47
  * 밀얎낎멎, 상위 N 만 볎는 화멎에서 정작 ꞉한 것읎 안 볎읞닀.
48
- * ③ **자늬 색은 렌슈륌 가로질러 가장 ꞉한 것윌로** 접는닀 — 두 렌슈가 같은 자늬륌 가늬킀멎 ê·ž 자늬는
48
+ * ③ **자늬 색은 렌슈륌 가로질러 가장 ꞉한 것윌로** 계산한닀 — 두 렌슈가 같은 자늬륌 가늬킀멎 ê·ž 자늬는
49
49
  * 하나의 현싀읎므로 더 ꞉한 쪜읎 읎ꞎ닀(둘 쀑 하나륌 임의로 고륎멎 색읎 렌슈 순서에 따띌 달띌진닀).
50
50
  */
51
51
  export declare function mergeLensAttentions(lenses: readonly LensAttentions[], limit?: number): AttentionDigestResult;
@@ -7,12 +7,12 @@
7
7
  * 는 신혞 397걎읎 108KB 띌 5ë°° 감소에 귞쳀닀. 귞런데 화멎읎 ê·ž 397걎윌로 하는 음은 둘뿐읎닀.
8
8
  *
9
9
  * ① 레음에 **20걎**만 볎여죌고 나뚞지는 "N걎 더" 띌고만 말한닀.
10
- * ② 자늬(폎늬곀)륌 칠할 **자늬별 최고 심각도**륌 뜑는닀 — 397걎읎 자늬 7곳의 색 7개로 접힌닀.
10
+ * ② 자늬(폎늬곀)륌 칠할 **자늬별 최고 심각도**륌 뜑는닀 — 397걎읎 자늬 7곳의 색 7개로 쀄얎든닀.
11
11
  *
12
- * 슉 전량을 낎렀볎낎 큎띌읎얞튞가 접는 구조였닀. 접는 것은 값싞므로 **서버가 접얎서 볎낞닀.**
12
+ * 슉 전량을 낎렀볎낎 큎띌읎얞튞가 계산하는 구조였닀. 계산하는 것은 값싞므로 **서버가 계산핎서 볎낞닀.**
13
13
  *
14
- * ── 조용히 자륎지 않는닀 ────────────────────────────────────────────────────
15
- * 잘랐닀는 사싀곌 **전첎 개수**륌 핚께 볎낞닀. 겜고 목록에서 조용한 누띜은 "ꎜ찮은 쀄 알았닀" 로
14
+ * ── 알늬지 않고 자륎지 않는닀 ────────────────────────────────────────────────────
15
+ * 잘랐닀는 사싀곌 **전첎 개수**륌 핚께 볎낞닀. 겜고 목록에서 듀얎옚 것읎 없는 누띜은 "ꎜ찮은 쀄 알았닀" 로
16
16
  * 읎얎진닀 — 레음읎 읎믞 "N걎 더" 륌 말하고 있었고, ê·ž N 은 전첎 개수에서 나와알 ë§žë‹€.
17
17
  *
18
18
  * ── 정렬을 한 곳에 둔닀 ─────────────────────────────────────────────────────
@@ -34,11 +34,11 @@ exports.compareAttentions = compareAttentions;
34
34
  * 신혞륌 요앜한닀.
35
35
  *
36
36
  * `limit` 읎 없거나 0 읎하멎 **자륎지 않는닀** — 자륎는 쪜읎 Ʞ볞읎멎 읎 값을 몚륎는 소비처가
37
- * 조용히 음부만 받는닀(요앜을 도입하닀 만드는 전형적읞 사고닀).
37
+ * 알늬지 않고 음부만 받는닀(요앜을 도입하닀 만드는 전형적읞 사고닀).
38
38
  */
39
39
  function digestAttentions(attentions, limit) {
40
40
  const all = Array.isArray(attentions) ? attentions : [];
41
- /* 자늬 색은 전량윌로 접는닀 — 잘늰 뒀에 접윌멎 색을 잃는 자늬가 생ꞎ닀. */
41
+ /* 자늬 색은 전량윌로 처늬한닀 — 잘늰 뒀에 계산하멎 색을 잃는 자늬가 생ꞎ닀. */
42
42
  const severityByLocation = {};
43
43
  for (const a of all) {
44
44
  const nid = a?.anchor?.locationId;
@@ -62,7 +62,7 @@ function digestAttentions(attentions, limit) {
62
62
  * 같은 자늬 id 가 렌슈마닀 닀륞 것을 가늬킬 수 있닀.
63
63
  * ② **순서는 렌슈 순서가 아니띌 ꞉한 순서닀** — 앞 렌슈의 낮은 신혞가 ë’€ 렌슈의 심각한 신혞륌
64
64
  * 밀얎낎멎, 상위 N 만 볎는 화멎에서 정작 ꞉한 것읎 안 볎읞닀.
65
- * ③ **자늬 색은 렌슈륌 가로질러 가장 ꞉한 것윌로** 접는닀 — 두 렌슈가 같은 자늬륌 가늬킀멎 ê·ž 자늬는
65
+ * ③ **자늬 색은 렌슈륌 가로질러 가장 ꞉한 것윌로** 계산한닀 — 두 렌슈가 같은 자늬륌 가늬킀멎 ê·ž 자늬는
66
66
  * 하나의 현싀읎므로 더 ꞉한 쪜읎 읎ꞎ닀(둘 쀑 하나륌 임의로 고륎멎 색읎 렌슈 순서에 따띌 달띌진닀).
67
67
  */
68
68
  function mergeLensAttentions(lenses, limit) {
@@ -1 +1 @@
1
- {"version":3,"file":"attention-digest.js","sourceRoot":"","sources":["../../server/engine/attention-digest.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAuCH,4CAeC;AAqBD,kDAMC;AA/ED,uCAAuC;AACvC,MAAM,IAAI,GAA2B,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;AAyBhF,+CAA+C;AACxC,MAAM,iBAAiB,GAAG,CAAC,CAAgB,EAAE,CAAgB,EAAU,EAAE,CAC9E,CAAC,CAAC,CAAC,KAAK,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AAFlD,QAAA,iBAAiB,qBAEiC;AAE/D;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,UAAuD,EAAE,KAAc;IACtG,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;IAEvD,+CAA+C;IAC/C,MAAM,kBAAkB,GAA2B,EAAE,CAAA;IACrD,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAA;QACjC,IAAI,CAAC,GAAG;YAAE,SAAQ;QAClB,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAAE,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAA;IAC1G,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,yBAAiB,CAAC,CAAA;IAC/C,MAAM,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACnE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAA;AAC/E,CAAC;AAQD;;;;;;;;;;;;GAYG;AACH,SAAgB,mBAAmB,CAAC,MAAiC,EAAE,KAAc;IACnF,MAAM,GAAG,GAAoB,EAAE,CAAA;IAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAmB,CAAC,CAAA;IACzG,CAAC;IACD,OAAO,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AACrC,CAAC","sourcesContent":["/*\n * 죌의 신혞 요앜 — **순수**. \"화멎읎 싀제로 쓰는 두 가지만 값싞게 만든닀.\"\n *\n * ── 왜 있나 (2026-08-05) ────────────────────────────────────────────────────\n * 축 선택윌로 늬프레시륌 80KB → 2KB 로 쀄였는데, **신혞가 많은 튞윈은 거Ʞ서 막혔닀**: `hatio-yard`\n * 는 신혞 397걎읎 108KB 띌 5ë°° 감소에 귞쳀닀. 귞런데 화멎읎 ê·ž 397걎윌로 하는 음은 둘뿐읎닀.\n *\n * ① 레음에 **20걎**만 볎여죌고 나뚞지는 \"N걎 더\" 띌고만 말한닀.\n * ② 자늬(폎늬곀)륌 칠할 **자늬별 최고 심각도**륌 뜑는닀 — 397걎읎 자늬 7곳의 색 7개로 접힌닀.\n *\n * 슉 전량을 낎렀볎낎 큎띌읎얞튞가 접는 구조였닀. 접는 것은 값싞므로 **서버가 접얎서 볎낞닀.**\n *\n * ── 조용히 자륎지 않는닀 ────────────────────────────────────────────────────\n * 잘랐닀는 사싀곌 **전첎 개수**륌 핚께 볎낞닀. 겜고 목록에서 조용한 누띜은 \"ꎜ찮은 쀄 알았닀\" 로\n * 읎얎진닀 — 레음읎 읎믞 \"N걎 더\" 륌 말하고 있었고, ê·ž N 은 전첎 개수에서 나와알 ë§žë‹€.\n *\n * ── 정렬을 한 곳에 둔닀 ─────────────────────────────────────────────────────\n * 상위 N 을 서버가 고륎므로 **큎띌읎얞튞와 같은 순서**여알 한닀. 순서가 닀륎멎 서버가 고륞 20걎읎\n * 화멎읎 고륌 20걎곌 달띌지고, ê·ž 얎Ꞌ낚은 아묎 데서도 였류로 드러나지 않는닀.\n * 순서 = 확읞된 것은 아래로, 귞닀음 심각도 높은 것부터(큎띌읎얞튞 정렬곌 동음).\n */\n\n/** 알람 표쀀(ISA-18.2) 우선순위 — 큰 값읎 ꞉하닀. */\nconst RANK: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 }\n\ninterface AttentionLike {\n id?: string\n /** 얎느 튞윈(렌슈)에서 옚 신혞읞가 — 공간에서 몚을 때 붙는닀. */\n instanceId?: string\n severity?: string\n state?: string\n anchor?: { locationId?: string }\n}\n\nexport interface AttentionDigestResult {\n /** 상위 N — 레음읎 귞늬는 것. */\n attentions: AttentionLike[]\n /** 전첎 개수 — 레음의 \"N걎 더\" 가 읎 값에서 나옚닀(자륞 사싀을 밝힌닀). */\n attentionTotal: number\n /**\n * 자늬별 최고 심각도 — **전량을 귌거로** 접는닀.\n *\n * 상위 N 만윌로 접윌멎 20위 밖의 신혞륌 가진 자늬가 색을 잃는닀. 귞것읎 읎 요앜의 핵심 읎유닀:\n * 레음은 잘띌도 되지만 **지도 색은 잘띌선 안 된닀.**\n */\n severityByLocation: Record<string, string>\n}\n\n/** 화멎 정렬곌 같은 순서 — 확읞된 것은 아래로, 귞닀음 심각도 낎늌찚순. */\nexport const compareAttentions = (a: AttentionLike, b: AttentionLike): number =>\n (a.state === 'acknowledged' ? 1 : 0) - (b.state === 'acknowledged' ? 1 : 0) ||\n (RANK[b.severity ?? ''] ?? 0) - (RANK[a.severity ?? ''] ?? 0)\n\n/**\n * 신혞륌 요앜한닀.\n *\n * `limit` 읎 없거나 0 읎하멎 **자륎지 않는닀** — 자륎는 쪜읎 Ʞ볞읎멎 읎 값을 몚륎는 소비처가\n * 조용히 음부만 받는닀(요앜을 도입하닀 만드는 전형적읞 사고닀).\n */\nexport function digestAttentions(attentions: readonly AttentionLike[] | undefined | null, limit?: number): AttentionDigestResult {\n const all = Array.isArray(attentions) ? attentions : []\n\n /* 자늬 색은 전량윌로 접는닀 — 잘늰 뒀에 접윌멎 색을 잃는 자늬가 생ꞎ닀. */\n const severityByLocation: Record<string, string> = {}\n for (const a of all) {\n const nid = a?.anchor?.locationId\n if (!nid) continue\n const cur = severityByLocation[nid]\n if (!cur || (RANK[a.severity ?? ''] ?? 0) > (RANK[cur] ?? 0)) severityByLocation[nid] = a.severity ?? ''\n }\n\n const sorted = [...all].sort(compareAttentions)\n const capped = limit && limit > 0 ? sorted.slice(0, limit) : sorted\n return { attentions: capped, attentionTotal: all.length, severityByLocation }\n}\n\n/** 렌슈 하나가 낾 신혞 — 얎느 튞윈에서 왔는지와 핚께. */\nexport interface LensAttentions {\n instanceId: string\n attentions: readonly AttentionLike[] | undefined | null\n}\n\n/**\n * 여러 렌슈의 신혞륌 **한 현장의 목록윌로** 몚은닀.\n *\n * 한 공장에 WMS·MES·YMS 가 핚께 있윌므로 \"읎 현장에서 뎐알 할 것\" 은 렌슈 하나로 답할 수 없닀.\n * 몚윌멎서 지킀는 것 셋:\n *\n * ① **얎느 튞윈에서 왔는지 붙읞닀**(`instanceId`) — 조치는 ê²°êµ­ ê·ž 튞윈에 볎낎알 하고, 공간에서 볎멎\n * 같은 자늬 id 가 렌슈마닀 닀륞 것을 가늬킬 수 있닀.\n * ② **순서는 렌슈 순서가 아니띌 ꞉한 순서닀** — 앞 렌슈의 낮은 신혞가 ë’€ 렌슈의 심각한 신혞륌\n * 밀얎낎멎, 상위 N 만 볎는 화멎에서 정작 ꞉한 것읎 안 볎읞닀.\n * ③ **자늬 색은 렌슈륌 가로질러 가장 ꞉한 것윌로** 접는닀 — 두 렌슈가 같은 자늬륌 가늬킀멎 ê·ž 자늬는\n * 하나의 현싀읎므로 더 ꞉한 쪜읎 읎ꞎ닀(둘 쀑 하나륌 임의로 고륎멎 색읎 렌슈 순서에 따띌 달띌진닀).\n */\nexport function mergeLensAttentions(lenses: readonly LensAttentions[], limit?: number): AttentionDigestResult {\n const all: AttentionLike[] = []\n for (const lens of lenses) {\n for (const a of lens.attentions ?? []) all.push({ ...a, instanceId: lens.instanceId } as AttentionLike)\n }\n return digestAttentions(all, limit)\n}\n"]}
1
+ {"version":3,"file":"attention-digest.js","sourceRoot":"","sources":["../../server/engine/attention-digest.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAuCH,4CAeC;AAqBD,kDAMC;AA/ED,uCAAuC;AACvC,MAAM,IAAI,GAA2B,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;AAyBhF,+CAA+C;AACxC,MAAM,iBAAiB,GAAG,CAAC,CAAgB,EAAE,CAAgB,EAAU,EAAE,CAC9E,CAAC,CAAC,CAAC,KAAK,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AAFlD,QAAA,iBAAiB,qBAEiC;AAE/D;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,UAAuD,EAAE,KAAc;IACtG,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;IAEvD,iDAAiD;IACjD,MAAM,kBAAkB,GAA2B,EAAE,CAAA;IACrD,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAA;QACjC,IAAI,CAAC,GAAG;YAAE,SAAQ;QAClB,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAAE,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAA;IAC1G,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,yBAAiB,CAAC,CAAA;IAC/C,MAAM,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACnE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAA;AAC/E,CAAC;AAQD;;;;;;;;;;;;GAYG;AACH,SAAgB,mBAAmB,CAAC,MAAiC,EAAE,KAAc;IACnF,MAAM,GAAG,GAAoB,EAAE,CAAA;IAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAmB,CAAC,CAAA;IACzG,CAAC;IACD,OAAO,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AACrC,CAAC","sourcesContent":["/*\n * 죌의 신혞 요앜 — **순수**. \"화멎읎 싀제로 쓰는 두 가지만 값싞게 만든닀.\"\n *\n * ── 왜 있나 (2026-08-05) ────────────────────────────────────────────────────\n * 축 선택윌로 늬프레시륌 80KB → 2KB 로 쀄였는데, **신혞가 많은 튞윈은 거Ʞ서 막혔닀**: `hatio-yard`\n * 는 신혞 397걎읎 108KB 띌 5ë°° 감소에 귞쳀닀. 귞런데 화멎읎 ê·ž 397걎윌로 하는 음은 둘뿐읎닀.\n *\n * ① 레음에 **20걎**만 볎여죌고 나뚞지는 \"N걎 더\" 띌고만 말한닀.\n * ② 자늬(폎늬곀)륌 칠할 **자늬별 최고 심각도**륌 뜑는닀 — 397걎읎 자늬 7곳의 색 7개로 쀄얎든닀.\n *\n * 슉 전량을 낎렀볎낎 큎띌읎얞튞가 계산하는 구조였닀. 계산하는 것은 값싞므로 **서버가 계산핎서 볎낞닀.**\n *\n * ── 알늬지 않고 자륎지 않는닀 ────────────────────────────────────────────────────\n * 잘랐닀는 사싀곌 **전첎 개수**륌 핚께 볎낞닀. 겜고 목록에서 듀얎옚 것읎 없는 누띜은 \"ꎜ찮은 쀄 알았닀\" 로\n * 읎얎진닀 — 레음읎 읎믞 \"N걎 더\" 륌 말하고 있었고, ê·ž N 은 전첎 개수에서 나와알 ë§žë‹€.\n *\n * ── 정렬을 한 곳에 둔닀 ─────────────────────────────────────────────────────\n * 상위 N 을 서버가 고륎므로 **큎띌읎얞튞와 같은 순서**여알 한닀. 순서가 닀륎멎 서버가 고륞 20걎읎\n * 화멎읎 고륌 20걎곌 달띌지고, ê·ž 얎Ꞌ낚은 아묎 데서도 였류로 드러나지 않는닀.\n * 순서 = 확읞된 것은 아래로, 귞닀음 심각도 높은 것부터(큎띌읎얞튞 정렬곌 동음).\n */\n\n/** 알람 표쀀(ISA-18.2) 우선순위 — 큰 값읎 ꞉하닀. */\nconst RANK: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 }\n\ninterface AttentionLike {\n id?: string\n /** 얎느 튞윈(렌슈)에서 옚 신혞읞가 — 공간에서 몚을 때 붙는닀. */\n instanceId?: string\n severity?: string\n state?: string\n anchor?: { locationId?: string }\n}\n\nexport interface AttentionDigestResult {\n /** 상위 N — 레음읎 귞늬는 것. */\n attentions: AttentionLike[]\n /** 전첎 개수 — 레음의 \"N걎 더\" 가 읎 값에서 나옚닀(자륞 사싀을 밝힌닀). */\n attentionTotal: number\n /**\n * 자늬별 최고 심각도 — **전량을 귌거로** 계산한닀.\n *\n * 상위 N 만윌로 계산하멎 20위 밖의 신혞륌 가진 자늬가 색을 잃는닀. 귞것읎 읎 요앜의 핵심 읎유닀:\n * 레음은 잘띌도 되지만 **지도 색은 잘띌선 안 된닀.**\n */\n severityByLocation: Record<string, string>\n}\n\n/** 화멎 정렬곌 같은 순서 — 확읞된 것은 아래로, 귞닀음 심각도 낎늌찚순. */\nexport const compareAttentions = (a: AttentionLike, b: AttentionLike): number =>\n (a.state === 'acknowledged' ? 1 : 0) - (b.state === 'acknowledged' ? 1 : 0) ||\n (RANK[b.severity ?? ''] ?? 0) - (RANK[a.severity ?? ''] ?? 0)\n\n/**\n * 신혞륌 요앜한닀.\n *\n * `limit` 읎 없거나 0 읎하멎 **자륎지 않는닀** — 자륎는 쪜읎 Ʞ볞읎멎 읎 값을 몚륎는 소비처가\n * 알늬지 않고 음부만 받는닀(요앜을 도입하닀 만드는 전형적읞 사고닀).\n */\nexport function digestAttentions(attentions: readonly AttentionLike[] | undefined | null, limit?: number): AttentionDigestResult {\n const all = Array.isArray(attentions) ? attentions : []\n\n /* 자늬 색은 전량윌로 처늬한닀 — 잘늰 뒀에 계산하멎 색을 잃는 자늬가 생ꞎ닀. */\n const severityByLocation: Record<string, string> = {}\n for (const a of all) {\n const nid = a?.anchor?.locationId\n if (!nid) continue\n const cur = severityByLocation[nid]\n if (!cur || (RANK[a.severity ?? ''] ?? 0) > (RANK[cur] ?? 0)) severityByLocation[nid] = a.severity ?? ''\n }\n\n const sorted = [...all].sort(compareAttentions)\n const capped = limit && limit > 0 ? sorted.slice(0, limit) : sorted\n return { attentions: capped, attentionTotal: all.length, severityByLocation }\n}\n\n/** 렌슈 하나가 낾 신혞 — 얎느 튞윈에서 왔는지와 핚께. */\nexport interface LensAttentions {\n instanceId: string\n attentions: readonly AttentionLike[] | undefined | null\n}\n\n/**\n * 여러 렌슈의 신혞륌 **한 현장의 목록윌로** 몚은닀.\n *\n * 한 공장에 WMS·MES·YMS 가 핚께 있윌므로 \"읎 현장에서 뎐알 할 것\" 은 렌슈 하나로 답할 수 없닀.\n * 몚윌멎서 지킀는 것 셋:\n *\n * ① **얎느 튞윈에서 왔는지 붙읞닀**(`instanceId`) — 조치는 ê²°êµ­ ê·ž 튞윈에 볎낎알 하고, 공간에서 볎멎\n * 같은 자늬 id 가 렌슈마닀 닀륞 것을 가늬킬 수 있닀.\n * ② **순서는 렌슈 순서가 아니띌 ꞉한 순서닀** — 앞 렌슈의 낮은 신혞가 ë’€ 렌슈의 심각한 신혞륌\n * 밀얎낎멎, 상위 N 만 볎는 화멎에서 정작 ꞉한 것읎 안 볎읞닀.\n * ③ **자늬 색은 렌슈륌 가로질러 가장 ꞉한 것윌로** 계산한닀 — 두 렌슈가 같은 자늬륌 가늬킀멎 ê·ž 자늬는\n * 하나의 현싀읎므로 더 ꞉한 쪜읎 읎ꞎ닀(둘 쀑 하나륌 임의로 고륎멎 색읎 렌슈 순서에 따띌 달띌진닀).\n */\nexport function mergeLensAttentions(lenses: readonly LensAttentions[], limit?: number): AttentionDigestResult {\n const all: AttentionLike[] = []\n for (const lens of lenses) {\n for (const a of lens.attentions ?? []) all.push({ ...a, instanceId: lens.instanceId } as AttentionLike)\n }\n return digestAttentions(all, limit)\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type EnergyRecord, type EnergyEquipmentRecord, type OperationalRecord, type IngestResult } from '@operato/twin-kernel';
1
+ import { type EnergyRecord, type EnergyEquipmentRecord, type OperationalRecord, type IngestResult, type MasterDataRecord } from '@operato/twin-kernel';
2
2
  /** 개첎 ꎀ잡 — 묌걎 하나가 얎디서 묎엇읎 됐나. */
3
3
  export interface CanonicalRecord {
4
4
  /**
@@ -86,4 +86,13 @@ export interface CanonicalAggregationRecord {
86
86
  bizLocation?: string;
87
87
  }
88
88
  /** 정규 레윔드[] → 검슝된 CanonicalEnvelope[] (+ 거부분). 순수 핚수. 닚음→객첎도 배엎로 정규화. */
89
- export declare function ingestCanonicalRecords(records: CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord | EnergyRecord | EnergyEquipmentRecord | OperationalRecord | (CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord | EnergyRecord | EnergyEquipmentRecord | OperationalRecord)[] | undefined | null, tenantId: string, defaultEventTime: string): IngestResult;
89
+ export declare function ingestCanonicalRecords(records: CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord | EnergyRecord | EnergyEquipmentRecord | OperationalRecord | MasterDataRecord | (CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord | EnergyRecord | EnergyEquipmentRecord | OperationalRecord | MasterDataRecord)[] | undefined | null, tenantId: string, defaultEventTime: string): CanonicalIngestResult;
90
+ /**
91
+ * 유입 결곌 — 사걎(뎉투)곌 **사걎읎 아닌 것**을 갈띌 낞닀.
92
+ *
93
+ * 마슀터데읎터륌 `accepted` 에 섞지 않는 읎유: 부륎는 쪜읎 귞것을 저널에 적게 되고, 시각축읎 없는 값읎
94
+ * 「귞때 음얎난 음」로 낚는닀. 갈래륌 타입윌로 갈띌 두멎 ê·ž 싀수륌 할 수 없닀.
95
+ */
96
+ export interface CanonicalIngestResult extends IngestResult {
97
+ masterData: MasterDataRecord[];
98
+ }
@@ -9,6 +9,8 @@ const twin_kernel_1 = require("@operato/twin-kernel");
9
9
  * 여Ʞ 도착하는 레윔드는 읎믞 정규 필드닀 — 얎휘마닀 자Ʞ 필드 읎늄읎 계앜읎닀:
10
10
  * EPCIS 품목 { epc, action, bizStep, disposition?, readPoint?, bizLocation? }
11
11
  * 에너지 계량 { meterId, kW?, kWh?, 
 } · 섀비 에너지 { equipmentId, generatedKW?, soc?, 
 }
12
+ * 발전 적산 { equipmentId, kWh, kWhSince?, 
 }
13
+ * 사용 구간 { meterId, from, to, kWh, unitPrice?, basis?, 
 } · 청구서 { from, to, total?, 
 }
12
14
  * 닎김(적재) { parentID, childEPCs[] | childQuantityList[], action, bizStep, 
 }
13
15
  * 욎영 사싀 { taskId | moverId | personId | assetId | orderId, status, 
 } // vocabulary-guard: allow 저널 와읎얎 필드
14
16
  * 컀널은 objectEvent 구성 + EPCIS 검슝(위반=였엌 찚닚) + 뎉투 래핑만(ë°©ì–ž 없음).
@@ -30,6 +32,32 @@ const TWIN_INGEST_RULES = [
30
32
  epc: '$.epc',
31
33
  /* 비직렬 수량 — 개첎 없읎 「읎 자늬에 읎 품목읎 얌마 낚았닀」만 였는 ꎀ잡읎 있닀. */
32
34
  quantityList: '$.quantityList',
35
+ /*
36
+ * **개첎·로튞의 마슀터데읎터**(로튞 번혞·소비Ʞ한 등) — 컀널 0.7.58 에서 읎 자늬가 ì—Žë žë‹€.
37
+ *
38
+ * 싀잡(포천): 원볞 재고 1,704행 **전부**에 소비Ʞ한읎 있는데 투영된 상태에는 **0걎**읎었닀. 지난
39
+ * 재고 950걎·59,785kg 읎 얎디에도 나타나지 않았고, 빈 화멎읎 「읎상 없음」윌로 읜혔닀.
40
+ *
41
+ * ★ **표쀀읎 `action: 'ADD'` 음 때만 허용한닀**(또는 변환). 마슀터데읎터는 로튞가 **생Ꞟ 때**
42
+ * 말하는 사싀읎고, 죌Ʞ ꎀ잡마닀 싀윌멎 컀널읎 거부한닀 — 알늬지 않고 통곌시킀지 않는 것읎 옳닀
43
+ * (컀넥터가 첫 목격에 `ADD`, ê·ž 뒀로 `OBSERVE` 륌 낎알 한닀).
44
+ */
45
+ ilmd: '$.ilmd',
46
+ /*
47
+ * **정정 ì„ ì–ž** — 「읎 사걎은 없던 음읎 되었닀」(컀널 0.7.65 에서 읎 자늬가 ì—Žë žë‹€).
48
+ *
49
+ * 섞 값읎 핚께여알 뜻읎 있얎 묶음윌로 옚닀. 컀널읎 ì„ ì–ž 시각을 요구하고, 없윌멎 사걎 시각윌로
50
+ * 메우지 않고 읎유와 핚께 돌렀쀀닀 — 「얞제 정정했나」와 「얞제 음얎났나」가 같아지멎 둘을 닀시
51
+ * 갈띌낌 수 없닀.
52
+ *
53
+ * 상태는 읎것윌로 흔듀늬지 않는닀. 컀널은 정정을 목록에 적고 재고륌 귞대로 둔닀 — 묎엇을 얎떻게
54
+ * 되돌늎지는 도메읞 판닚읎고, ì°ž 재고는 ê·ž 뒀의 잔량 ꎀ잡읎 닀시 말핮 쀀닀.
55
+ */
56
+ errorDeclaration: {
57
+ declarationTime: '$.errorDeclaration.declarationTime',
58
+ reason: '$.errorDeclaration.reason',
59
+ correctiveEventIDs: '$.errorDeclaration.correctiveEventIDs'
60
+ },
33
61
  readPoint: '$.readPoint',
34
62
  bizLocation: '$.bizLocation'
35
63
  }
@@ -46,6 +74,11 @@ const TWIN_INGEST_RULES = [
46
74
  outputEPCList: '$.outputEPCList',
47
75
  outputQuantityList: '$.outputQuantityList',
48
76
  transformationID: '$.transformationID',
77
+ errorDeclaration: {
78
+ declarationTime: '$.errorDeclaration.declarationTime',
79
+ reason: '$.errorDeclaration.reason',
80
+ correctiveEventIDs: '$.errorDeclaration.correctiveEventIDs'
81
+ },
49
82
  readPoint: '$.readPoint',
50
83
  bizLocation: '$.bizLocation'
51
84
  }
@@ -66,6 +99,11 @@ const TWIN_INGEST_RULES = [
66
99
  childEPCs: '$.childEPCs',
67
100
  /* 낱개 식별자 없읎 **수량윌로** 닎ꞎ 자식(「읎 품번 40개」) — 입고·포장읎 읎 몚양윌로 옚닀. */
68
101
  childQuantityList: '$.childQuantityList',
102
+ errorDeclaration: {
103
+ declarationTime: '$.errorDeclaration.declarationTime',
104
+ reason: '$.errorDeclaration.reason',
105
+ correctiveEventIDs: '$.errorDeclaration.correctiveEventIDs'
106
+ },
69
107
  readPoint: '$.readPoint',
70
108
  bizLocation: '$.bizLocation'
71
109
  }
@@ -74,6 +112,23 @@ const TWIN_INGEST_RULES = [
74
112
  /** 정규 레윔드[] → 검슝된 CanonicalEnvelope[] (+ 거부분). 순수 핚수. 닚음→객첎도 배엎로 정규화. */
75
113
  function ingestCanonicalRecords(records, tenantId, defaultEventTime) {
76
114
  const arr = Array.isArray(records) ? records : records ? [records] : [];
115
+ /*
116
+ * ── **닀섯짞 얎휘는 사걎읎 아니닀** (2026-08-28) ────────────────────────────
117
+ *
118
+ * 마슀터데읎터 — 변하지 않는 속성(유통Ʞ한·로튞번혞·자늬의 성질). 표쀀은 읎것을 사걎읎 아니띌
119
+ * **얎휘 요소의 속성**윌로 닎고, 컀널에 ê·ž 자늬가 없얎서 지ꞈ까지 사걎에 싀렀 왔닀.
120
+ *
121
+ * ê·ž 결곌가 유입에서 읎렇게 났닀. 전량을 읜는 원볞읎 유통Ʞ한을 싀윌렀고 **듀얎였지 않은 것을
122
+ * `ADD`** 띌고 말했고, `ilmd` 가 사걎 닚위띌 자늬별로 묶을 수도 없얎 낱개로 나갔닀 — 재Ʞ동 한 번에
123
+ * 2,665걎읎닀.
124
+ *
125
+ * 귞래서 여Ʞ서 갈띌 낞닀. 읎것은 뎉투가 되지 않고 저널에도 적히지 않는닀(시각축읎 없는 값읎닀).
126
+ * 갈래 판정은 컀널의 것을 부륞닀 — 닀륞 넷곌 같은 규윚읎닀.
127
+ *
128
+ * 섀계: `operato-twin/design/plans/master-data.md`
129
+ */
130
+ const masterCandidates = arr.filter(twin_kernel_1.isMasterDataRecord);
131
+ const master = masterCandidates.length ? (0, twin_kernel_1.ingestMasterData)(masterCandidates) : { accepted: [], rejected: [] };
77
132
  /*
78
133
  * **얎휘가 넷읎닀** — 묌류(EPCIS)·에너지 계량·섀비 에너지·욎영 사싀. 예전에는 읎 핚수가 묎조걎
79
134
  * `ObjectEvent` 륌 만듀었고, 귞래서 계잡을 읎 Ꞟ로 넣윌멎 `epc` 가 없얎 거부되거나(귞나마 나은 쪜)
@@ -85,21 +140,69 @@ function ingestCanonicalRecords(records, tenantId, defaultEventTime) {
85
140
  * 소비처마닀 답읎 달띌진닀. 뎉투는 같은 것을 쓰므로 아래 소비처(믞러·저널·람로드캐슀팅)는 읎 갈늌을 알
86
141
  * 필요가 없닀.
87
142
  */
88
- const energy = arr.filter(twin_kernel_1.isEnergyRecord);
143
+ /*
144
+ * 여섯짞·음곱짞 얎휘 — **마감된 사용 구간**곌 **청구서**. 컀널 0.7.72 가 읎 묞듀을 엎었닀.
145
+ *
146
+ * ── ★ 사용 구간을 계량볎닀 **뚌저** 가륞닀 ─────────────────────────────────
147
+ * `isEnergyRecord` 는 `meterId` 가 있윌멎 찞읎므로 사용 구간에도 찞읎닀. 순서륌 정하지 않윌멎
148
+ * 시간별 사용량읎 계량 표볞윌로 듀얎가고, ê·ž 묞은 `kWh` 륌 **적산 레지슀터**로 읜는닀. 귞러멎
149
+ * 컀널읎 구간 전력량을 찚분윌로 구하는데 우늬가 넣은 값읎 읎믞 구간의 양읎닀 — 찚분의 찚분읎 되얎
150
+ * 값읎 조용히 틀늰닀. 거부되지도 않는닀.
151
+ */
152
+ const usagePeriods = arr.filter(twin_kernel_1.isEnergyUsagePeriodRecord);
153
+ const bills = arr.filter(twin_kernel_1.isEnergyBillRecord);
154
+ const energy = arr.filter(r => (0, twin_kernel_1.isEnergyRecord)(r) && !(0, twin_kernel_1.isEnergyUsagePeriodRecord)(r));
89
155
  /* 섞 번짞 얎휘 — 섀비가 낾 자Ʞ 에너지 상태(발전·저장·감축 여지·개폐 위치). 계량곌 갈띌 두는
90
156
  읎유는 컀널에 적혀 있닀: 계량은 구간에 누적되고, 읎것듀은 ê·ž 섀비의 지ꞈ읎닀. */
91
- const energyEquipment = arr.filter(twin_kernel_1.isEnergyEquipmentRecord);
157
+ /*
158
+ * 닀섯 번짞 얎휘 — **발전 적산**(섀비가 지ꞈ까지 만든 양). 컀널 0.7.69 가 읎 묞을 엎었닀.
159
+ *
160
+ * ── ★ 섀비 상태볎닀 **뚌저** 가륞닀 ──────────────────────────────────────────
161
+ * 두 판정읎 겹친닀. `isEnergyEquipmentRecord` 는 `equipmentId` 가 있고 묌류·계량 얎휘가 아니멎
162
+ * 찞읎므로 발전 적산도 핚께 찞읎닀. 귞래서 순서가 갈늌을 정한닀.
163
+ *
164
+ * 순서륌 잘못 두멎 조용히 사띌지는 것읎 아니띌 **엉뚱한 읎유로 거부된닀**: 섀비 상태 묞은 적산을
165
+ * 값윌로 섞지 않아 「바꿀 상태가 하나도 없닀」로 돌렀볎낞닀. 컀넥터는 볎냈닀고 믿고, 화멎에는
166
+ * 발전량읎 없닀.
167
+ */
168
+ const energyGeneration = arr.filter(twin_kernel_1.isEnergyGenerationRecord);
169
+ const energyEquipment = arr.filter(r => (0, twin_kernel_1.isEnergyEquipmentRecord)(r) && !(0, twin_kernel_1.isEnergyGenerationRecord)(r));
92
170
  /*
93
171
  * ë„€ 번짞 얎휘 — **욎영 사싀**(작업·섀비·사람·자산·였더·품질). ꎀ잡 늬듀서는 읎것을 였래전부터
94
- * 접었는데 **듀얎올 묞읎 없었닀**: 원볞읎 「읎 작업읎 끝났닀」륌 말할 Ꞟ읎 없얎 시뮬 컀널만 귞것을
172
+ * 계산했는데 **듀얎올 묞읎 없었닀**: 원볞읎 「읎 작업읎 끝났닀」륌 말할 Ꞟ읎 없얎 시뮬 컀널만 귞것을
95
173
  * 아는 상태가 낚았닀(같은 화멎읎 두 구동에서 닀륞 것을 말한닀).
96
174
  */
97
175
  const operational = arr.filter(twin_kernel_1.isOperationalRecord);
98
- const epcis = arr.filter(r => !(0, twin_kernel_1.isEnergyRecord)(r) && !(0, twin_kernel_1.isEnergyEquipmentRecord)(r) && !(0, twin_kernel_1.isOperationalRecord)(r));
176
+ const epcis = arr.filter(r => !(0, twin_kernel_1.isEnergyRecord)(r) &&
177
+ !(0, twin_kernel_1.isEnergyEquipmentRecord)(r) &&
178
+ !(0, twin_kernel_1.isEnergyGenerationRecord)(r) &&
179
+ !(0, twin_kernel_1.isEnergyUsagePeriodRecord)(r) &&
180
+ !(0, twin_kernel_1.isEnergyBillRecord)(r) &&
181
+ !(0, twin_kernel_1.isOperationalRecord)(r) &&
182
+ !(0, twin_kernel_1.isMasterDataRecord)(r));
99
183
  /* 품목 얎휘 안에서도 갈늌읎 있닀(개첎 ꎀ잡 / 닎김) — ê·ž 판정도 컀널의 것을 부륞닀. */
100
184
  const epcisResult = epcis.length
101
185
  ? (0, twin_kernel_1.ingest)(epcis.map(r => ({
102
186
  ...r,
187
+ /*
188
+ * ── **시각의 읎늄을 둘 흡수한닀** (2026-08-24 싀잡) ────────────────────
189
+ * `eventTimePath` 는 **한 읎늄**만 받는닀. 혞슀튞가 `'eventTime'` 윌로 못박아 두었는데, 뒀에
190
+ * 생ꞎ 컀넥터는 `at` 을 싣는닀(에너지 채널읎 읎믞 `at` 을 쓰고 있얎 ê·ž 얎휘륌 따랐닀).
191
+ * 귞래서 ê·ž 컀넥터의 사걎은 **전부 폎링 순간**윌로 찍혔닀 — 저널 18,150걎읎 귞랬닀.
192
+ *
193
+ * ê·ž 결곌 둘읎 핚께 망가졌닀: 재고 ꎀ잡읎 튞윈의 시계륌 밀지 못핎 시계가 `task.status` 의
194
+ * 최댓값(2026-04-15)에 **멈춰 있었고**, 읎동 사걎에서 「얞제」가 사띌젞 순서만 낚았닀.
195
+ *
196
+ * 읎늄을 하나로 강요하지 않고 흡수한닀 — `orderId`·`resourceRef`·`equipmentId` 륌 핚께 볎는
197
+ * 것곌 같은 규윚읎닀(§`twin-event-keys`). 섞대가 섞읎는 것은 읎 읎음새의 성질읎닀.
198
+ *
199
+ * **없윌멎 만듀지 않는닀**: 절대값 슀냅샷 ꎀ잡은 원볞의 갱신 시각읎 아니띌 **폎링 순간**읎
200
+ * 맞는 ꎀ잡 시각읎닀(「얎제 값을 였늘 뎀닀」는 「얎제 음얎났닀」가 아니닀). 값을 말하는
201
+ * 레윔드만 자Ʞ 시각을 갖는닀.
202
+ */
203
+ ...((r.eventTime ?? r.at) !== undefined
204
+ ? { eventTime: r.eventTime ?? r.at }
205
+ : {}),
103
206
  /* 판정은 컀널읎 한 곳에서 한닀 — 여Ʞ서 닀시 짐작하멎 소비처마닀 답읎 달띌진닀. */
104
207
  sourceType: (0, twin_kernel_1.isTransformationRecord)(r)
105
208
  ? 'twin-transformation'
@@ -111,14 +214,14 @@ function ingestCanonicalRecords(records, tenantId, defaultEventTime) {
111
214
  * **레윔드가 시각을 말하멎 귞것을 쓎닀** (2026-08-23).
112
215
  *
113
216
  * `eventTimePath` 륌 죌지 않던 동안 읎 겜로는 **얞제나 폎링 시각**을 썌닀(`defaultEventTime`).
114
- * 귞래서 컀넥터가 읎믞 싣고 있던 `eventTime`(변환 레윔드의 `finishedAt` 등)읎 **조용히
217
+ * 귞래서 컀넥터가 읎믞 싣고 있던 `eventTime`(변환 레윔드의 `finishedAt` 등)읎 **알늬지 않고
115
218
  * 묎시됐닀** — 컀넥터륌 붙읞 쪜은 귞것읎 뚹는닀고 믿고 있었고, 얎디에도 였류가 나지 않았닀.
116
219
  *
117
220
  * 묎엇읎 걞렞나: 계볎(변환)의 시각읎닀. 4월에 만든 로튞가 8월에 만듀얎진 것윌로 저널에 낚았닀.
118
221
  * 귞늬고 싀잡 소요륌 재는 폎드가 뎉투 시각을 쓰므로(§`kpi-fold`: `workMs = 완료 − 첫 착수`),
119
222
  * 폎링 간격을 작업시간윌로 ë°°ìšž 수 있었닀 — 못 배우는 것볎닀 나쁘닀.
120
223
  *
121
- * 레윔드에 `eventTime` 읎 없윌멎 컀널읎 조용히 Ʞ볞값윌로 ë–šì–Žì§„ë‹€(§`resolve` — 없는 값은
224
+ * 레윔드에 `eventTime` 읎 없윌멎 컀널읎 알늬지 않고 Ʞ볞값윌로 ë–šì–Žì§„ë‹€(§`resolve` — 없는 값은
122
225
  * 였류가 아니닀). 귞래서 읎 한 쀄읎 Ʞ졎 겜로륌 막지 않는닀: 시각을 말하는 레윔드만 사싀읎 된닀.
123
226
  */
124
227
  { tenantId, defaultEventTime, eventTimePath: 'eventTime' })
@@ -127,13 +230,39 @@ function ingestCanonicalRecords(records, tenantId, defaultEventTime) {
127
230
  const equipmentResult = energyEquipment.length
128
231
  ? (0, twin_kernel_1.ingestEnergyEquipmentRecords)(energyEquipment, { tenantId, defaultEventTime })
129
232
  : { accepted: [], rejected: [] };
233
+ const usageResult = usagePeriods.length
234
+ ? (0, twin_kernel_1.ingestEnergyUsagePeriodRecords)(usagePeriods, { tenantId, defaultEventTime })
235
+ : { accepted: [], rejected: [] };
236
+ const billResult = bills.length ? (0, twin_kernel_1.ingestEnergyBillRecords)(bills, { tenantId, defaultEventTime }) : { accepted: [], rejected: [] };
237
+ const generationResult = energyGeneration.length
238
+ ? (0, twin_kernel_1.ingestEnergyGenerationRecords)(energyGeneration, { tenantId, defaultEventTime })
239
+ : { accepted: [], rejected: [] };
130
240
  const operationalResult = operational.length
131
241
  ? (0, twin_kernel_1.ingestOperationalRecords)(operational, { tenantId, defaultEventTime })
132
242
  : { accepted: [], rejected: [] };
133
243
  /* 거부분을 합쳐 돌렀쀀닀 — 얎느 얎휘에서 거부됐는지는 읎유 묞구가 말한닀. */
134
244
  return {
135
- accepted: [...epcisResult.accepted, ...energyResult.accepted, ...equipmentResult.accepted, ...operationalResult.accepted],
136
- rejected: [...epcisResult.rejected, ...energyResult.rejected, ...equipmentResult.rejected, ...operationalResult.rejected]
245
+ accepted: [
246
+ ...epcisResult.accepted,
247
+ ...energyResult.accepted,
248
+ ...equipmentResult.accepted,
249
+ ...generationResult.accepted,
250
+ ...usageResult.accepted,
251
+ ...billResult.accepted,
252
+ ...operationalResult.accepted
253
+ ],
254
+ rejected: [
255
+ ...epcisResult.rejected,
256
+ ...energyResult.rejected,
257
+ ...equipmentResult.rejected,
258
+ ...generationResult.rejected,
259
+ ...usageResult.rejected,
260
+ ...billResult.rejected,
261
+ ...operationalResult.rejected,
262
+ ...master.rejected
263
+ ],
264
+ /* 사걎읎 아닌 것은 따로 낞닀 — 부륎는 쪜읎 상태 섞우는 묞윌로 볎낞닀(저널로 가지 않게). */
265
+ masterData: master.accepted
137
266
  };
138
267
  }
139
268
  //# sourceMappingURL=canonical-ingest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-ingest.js","sourceRoot":"","sources":["../../server/engine/canonical-ingest.ts"],"names":[],"mappings":"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","sourcesContent":["import { ingest, ingestEnergyRecords, ingestEnergyEquipmentRecords, ingestOperationalRecords, isAggregationRecord, isTransformationRecord,\n isEnergyRecord, isEnergyEquipmentRecord, isOperationalRecord, type AdapterRule, type EnergyRecord,\n type EnergyEquipmentRecord, type OperationalRecord, type IngestResult } from '@operato/twin-kernel'\n\n/*\n * 정규 레윔드 → 컀널 검슝 ACL → CanonicalEnvelope (P1 seam 윔얎).\n * 순수(컀널만 의졎; shell·integration-base 묎의졎 → node:test 검슝 가능).\n * 맀핑(레거시 슀킀마 → 정규)은 읎 앞 닚계(jsonata step 또는 컀넥터 openLiveFeed)가 끝낞닀.\n * 여Ʞ 도착하는 레윔드는 읎믞 정규 필드닀 — 얎휘마닀 자Ʞ 필드 읎늄읎 계앜읎닀:\n * EPCIS 품목 { epc, action, bizStep, disposition?, readPoint?, bizLocation? }\n * 에너지 계량 { meterId, kW?, kWh?, 
 } · 섀비 에너지 { equipmentId, generatedKW?, soc?, 
 }\n * 닎김(적재) { parentID, childEPCs[] | childQuantityList[], action, bizStep, 
 }\n * 욎영 사싀 { taskId | moverId | personId | assetId | orderId, status, 
 } // vocabulary-guard: allow 저널 와읎얎 필드\n * 컀널은 objectEvent 구성 + EPCIS 검슝(위반=였엌 찚닚) + 뎉투 래핑만(ë°©ì–ž 없음).\n *\n * 두 소비처가 읎 닚음 윔얎륌 공유(쀑복 ꞈ지):\n * - sim/scenario 겜로: operato-twin twin-ingest 태슀크(http-get→jsonata→여Ʞ).\n * - live 컀넥터 겜로: reference-live(얎댑터 openLiveFeed→여Ʞ).\n * SoT: design/integration/face2-adapters.md §5(seam)·§7(맀핑=밖, 검슝=컀널).\n */\n\n/** 고정 정규 맀핑(ë°©ì–ž 아님 — 필드명 자첎가 정규 계앜). `sourceType` 윌로 얎느 품목 사싀읞지 고륞닀. */\nconst TWIN_INGEST_RULES: AdapterRule[] = [\n {\n sourceType: 'twin',\n mapping: {\n type: 'ObjectEvent',\n action: '$.action',\n bizStep: '$.bizStep',\n disposition: '$.disposition',\n epc: '$.epc',\n /* 비직렬 수량 — 개첎 없읎 「읎 자늬에 읎 품목읎 얌마 낚았닀」만 였는 ꎀ잡읎 있닀. */\n quantityList: '$.quantityList',\n readPoint: '$.readPoint',\n bizLocation: '$.bizLocation'\n }\n },\n {\n /* **변환의 사싀** — 묎엇윌로 묎엇읎 되었나. 읎늄은 표쀀의 것을 귞대로 쓎닀(갈래 판정읎 ê·ž 읎늄을 볞닀). */\n sourceType: 'twin-transformation',\n mapping: {\n type: 'TransformationEvent',\n bizStep: '$.bizStep',\n disposition: '$.disposition',\n inputEPCList: '$.inputEPCList',\n inputQuantityList: '$.inputQuantityList',\n outputEPCList: '$.outputEPCList',\n outputQuantityList: '$.outputQuantityList',\n transformationID: '$.transformationID',\n readPoint: '$.readPoint',\n bizLocation: '$.bizLocation'\n }\n },\n {\n /*\n * **닎김의 사싀** — 묎엇읎 묎엇에 싀렞나(팔레튞·상자). 였래 비얎 있던 자늬닀: ꎀ잡 늬듀서는 읎 사싀을\n * 받윌멎 자식 묌품에 `parent` 륌 붙읎는데, 묞읎 `ObjectEvent` 하나만 알아서 원볞은 적재륌 말할 Ꞟ읎\n * 없었닀(시뮬 원볞을 붙여 돌렀 볎고서알 로귞로 드러났닀).\n */\n sourceType: 'twin-aggregation',\n mapping: {\n type: 'AggregationEvent',\n action: '$.action',\n bizStep: '$.bizStep',\n disposition: '$.disposition',\n parentID: '$.parentID',\n childEPCs: '$.childEPCs',\n /* 낱개 식별자 없읎 **수량윌로** 닎ꞎ 자식(「읎 품번 40개」) — 입고·포장읎 읎 몚양윌로 옚닀. */\n childQuantityList: '$.childQuantityList',\n readPoint: '$.readPoint',\n bizLocation: '$.bizLocation'\n }\n }\n]\n\n/** 개첎 ꎀ잡 — 묌걎 하나가 얎디서 묎엇읎 됐나. */\nexport interface CanonicalRecord {\n /**\n * 개첎 하나의 식별자. **`quantityList` 륌 쓰멎 없얎도 된닀** — 낱개 번혞가 없는 자재(밀가룚 3.5kg)는\n * 개첎가 없닀. 둘 ë‹€ 없윌멎 묎엇을 ꎀ잡했는지 말하지 않은 것읎므로 컀널 맀핑읎 거부한닀.\n */\n epc?: string\n /**\n * 큎래슀와 수량 — `{ epcClass, quantity, uom? }`. **잔량 절대값을 싣는닀**(「얌마 뺐닀」가 아니띌\n * 「얌마 낚았닀」). 귞래알 사걎 하나륌 놓쳐도 닀음 사걎읎 정답을 닀시 말핮 죌고 였찚가 쌓읎지 않는닀.\n *\n * 닎김(`childQuantityList`)읎 하룚 뚌저 읎 자늬륌 받았닀 — 귞때와 같은 읎유닀. 원볞읎 비직렬 수량을\n * 말할 Ꞟ읎 없얎서, 귞것읎 죌된 겜로읞 시슀템(식품 제조 MES)은 띌읎람륌 낌 수 없었닀. 컀널의\n * ꎀ잡 늬듀서는 처음부터 읎 값을 읜었고 묞만 없었닀.\n */\n quantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n action: string // ADD | OBSERVE | DELETE\n bizStep: string\n disposition?: string\n readPoint?: string\n bizLocation?: string\n}\n\n/**\n * 닎김 ꎀ잡 — **부몚와 자식**윌로 말한닀. 자늬 필드는 개첎 ꎀ잡곌 같은 읎늄읎닀(묞자엎).\n *\n * 읎늄은 표쀀의 것을 귞대로 쓎닀(`parentID`·`childEPCs`) — 여Ʞ서 닀시 지윌멎 맀핑읎 번역읎 되고,\n * 같은 사싀에 두 얎휘가 생ꞎ닀.\n */\n/**\n * 변환 ꎀ잡 — **묎엇윌로 묎엇읎 되었나.** 입력곌 출력읎 **한 사싀에 핚께** 있얎알 계볎가 낚는닀.\n *\n * 따로 볎낎멎(「읎 로튞가 없얎졌닀」와 「읎 제품읎 생게닀」) ê·ž 둘을 읎을 귌거가 없닀. 귞래서 표쀀읎\n * 한 사걎에 둘을 닎고, 우늬 레윔드도 같은 몚양읎닀.\n *\n * 읎늄은 **표쀀의 것을 귞대로** 쓎닀(`inputQuantityList` 등). 갈래 판정읎 읎 읎늄윌로 읎룚얎지므로\n * 컀넥터 낱말(`consumed`·`produced`)로 닎윌멎 판정되지 않는닀 — 컀넥터가 정규 읎늄윌로 닎아 볎낎고\n * 맀핑은 ê·ž 안에서 값을 고륞닀.\n *\n * **없는 쪜은 필드륌 만듀지 않는닀.** 빈 배엎을 싀윌멎 「없닀」고 말하는 것읎 된닀. 소싀(N→0)곌\n * 생성(0→N)도 표쀀읎 읞정하는 변환읎닀.\n *\n * `transformationID` 가 한 였더의 여러 닚계륌 잇는닀 — 소비륌 뚌저 알고 산출을 나쀑에 알게 되는 원볞에서\n * ê·ž 둘을 묶는 유음한 자늬닀.\n */\nexport interface CanonicalTransformationRecord {\n /** 개첎로 소비된 것. */\n inputEPCList?: string[]\n /** 큎래슀와 수량윌로 소비된 것 — 로튞 닚위 소비가 읎 자늬닀. */\n inputQuantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n outputEPCList?: string[]\n outputQuantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n /** 한 였더의 여러 닚계륌 잇는 식별자. */\n transformationID?: string\n bizStep: string\n disposition?: string\n readPoint?: string\n bizLocation?: string\n}\n\nexport interface CanonicalAggregationRecord {\n parentID: string\n /** 개첎로 닎ꞎ 자식. 수량윌로만 닎게윌멎 없닀(둘 쀑 하나는 있얎알 한닀). */\n childEPCs?: string[]\n /** 수량윌로 닎ꞎ 자식 — `{ epcClass, quantity, uom? }`. 값의 옳고 귞늄은 컀널 검슝읎 볞닀. */\n childQuantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n action: string // ADD(닎닀) | DELETE(풀닀) | OBSERVE\n bizStep: string\n disposition?: string\n readPoint?: string\n bizLocation?: string\n}\n\n/** 정규 레윔드[] → 검슝된 CanonicalEnvelope[] (+ 거부분). 순수 핚수. 닚음→객첎도 배엎로 정규화. */\nexport function ingestCanonicalRecords(\n records:\n | CanonicalRecord\n | CanonicalAggregationRecord\n | CanonicalTransformationRecord\n | EnergyRecord\n | EnergyEquipmentRecord\n | OperationalRecord\n | (CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord | EnergyRecord | EnergyEquipmentRecord | OperationalRecord)[]\n | undefined\n | null,\n tenantId: string,\n defaultEventTime: string\n): IngestResult {\n const arr = Array.isArray(records) ? records : records ? [records] : []\n /*\n * **얎휘가 넷읎닀** — 묌류(EPCIS)·에너지 계량·섀비 에너지·욎영 사싀. 예전에는 읎 핚수가 묎조걎\n * `ObjectEvent` 륌 만듀었고, 귞래서 계잡을 읎 Ꞟ로 넣윌멎 `epc` 가 없얎 거부되거나(귞나마 나은 쪜)\n * 엉뚱한 묌품 ꎀ잡읎 됐닀.\n *\n * 묌류 얎휘 안에는 몚양읎 둘읎닀(개첎 ꎀ잡 `epc` / 닎김 `parentID`+`childEPCs`).\n *\n * 판정은 컀널읎 한 곳에서 한닀(`isEnergyRecord`·`isOperationalRecord`·`isAggregationRecord`) — 여Ʞ서 닀시 짐작하멎\n * 소비처마닀 답읎 달띌진닀. 뎉투는 같은 것을 쓰므로 아래 소비처(믞러·저널·람로드캐슀팅)는 읎 갈늌을 알\n * 필요가 없닀.\n */\n const energy = arr.filter(isEnergyRecord) as EnergyRecord[]\n /* 섞 번짞 얎휘 — 섀비가 낾 자Ʞ 에너지 상태(발전·저장·감축 여지·개폐 위치). 계량곌 갈띌 두는\n 읎유는 컀널에 적혀 있닀: 계량은 구간에 누적되고, 읎것듀은 ê·ž 섀비의 지ꞈ읎닀. */\n const energyEquipment = arr.filter(isEnergyEquipmentRecord) as unknown as EnergyEquipmentRecord[]\n /*\n * ë„€ 번짞 얎휘 — **욎영 사싀**(작업·섀비·사람·자산·였더·품질). ꎀ잡 늬듀서는 읎것을 였래전부터\n * 접었는데 **듀얎올 묞읎 없었닀**: 원볞읎 「읎 작업읎 끝났닀」륌 말할 Ꞟ읎 없얎 시뮬 컀널만 귞것을\n * 아는 상태가 낚았닀(같은 화멎읎 두 구동에서 닀륞 것을 말한닀).\n */\n const operational = arr.filter(isOperationalRecord) as OperationalRecord[]\n const epcis = arr.filter(r => !isEnergyRecord(r) && !isEnergyEquipmentRecord(r) && !isOperationalRecord(r)) as (CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord)[]\n\n /* 품목 얎휘 안에서도 갈늌읎 있닀(개첎 ꎀ잡 / 닎김) — ê·ž 판정도 컀널의 것을 부륞닀. */\n const epcisResult = epcis.length\n ? ingest(\n epcis.map(r => ({\n ...r,\n /* 판정은 컀널읎 한 곳에서 한닀 — 여Ʞ서 닀시 짐작하멎 소비처마닀 답읎 달띌진닀. */\n sourceType: isTransformationRecord(r)\n ? 'twin-transformation'\n : isAggregationRecord(r)\n ? 'twin-aggregation'\n : 'twin'\n })),\n TWIN_INGEST_RULES,\n /*\n * **레윔드가 시각을 말하멎 귞것을 쓎닀** (2026-08-23).\n *\n * `eventTimePath` 륌 죌지 않던 동안 읎 겜로는 **얞제나 폎링 시각**을 썌닀(`defaultEventTime`).\n * 귞래서 컀넥터가 읎믞 싣고 있던 `eventTime`(변환 레윔드의 `finishedAt` 등)읎 **조용히\n * 묎시됐닀** — 컀넥터륌 붙읞 쪜은 귞것읎 뚹는닀고 믿고 있었고, 얎디에도 였류가 나지 않았닀.\n *\n * 묎엇읎 걞렞나: 계볎(변환)의 시각읎닀. 4월에 만든 로튞가 8월에 만듀얎진 것윌로 저널에 낚았닀.\n * 귞늬고 싀잡 소요륌 재는 폎드가 뎉투 시각을 쓰므로(§`kpi-fold`: `workMs = 완료 − 첫 착수`),\n * 폎링 간격을 작업시간윌로 ë°°ìšž 수 있었닀 — 못 배우는 것볎닀 나쁘닀.\n *\n * 레윔드에 `eventTime` 읎 없윌멎 컀널읎 조용히 Ʞ볞값윌로 ë–šì–Žì§„ë‹€(§`resolve` — 없는 값은\n * 였류가 아니닀). 귞래서 읎 한 쀄읎 Ʞ졎 겜로륌 막지 않는닀: 시각을 말하는 레윔드만 사싀읎 된닀.\n */\n { tenantId, defaultEventTime, eventTimePath: 'eventTime' }\n )\n : { accepted: [], rejected: [] }\n const energyResult = energy.length ? ingestEnergyRecords(energy, { tenantId, defaultEventTime }) : { accepted: [], rejected: [] }\n const equipmentResult = energyEquipment.length\n ? ingestEnergyEquipmentRecords(energyEquipment, { tenantId, defaultEventTime })\n : { accepted: [], rejected: [] }\n const operationalResult = operational.length\n ? ingestOperationalRecords(operational, { tenantId, defaultEventTime })\n : { accepted: [], rejected: [] }\n\n /* 거부분을 합쳐 돌렀쀀닀 — 얎느 얎휘에서 거부됐는지는 읎유 묞구가 말한닀. */\n return {\n accepted: [...epcisResult.accepted, ...energyResult.accepted, ...equipmentResult.accepted, ...operationalResult.accepted],\n rejected: [...epcisResult.rejected, ...energyResult.rejected, ...equipmentResult.rejected, ...operationalResult.rejected]\n }\n}\n"]}
1
+ {"version":3,"file":"canonical-ingest.js","sourceRoot":"","sources":["../../server/engine/canonical-ingest.ts"],"names":[],"mappings":"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","sourcesContent":["import { ingest, ingestEnergyRecords, ingestEnergyEquipmentRecords, ingestEnergyGenerationRecords,\n ingestEnergyUsagePeriodRecords, ingestEnergyBillRecords, ingestOperationalRecords,\n isAggregationRecord, isTransformationRecord,\n isEnergyRecord, isEnergyEquipmentRecord, isEnergyGenerationRecord, isEnergyUsagePeriodRecord, isEnergyBillRecord,\n isOperationalRecord, type AdapterRule, type EnergyRecord,\n isMasterDataRecord, ingestMasterData,\n type EnergyEquipmentRecord, type EnergyGenerationRecord, type EnergyUsagePeriodRecord, type EnergyBillRecord,\n type OperationalRecord, type IngestResult, type MasterDataRecord } from '@operato/twin-kernel'\n\n/*\n * 정규 레윔드 → 컀널 검슝 ACL → CanonicalEnvelope (P1 seam 윔얎).\n * 순수(컀널만 의졎; shell·integration-base 묎의졎 → node:test 검슝 가능).\n * 맀핑(레거시 슀킀마 → 정규)은 읎 앞 닚계(jsonata step 또는 컀넥터 openLiveFeed)가 끝낞닀.\n * 여Ʞ 도착하는 레윔드는 읎믞 정규 필드닀 — 얎휘마닀 자Ʞ 필드 읎늄읎 계앜읎닀:\n * EPCIS 품목 { epc, action, bizStep, disposition?, readPoint?, bizLocation? }\n * 에너지 계량 { meterId, kW?, kWh?, 
 } · 섀비 에너지 { equipmentId, generatedKW?, soc?, 
 }\n * 발전 적산 { equipmentId, kWh, kWhSince?, 
 }\n * 사용 구간 { meterId, from, to, kWh, unitPrice?, basis?, 
 } · 청구서 { from, to, total?, 
 }\n * 닎김(적재) { parentID, childEPCs[] | childQuantityList[], action, bizStep, 
 }\n * 욎영 사싀 { taskId | moverId | personId | assetId | orderId, status, 
 } // vocabulary-guard: allow 저널 와읎얎 필드\n * 컀널은 objectEvent 구성 + EPCIS 검슝(위반=였엌 찚닚) + 뎉투 래핑만(ë°©ì–ž 없음).\n *\n * 두 소비처가 읎 닚음 윔얎륌 공유(쀑복 ꞈ지):\n * - sim/scenario 겜로: operato-twin twin-ingest 태슀크(http-get→jsonata→여Ʞ).\n * - live 컀넥터 겜로: reference-live(얎댑터 openLiveFeed→여Ʞ).\n * SoT: design/integration/face2-adapters.md §5(seam)·§7(맀핑=밖, 검슝=컀널).\n */\n\n/** 고정 정규 맀핑(ë°©ì–ž 아님 — 필드명 자첎가 정규 계앜). `sourceType` 윌로 얎느 품목 사싀읞지 고륞닀. */\nconst TWIN_INGEST_RULES: AdapterRule[] = [\n {\n sourceType: 'twin',\n mapping: {\n type: 'ObjectEvent',\n action: '$.action',\n bizStep: '$.bizStep',\n disposition: '$.disposition',\n epc: '$.epc',\n /* 비직렬 수량 — 개첎 없읎 「읎 자늬에 읎 품목읎 얌마 낚았닀」만 였는 ꎀ잡읎 있닀. */\n quantityList: '$.quantityList',\n /*\n * **개첎·로튞의 마슀터데읎터**(로튞 번혞·소비Ʞ한 등) — 컀널 0.7.58 에서 읎 자늬가 ì—Žë žë‹€.\n *\n * 싀잡(포천): 원볞 재고 1,704행 **전부**에 소비Ʞ한읎 있는데 투영된 상태에는 **0걎**읎었닀. 지난\n * 재고 950걎·59,785kg 읎 얎디에도 나타나지 않았고, 빈 화멎읎 「읎상 없음」윌로 읜혔닀.\n *\n * ★ **표쀀읎 `action: 'ADD'` 음 때만 허용한닀**(또는 변환). 마슀터데읎터는 로튞가 **생Ꞟ 때**\n * 말하는 사싀읎고, 죌Ʞ ꎀ잡마닀 싀윌멎 컀널읎 거부한닀 — 알늬지 않고 통곌시킀지 않는 것읎 옳닀\n * (컀넥터가 첫 목격에 `ADD`, ê·ž 뒀로 `OBSERVE` 륌 낎알 한닀).\n */\n ilmd: '$.ilmd',\n /*\n * **정정 ì„ ì–ž** — 「읎 사걎은 없던 음읎 되었닀」(컀널 0.7.65 에서 읎 자늬가 ì—Žë žë‹€).\n *\n * 섞 값읎 핚께여알 뜻읎 있얎 묶음윌로 옚닀. 컀널읎 ì„ ì–ž 시각을 요구하고, 없윌멎 사걎 시각윌로\n * 메우지 않고 읎유와 핚께 돌렀쀀닀 — 「얞제 정정했나」와 「얞제 음얎났나」가 같아지멎 둘을 닀시\n * 갈띌낌 수 없닀.\n *\n * 상태는 읎것윌로 흔듀늬지 않는닀. 컀널은 정정을 목록에 적고 재고륌 귞대로 둔닀 — 묎엇을 얎떻게\n * 되돌늎지는 도메읞 판닚읎고, ì°ž 재고는 ê·ž 뒀의 잔량 ꎀ잡읎 닀시 말핮 쀀닀.\n */\n errorDeclaration: {\n declarationTime: '$.errorDeclaration.declarationTime',\n reason: '$.errorDeclaration.reason',\n correctiveEventIDs: '$.errorDeclaration.correctiveEventIDs'\n },\n readPoint: '$.readPoint',\n bizLocation: '$.bizLocation'\n }\n },\n {\n /* **변환의 사싀** — 묎엇윌로 묎엇읎 되었나. 읎늄은 표쀀의 것을 귞대로 쓎닀(갈래 판정읎 ê·ž 읎늄을 볞닀). */\n sourceType: 'twin-transformation',\n mapping: {\n type: 'TransformationEvent',\n bizStep: '$.bizStep',\n disposition: '$.disposition',\n inputEPCList: '$.inputEPCList',\n inputQuantityList: '$.inputQuantityList',\n outputEPCList: '$.outputEPCList',\n outputQuantityList: '$.outputQuantityList',\n transformationID: '$.transformationID',\n errorDeclaration: {\n declarationTime: '$.errorDeclaration.declarationTime',\n reason: '$.errorDeclaration.reason',\n correctiveEventIDs: '$.errorDeclaration.correctiveEventIDs'\n },\n readPoint: '$.readPoint',\n bizLocation: '$.bizLocation'\n }\n },\n {\n /*\n * **닎김의 사싀** — 묎엇읎 묎엇에 싀렞나(팔레튞·상자). 였래 비얎 있던 자늬닀: ꎀ잡 늬듀서는 읎 사싀을\n * 받윌멎 자식 묌품에 `parent` 륌 붙읎는데, 묞읎 `ObjectEvent` 하나만 알아서 원볞은 적재륌 말할 Ꞟ읎\n * 없었닀(시뮬 원볞을 붙여 돌렀 볎고서알 로귞로 드러났닀).\n */\n sourceType: 'twin-aggregation',\n mapping: {\n type: 'AggregationEvent',\n action: '$.action',\n bizStep: '$.bizStep',\n disposition: '$.disposition',\n parentID: '$.parentID',\n childEPCs: '$.childEPCs',\n /* 낱개 식별자 없읎 **수량윌로** 닎ꞎ 자식(「읎 품번 40개」) — 입고·포장읎 읎 몚양윌로 옚닀. */\n childQuantityList: '$.childQuantityList',\n errorDeclaration: {\n declarationTime: '$.errorDeclaration.declarationTime',\n reason: '$.errorDeclaration.reason',\n correctiveEventIDs: '$.errorDeclaration.correctiveEventIDs'\n },\n readPoint: '$.readPoint',\n bizLocation: '$.bizLocation'\n }\n }\n]\n\n/** 개첎 ꎀ잡 — 묌걎 하나가 얎디서 묎엇읎 됐나. */\nexport interface CanonicalRecord {\n /**\n * 개첎 하나의 식별자. **`quantityList` 륌 쓰멎 없얎도 된닀** — 낱개 번혞가 없는 자재(밀가룚 3.5kg)는\n * 개첎가 없닀. 둘 ë‹€ 없윌멎 묎엇을 ꎀ잡했는지 말하지 않은 것읎므로 컀널 맀핑읎 거부한닀.\n */\n epc?: string\n /**\n * 큎래슀와 수량 — `{ epcClass, quantity, uom? }`. **잔량 절대값을 싣는닀**(「얌마 뺐닀」가 아니띌\n * 「얌마 낚았닀」). 귞래알 사걎 하나륌 놓쳐도 닀음 사걎읎 정답을 닀시 말핮 죌고 였찚가 쌓읎지 않는닀.\n *\n * 닎김(`childQuantityList`)읎 하룚 뚌저 읎 자늬륌 받았닀 — 귞때와 같은 읎유닀. 원볞읎 비직렬 수량을\n * 말할 Ꞟ읎 없얎서, 귞것읎 죌된 겜로읞 시슀템(식품 제조 MES)은 띌읎람륌 낌 수 없었닀. 컀널의\n * ꎀ잡 늬듀서는 처음부터 읎 값을 읜었고 묞만 없었닀.\n */\n quantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n action: string // ADD | OBSERVE | DELETE\n bizStep: string\n disposition?: string\n readPoint?: string\n bizLocation?: string\n}\n\n/**\n * 닎김 ꎀ잡 — **부몚와 자식**윌로 말한닀. 자늬 필드는 개첎 ꎀ잡곌 같은 읎늄읎닀(묞자엎).\n *\n * 읎늄은 표쀀의 것을 귞대로 쓎닀(`parentID`·`childEPCs`) — 여Ʞ서 닀시 지윌멎 맀핑읎 번역읎 되고,\n * 같은 사싀에 두 얎휘가 생ꞎ닀.\n */\n/**\n * 변환 ꎀ잡 — **묎엇윌로 묎엇읎 되었나.** 입력곌 출력읎 **한 사싀에 핚께** 있얎알 계볎가 낚는닀.\n *\n * 따로 볎낎멎(「읎 로튞가 없얎졌닀」와 「읎 제품읎 생게닀」) ê·ž 둘을 읎을 귌거가 없닀. 귞래서 표쀀읎\n * 한 사걎에 둘을 닎고, 우늬 레윔드도 같은 몚양읎닀.\n *\n * 읎늄은 **표쀀의 것을 귞대로** 쓎닀(`inputQuantityList` 등). 갈래 판정읎 읎 읎늄윌로 읎룚얎지므로\n * 컀넥터 낱말(`consumed`·`produced`)로 닎윌멎 판정되지 않는닀 — 컀넥터가 정규 읎늄윌로 닎아 볎낎고\n * 맀핑은 ê·ž 안에서 값을 고륞닀.\n *\n * **없는 쪜은 필드륌 만듀지 않는닀.** 빈 배엎을 싀윌멎 「없닀」고 말하는 것읎 된닀. 소싀(N→0)곌\n * 생성(0→N)도 표쀀읎 읞정하는 변환읎닀.\n *\n * `transformationID` 가 한 였더의 여러 닚계륌 잇는닀 — 소비륌 뚌저 알고 산출을 나쀑에 알게 되는 원볞에서\n * ê·ž 둘을 묶는 유음한 자늬닀.\n */\nexport interface CanonicalTransformationRecord {\n /** 개첎로 소비된 것. */\n inputEPCList?: string[]\n /** 큎래슀와 수량윌로 소비된 것 — 로튞 닚위 소비가 읎 자늬닀. */\n inputQuantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n outputEPCList?: string[]\n outputQuantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n /** 한 였더의 여러 닚계륌 잇는 식별자. */\n transformationID?: string\n bizStep: string\n disposition?: string\n readPoint?: string\n bizLocation?: string\n}\n\nexport interface CanonicalAggregationRecord {\n parentID: string\n /** 개첎로 닎ꞎ 자식. 수량윌로만 닎게윌멎 없닀(둘 쀑 하나는 있얎알 한닀). */\n childEPCs?: string[]\n /** 수량윌로 닎ꞎ 자식 — `{ epcClass, quantity, uom? }`. 값의 옳고 귞늄은 컀널 검슝읎 볞닀. */\n childQuantityList?: { epcClass: string; quantity?: number; uom?: string }[]\n action: string // ADD(닎닀) | DELETE(풀닀) | OBSERVE\n bizStep: string\n disposition?: string\n readPoint?: string\n bizLocation?: string\n}\n\n/** 정규 레윔드[] → 검슝된 CanonicalEnvelope[] (+ 거부분). 순수 핚수. 닚음→객첎도 배엎로 정규화. */\nexport function ingestCanonicalRecords(\n records:\n | CanonicalRecord\n | CanonicalAggregationRecord\n | CanonicalTransformationRecord\n | EnergyRecord\n | EnergyEquipmentRecord\n | OperationalRecord\n /* 닀섯짞 얎휘 — 사걎읎 아닌 것(변하지 않는 속성). 저널로 가지 않는닀(§`CanonicalIngestResult`). */\n | MasterDataRecord\n | (\n | CanonicalRecord\n | CanonicalAggregationRecord\n | CanonicalTransformationRecord\n | EnergyRecord\n | EnergyEquipmentRecord\n | OperationalRecord\n | MasterDataRecord\n )[]\n | undefined\n | null,\n tenantId: string,\n defaultEventTime: string\n): CanonicalIngestResult {\n const arr = Array.isArray(records) ? records : records ? [records] : []\n /*\n * ── **닀섯짞 얎휘는 사걎읎 아니닀** (2026-08-28) ────────────────────────────\n *\n * 마슀터데읎터 — 변하지 않는 속성(유통Ʞ한·로튞번혞·자늬의 성질). 표쀀은 읎것을 사걎읎 아니띌\n * **얎휘 요소의 속성**윌로 닎고, 컀널에 ê·ž 자늬가 없얎서 지ꞈ까지 사걎에 싀렀 왔닀.\n *\n * ê·ž 결곌가 유입에서 읎렇게 났닀. 전량을 읜는 원볞읎 유통Ʞ한을 싀윌렀고 **듀얎였지 않은 것을\n * `ADD`** 띌고 말했고, `ilmd` 가 사걎 닚위띌 자늬별로 묶을 수도 없얎 낱개로 나갔닀 — 재Ʞ동 한 번에\n * 2,665걎읎닀.\n *\n * 귞래서 여Ʞ서 갈띌 낞닀. 읎것은 뎉투가 되지 않고 저널에도 적히지 않는닀(시각축읎 없는 값읎닀).\n * 갈래 판정은 컀널의 것을 부륞닀 — 닀륞 넷곌 같은 규윚읎닀.\n *\n * 섀계: `operato-twin/design/plans/master-data.md`\n */\n const masterCandidates = arr.filter(isMasterDataRecord)\n const master = masterCandidates.length ? ingestMasterData(masterCandidates) : { accepted: [], rejected: [] }\n /*\n * **얎휘가 넷읎닀** — 묌류(EPCIS)·에너지 계량·섀비 에너지·욎영 사싀. 예전에는 읎 핚수가 묎조걎\n * `ObjectEvent` 륌 만듀었고, 귞래서 계잡을 읎 Ꞟ로 넣윌멎 `epc` 가 없얎 거부되거나(귞나마 나은 쪜)\n * 엉뚱한 묌품 ꎀ잡읎 됐닀.\n *\n * 묌류 얎휘 안에는 몚양읎 둘읎닀(개첎 ꎀ잡 `epc` / 닎김 `parentID`+`childEPCs`).\n *\n * 판정은 컀널읎 한 곳에서 한닀(`isEnergyRecord`·`isOperationalRecord`·`isAggregationRecord`) — 여Ʞ서 닀시 짐작하멎\n * 소비처마닀 답읎 달띌진닀. 뎉투는 같은 것을 쓰므로 아래 소비처(믞러·저널·람로드캐슀팅)는 읎 갈늌을 알\n * 필요가 없닀.\n */\n /*\n * 여섯짞·음곱짞 얎휘 — **마감된 사용 구간**곌 **청구서**. 컀널 0.7.72 가 읎 묞듀을 엎었닀.\n *\n * ── ★ 사용 구간을 계량볎닀 **뚌저** 가륞닀 ─────────────────────────────────\n * `isEnergyRecord` 는 `meterId` 가 있윌멎 찞읎므로 사용 구간에도 찞읎닀. 순서륌 정하지 않윌멎\n * 시간별 사용량읎 계량 표볞윌로 듀얎가고, ê·ž 묞은 `kWh` 륌 **적산 레지슀터**로 읜는닀. 귞러멎\n * 컀널읎 구간 전력량을 찚분윌로 구하는데 우늬가 넣은 값읎 읎믞 구간의 양읎닀 — 찚분의 찚분읎 되얎\n * 값읎 조용히 틀늰닀. 거부되지도 않는닀.\n */\n const usagePeriods = arr.filter(isEnergyUsagePeriodRecord) as unknown as EnergyUsagePeriodRecord[]\n const bills = arr.filter(isEnergyBillRecord) as unknown as EnergyBillRecord[]\n const energy = arr.filter(r => isEnergyRecord(r) && !isEnergyUsagePeriodRecord(r)) as EnergyRecord[]\n /* 섞 번짞 얎휘 — 섀비가 낾 자Ʞ 에너지 상태(발전·저장·감축 여지·개폐 위치). 계량곌 갈띌 두는\n 읎유는 컀널에 적혀 있닀: 계량은 구간에 누적되고, 읎것듀은 ê·ž 섀비의 지ꞈ읎닀. */\n /*\n * 닀섯 번짞 얎휘 — **발전 적산**(섀비가 지ꞈ까지 만든 양). 컀널 0.7.69 가 읎 묞을 엎었닀.\n *\n * ── ★ 섀비 상태볎닀 **뚌저** 가륞닀 ──────────────────────────────────────────\n * 두 판정읎 겹친닀. `isEnergyEquipmentRecord` 는 `equipmentId` 가 있고 묌류·계량 얎휘가 아니멎\n * 찞읎므로 발전 적산도 핚께 찞읎닀. 귞래서 순서가 갈늌을 정한닀.\n *\n * 순서륌 잘못 두멎 조용히 사띌지는 것읎 아니띌 **엉뚱한 읎유로 거부된닀**: 섀비 상태 묞은 적산을\n * 값윌로 섞지 않아 「바꿀 상태가 하나도 없닀」로 돌렀볎낞닀. 컀넥터는 볎냈닀고 믿고, 화멎에는\n * 발전량읎 없닀.\n */\n const energyGeneration = arr.filter(isEnergyGenerationRecord) as unknown as EnergyGenerationRecord[]\n const energyEquipment = arr.filter(r => isEnergyEquipmentRecord(r) && !isEnergyGenerationRecord(r)) as unknown as EnergyEquipmentRecord[]\n /*\n * ë„€ 번짞 얎휘 — **욎영 사싀**(작업·섀비·사람·자산·였더·품질). ꎀ잡 늬듀서는 읎것을 였래전부터\n * 계산했는데 **듀얎올 묞읎 없었닀**: 원볞읎 「읎 작업읎 끝났닀」륌 말할 Ꞟ읎 없얎 시뮬 컀널만 귞것을\n * 아는 상태가 낚았닀(같은 화멎읎 두 구동에서 닀륞 것을 말한닀).\n */\n const operational = arr.filter(isOperationalRecord) as OperationalRecord[]\n const epcis = arr.filter(\n r =>\n !isEnergyRecord(r) &&\n !isEnergyEquipmentRecord(r) &&\n !isEnergyGenerationRecord(r) &&\n !isEnergyUsagePeriodRecord(r) &&\n !isEnergyBillRecord(r) &&\n !isOperationalRecord(r) &&\n !isMasterDataRecord(r)\n ) as (CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord)[]\n\n /* 품목 얎휘 안에서도 갈늌읎 있닀(개첎 ꎀ잡 / 닎김) — ê·ž 판정도 컀널의 것을 부륞닀. */\n const epcisResult = epcis.length\n ? ingest(\n epcis.map(r => ({\n ...r,\n /*\n * ── **시각의 읎늄을 둘 흡수한닀** (2026-08-24 싀잡) ────────────────────\n * `eventTimePath` 는 **한 읎늄**만 받는닀. 혞슀튞가 `'eventTime'` 윌로 못박아 두었는데, 뒀에\n * 생ꞎ 컀넥터는 `at` 을 싣는닀(에너지 채널읎 읎믞 `at` 을 쓰고 있얎 ê·ž 얎휘륌 따랐닀).\n * 귞래서 ê·ž 컀넥터의 사걎은 **전부 폎링 순간**윌로 찍혔닀 — 저널 18,150걎읎 귞랬닀.\n *\n * ê·ž 결곌 둘읎 핚께 망가졌닀: 재고 ꎀ잡읎 튞윈의 시계륌 밀지 못핎 시계가 `task.status` 의\n * 최댓값(2026-04-15)에 **멈춰 있었고**, 읎동 사걎에서 「얞제」가 사띌젞 순서만 낚았닀.\n *\n * 읎늄을 하나로 강요하지 않고 흡수한닀 — `orderId`·`resourceRef`·`equipmentId` 륌 핚께 볎는\n * 것곌 같은 규윚읎닀(§`twin-event-keys`). 섞대가 섞읎는 것은 읎 읎음새의 성질읎닀.\n *\n * **없윌멎 만듀지 않는닀**: 절대값 슀냅샷 ꎀ잡은 원볞의 갱신 시각읎 아니띌 **폎링 순간**읎\n * 맞는 ꎀ잡 시각읎닀(「얎제 값을 였늘 뎀닀」는 「얎제 음얎났닀」가 아니닀). 값을 말하는\n * 레윔드만 자Ʞ 시각을 갖는닀.\n */\n ...(((r as any).eventTime ?? (r as any).at) !== undefined\n ? { eventTime: (r as any).eventTime ?? (r as any).at }\n : {}),\n /* 판정은 컀널읎 한 곳에서 한닀 — 여Ʞ서 닀시 짐작하멎 소비처마닀 답읎 달띌진닀. */\n sourceType: isTransformationRecord(r)\n ? 'twin-transformation'\n : isAggregationRecord(r)\n ? 'twin-aggregation'\n : 'twin'\n })),\n TWIN_INGEST_RULES,\n /*\n * **레윔드가 시각을 말하멎 귞것을 쓎닀** (2026-08-23).\n *\n * `eventTimePath` 륌 죌지 않던 동안 읎 겜로는 **얞제나 폎링 시각**을 썌닀(`defaultEventTime`).\n * 귞래서 컀넥터가 읎믞 싣고 있던 `eventTime`(변환 레윔드의 `finishedAt` 등)읎 **알늬지 않고\n * 묎시됐닀** — 컀넥터륌 붙읞 쪜은 귞것읎 뚹는닀고 믿고 있었고, 얎디에도 였류가 나지 않았닀.\n *\n * 묎엇읎 걞렞나: 계볎(변환)의 시각읎닀. 4월에 만든 로튞가 8월에 만듀얎진 것윌로 저널에 낚았닀.\n * 귞늬고 싀잡 소요륌 재는 폎드가 뎉투 시각을 쓰므로(§`kpi-fold`: `workMs = 완료 − 첫 착수`),\n * 폎링 간격을 작업시간윌로 ë°°ìšž 수 있었닀 — 못 배우는 것볎닀 나쁘닀.\n *\n * 레윔드에 `eventTime` 읎 없윌멎 컀널읎 알늬지 않고 Ʞ볞값윌로 ë–šì–Žì§„ë‹€(§`resolve` — 없는 값은\n * 였류가 아니닀). 귞래서 읎 한 쀄읎 Ʞ졎 겜로륌 막지 않는닀: 시각을 말하는 레윔드만 사싀읎 된닀.\n */\n { tenantId, defaultEventTime, eventTimePath: 'eventTime' }\n )\n : { accepted: [], rejected: [] }\n const energyResult = energy.length ? ingestEnergyRecords(energy, { tenantId, defaultEventTime }) : { accepted: [], rejected: [] }\n const equipmentResult = energyEquipment.length\n ? ingestEnergyEquipmentRecords(energyEquipment, { tenantId, defaultEventTime })\n : { accepted: [], rejected: [] }\n const usageResult = usagePeriods.length\n ? ingestEnergyUsagePeriodRecords(usagePeriods, { tenantId, defaultEventTime })\n : { accepted: [], rejected: [] }\n const billResult = bills.length ? ingestEnergyBillRecords(bills, { tenantId, defaultEventTime }) : { accepted: [], rejected: [] }\n const generationResult = energyGeneration.length\n ? ingestEnergyGenerationRecords(energyGeneration, { tenantId, defaultEventTime })\n : { accepted: [], rejected: [] }\n const operationalResult = operational.length\n ? ingestOperationalRecords(operational, { tenantId, defaultEventTime })\n : { accepted: [], rejected: [] }\n\n /* 거부분을 합쳐 돌렀쀀닀 — 얎느 얎휘에서 거부됐는지는 읎유 묞구가 말한닀. */\n return {\n accepted: [\n ...epcisResult.accepted,\n ...energyResult.accepted,\n ...equipmentResult.accepted,\n ...generationResult.accepted,\n ...usageResult.accepted,\n ...billResult.accepted,\n ...operationalResult.accepted\n ],\n rejected: [\n ...epcisResult.rejected,\n ...energyResult.rejected,\n ...equipmentResult.rejected,\n ...generationResult.rejected,\n ...usageResult.rejected,\n ...billResult.rejected,\n ...operationalResult.rejected,\n ...master.rejected\n ],\n /* 사걎읎 아닌 것은 따로 낞닀 — 부륎는 쪜읎 상태 섞우는 묞윌로 볎낞닀(저널로 가지 않게). */\n masterData: master.accepted\n }\n}\n\n/**\n * 유입 결곌 — 사걎(뎉투)곌 **사걎읎 아닌 것**을 갈띌 낞닀.\n *\n * 마슀터데읎터륌 `accepted` 에 섞지 않는 읎유: 부륎는 쪜읎 귞것을 저널에 적게 되고, 시각축읎 없는 값읎\n * 「귞때 음얎난 음」로 낚는닀. 갈래륌 타입윌로 갈띌 두멎 ê·ž 싀수륌 할 수 없닀.\n */\nexport interface CanonicalIngestResult extends IngestResult {\n masterData: MasterDataRecord[]\n}\n"]}
@@ -17,7 +17,7 @@
17
17
  * | 죌석(확읞 ack) | 컀널 런타임 | ꎀ잡 컀널 |
18
18
  *
19
19
  * 믞러에서 액추에읎션을 귞냥 허용하멎 **새 거짓말읎 생ꞎ닀**: 튞윈은 "볎류됚" 읎띌 말하고 ì‹€ 시슀템은
20
- * 몚륞닀. 조용히 컀널만 바꟞지 않고, 읎유륌 밝혀 거절한닀.
20
+ * 몚륞닀. 알늬지 않고 컀널만 바꟞지 않고, 읎유륌 밝혀 거절한닀.
21
21
  *
22
22
  * 반멎 확읞(ack)은 액추에읎션읎 아니닀 — 신혞륌 뎀닀는 튞윈 쪜 죌석읎띌 현싀을 걎드늬지 않는닀.
23
23
  * 믞러에서도 성늜핎알 하므로 ꎀ잡 컀널로 볎낞닀.
@@ -1 +1 @@
1
- {"version":3,"file":"command-routing.js","sourceRoot":"","sources":["../../server/engine/command-routing.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;AAgCH,oCAYC;AA1CD,6CAA6C;AAC7C,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAS,CAAC,eAAe,CAAC,CAAC,CAAA;AAoB9D,uCAAuC;AAChC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AAAvE,QAAA,WAAW,eAA4D;AAEpF;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,IAAkC,EAAE,aAAsB,EAAE,IAAY;IACnG,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,CAAA;IAClF,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAA;IAEpE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,+CAA+C;QAC/C,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,CAAA;IAChG,CAAC;IAED,iDAAiD;IACjD,IAAI,IAAA,mBAAW,EAAC,IAAI,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,qBAAqB,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,EAAE,CAAA;IAC3G,OAAO,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,CAAA;AACtG,CAAC","sourcesContent":["/*\n * 컀맚드 띌우팅 판정 — **순수**. \"읎 컀맚드륌 누구에게 볎낌 것읞가\" 만 정한닀.\n * 싀제 dispatch·저널 Ʞ록은 엔진읎 한닀(`design/plans/command-routing.md` §1·§4 P0).\n *\n * ── 왜 떌얎냈나 ─────────────────────────────────────────────────────────────\n * 예전에는 늬졞버가 `inst.runtime.dispatch(...)` 륌 곧바로 불렀닀. `runtime` 은 **시뮬 겜로에서만**\n * 만듀얎지므로 싀묌을 비추는 튞윈(mirror)에서는 ê·ž 한 쀄읎 `TypeError` 로 터졌닀 — 조치 채널읎\n * 통짞로 닿지 않았고, 사용자에게는 읎유 있는 거절읎 아니띌 귞냥 싀팚였닀.\n *\n * 판정읎 윔드 한가욎데 있윌멎 읎런 부류륌 테슀튞로 못 잡는닀(엔진은 DB·TypeORM 을 묌고 있얎 닚위\n * 테슀튞가 불러올 수 없닀). 귞래서 판정만 순수하게 떌얎 둔닀 — `planWarmStart` 와 같은 읎유닀.\n *\n * ── 판정 규칙 = 권위 × 성격 ─────────────────────────────────────────────────\n * | 성격 \\ 몚드 | 시뮬 | 믞러(현싀을 비춀) |\n * | 액추에읎션 | 컀널 런타임 | **거절**(아웃바욎드 얎댑터 믞결선) |\n * | 죌석(확읞 ack) | 컀널 런타임 | ꎀ잡 컀널 |\n *\n * 믞러에서 액추에읎션을 귞냥 허용하멎 **새 거짓말읎 생ꞎ닀**: 튞윈은 \"볎류됚\" 읎띌 말하고 ì‹€ 시슀템은\n * 몚륞닀. 조용히 컀널만 바꟞지 않고, 읎유륌 밝혀 거절한닀.\n *\n * 반멎 확읞(ack)은 액추에읎션읎 아니닀 — 신혞륌 뎀닀는 튞윈 쪜 죌석읎띌 현싀을 걎드늬지 않는닀.\n * 믞러에서도 성늜핎알 하므로 ꎀ잡 컀널로 볎낞닀.\n */\n\n/** ꎀ잡 쪜 죌석 컀맚드 — 현싀을 바꟞지 않윌므로 믞러에서도 통곌한닀. */\nconst ANNOTATION_COMMANDS = new Set<string>(['attention.ack'])\n\n/** 띌우팅에 필요한 읞슀턎슀 사싀만 — 엔진 객첎륌 귞대로 받지 않는닀(순수하게 유지). */\nexport interface RoutableInstance {\n /** 'live' 멎 현싀을 비추는 튞윈(믞러). ê·ž 왞는 시뮬. */\n mode?: string\n /** 컀널 런타임(tick/dispatch)읎 붙얎 있나 — 시뮬 겜로에서만 만듀얎진닀. */\n hasRuntime: boolean\n /** ꎀ잡 컀널읎 dispatch 륌 받을 수 있나. */\n hasKernelDispatch: boolean\n}\n\nexport type CommandRoute =\n /** 컀널 런타임윌로(시뮬 — 컀널읎 섞계닀). */\n | { target: 'runtime' }\n /** ꎀ잡 컀널로(믞러 — 죌석만). 방출된 사싀은 저널 큐에 싀얎알 한닀. */\n | { target: 'kernel' }\n /** 볎낎지 않는닀. 사유는 ì–žì–Ž 쀑늜 윔드 — 화멎읎 `twin.cmderr.<code>` 로 사람 말을 만든닀. */\n | { target: 'reject'; errorCode: string; errorParams?: Record<string, string | number> }\n\n/** 읎 컀맚드가 ì‹€ 프로섞슀륌 바꟞는 것읞가(= 액추에읎션). */\nexport const isActuation = (type: string): boolean => !ANNOTATION_COMMANDS.has(type)\n\n/**\n * 얎디로 볎낌지 정한닀.\n *\n * `inst` 가 없거나 혞출자 도메읞 소유가 아니멎 **같은 사유로** 거절한닀 — 졎재 여부륌 알렀 죌멎\n * 닀륞 테넌튞의 읞슀턎슀 id 륌 추잡할 수 있닀(있음/없음읎 구별되멎 귞것읎 정볎닀).\n */\nexport function routeCommand(inst: RoutableInstance | undefined, ownedByCaller: boolean, type: string): CommandRoute {\n if (!inst || !ownedByCaller) return { target: 'reject', errorCode: 'no-instance' }\n if (!type) return { target: 'reject', errorCode: 'unknown-command' }\n\n if (inst.mode !== 'live') {\n /* 시뮬 — 컀널읎 섞계닀. 런타임읎 없윌멎 였류륌 낎지 않고 읎유륌 말한닀. */\n return inst.hasRuntime ? { target: 'runtime' } : { target: 'reject', errorCode: 'no-runtime' }\n }\n\n /* 믞러 — ì‹€ 프로섞슀 변겜은 아웃바욎드 얎댑터의 몫읎고 아직 결선되지 않았닀. */\n if (isActuation(type)) return { target: 'reject', errorCode: 'actuation-not-wired', errorParams: { type } }\n return inst.hasKernelDispatch ? { target: 'kernel' } : { target: 'reject', errorCode: 'no-runtime' }\n}\n"]}
1
+ {"version":3,"file":"command-routing.js","sourceRoot":"","sources":["../../server/engine/command-routing.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;AAgCH,oCAYC;AA1CD,6CAA6C;AAC7C,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAS,CAAC,eAAe,CAAC,CAAC,CAAA;AAoB9D,uCAAuC;AAChC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AAAvE,QAAA,WAAW,eAA4D;AAEpF;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,IAAkC,EAAE,aAAsB,EAAE,IAAY;IACnG,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,CAAA;IAClF,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAA;IAEpE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,+CAA+C;QAC/C,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,CAAA;IAChG,CAAC;IAED,iDAAiD;IACjD,IAAI,IAAA,mBAAW,EAAC,IAAI,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,qBAAqB,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,EAAE,CAAA;IAC3G,OAAO,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,CAAA;AACtG,CAAC","sourcesContent":["/*\n * 컀맚드 띌우팅 판정 — **순수**. \"읎 컀맚드륌 누구에게 볎낌 것읞가\" 만 정한닀.\n * 싀제 dispatch·저널 Ʞ록은 엔진읎 한닀(`design/plans/command-routing.md` §1·§4 P0).\n *\n * ── 왜 떌얎냈나 ─────────────────────────────────────────────────────────────\n * 예전에는 늬졞버가 `inst.runtime.dispatch(...)` 륌 곧바로 불렀닀. `runtime` 은 **시뮬 겜로에서만**\n * 만듀얎지므로 싀묌을 비추는 튞윈(mirror)에서는 ê·ž 한 쀄읎 `TypeError` 로 터졌닀 — 조치 채널읎\n * 통짞로 닿지 않았고, 사용자에게는 읎유 있는 거절읎 아니띌 귞냥 싀팚였닀.\n *\n * 판정읎 윔드 한가욎데 있윌멎 읎런 부류륌 테슀튞로 못 잡는닀(엔진은 DB·TypeORM 을 묌고 있얎 닚위\n * 테슀튞가 불러올 수 없닀). 귞래서 판정만 순수하게 떌얎 둔닀 — `planWarmStart` 와 같은 읎유닀.\n *\n * ── 판정 규칙 = 권위 × 성격 ─────────────────────────────────────────────────\n * | 성격 \\ 몚드 | 시뮬 | 믞러(현싀을 비춀) |\n * | 액추에읎션 | 컀널 런타임 | **거절**(아웃바욎드 얎댑터 믞결선) |\n * | 죌석(확읞 ack) | 컀널 런타임 | ꎀ잡 컀널 |\n *\n * 믞러에서 액추에읎션을 귞냥 허용하멎 **새 거짓말읎 생ꞎ닀**: 튞윈은 \"볎류됚\" 읎띌 말하고 ì‹€ 시슀템은\n * 몚륞닀. 알늬지 않고 컀널만 바꟞지 않고, 읎유륌 밝혀 거절한닀.\n *\n * 반멎 확읞(ack)은 액추에읎션읎 아니닀 — 신혞륌 뎀닀는 튞윈 쪜 죌석읎띌 현싀을 걎드늬지 않는닀.\n * 믞러에서도 성늜핎알 하므로 ꎀ잡 컀널로 볎낞닀.\n */\n\n/** ꎀ잡 쪜 죌석 컀맚드 — 현싀을 바꟞지 않윌므로 믞러에서도 통곌한닀. */\nconst ANNOTATION_COMMANDS = new Set<string>(['attention.ack'])\n\n/** 띌우팅에 필요한 읞슀턎슀 사싀만 — 엔진 객첎륌 귞대로 받지 않는닀(순수하게 유지). */\nexport interface RoutableInstance {\n /** 'live' 멎 현싀을 비추는 튞윈(믞러). ê·ž 왞는 시뮬. */\n mode?: string\n /** 컀널 런타임(tick/dispatch)읎 붙얎 있나 — 시뮬 겜로에서만 만듀얎진닀. */\n hasRuntime: boolean\n /** ꎀ잡 컀널읎 dispatch 륌 받을 수 있나. */\n hasKernelDispatch: boolean\n}\n\nexport type CommandRoute =\n /** 컀널 런타임윌로(시뮬 — 컀널읎 섞계닀). */\n | { target: 'runtime' }\n /** ꎀ잡 컀널로(믞러 — 죌석만). 방출된 사싀은 저널 큐에 싀얎알 한닀. */\n | { target: 'kernel' }\n /** 볎낎지 않는닀. 사유는 ì–žì–Ž 쀑늜 윔드 — 화멎읎 `twin.cmderr.<code>` 로 사람 말을 만든닀. */\n | { target: 'reject'; errorCode: string; errorParams?: Record<string, string | number> }\n\n/** 읎 컀맚드가 ì‹€ 프로섞슀륌 바꟞는 것읞가(= 액추에읎션). */\nexport const isActuation = (type: string): boolean => !ANNOTATION_COMMANDS.has(type)\n\n/**\n * 얎디로 볎낌지 정한닀.\n *\n * `inst` 가 없거나 혞출자 도메읞 소유가 아니멎 **같은 사유로** 거절한닀 — 졎재 여부륌 알렀 죌멎\n * 닀륞 테넌튞의 읞슀턎슀 id 륌 추잡할 수 있닀(있음/없음읎 구별되멎 귞것읎 정볎닀).\n */\nexport function routeCommand(inst: RoutableInstance | undefined, ownedByCaller: boolean, type: string): CommandRoute {\n if (!inst || !ownedByCaller) return { target: 'reject', errorCode: 'no-instance' }\n if (!type) return { target: 'reject', errorCode: 'unknown-command' }\n\n if (inst.mode !== 'live') {\n /* 시뮬 — 컀널읎 섞계닀. 런타임읎 없윌멎 였류륌 낎지 않고 읎유륌 말한닀. */\n return inst.hasRuntime ? { target: 'runtime' } : { target: 'reject', errorCode: 'no-runtime' }\n }\n\n /* 믞러 — ì‹€ 프로섞슀 변겜은 아웃바욎드 얎댑터의 몫읎고 아직 결선되지 않았닀. */\n if (isActuation(type)) return { target: 'reject', errorCode: 'actuation-not-wired', errorParams: { type } }\n return inst.hasKernelDispatch ? { target: 'kernel' } : { target: 'reject', errorCode: 'no-runtime' }\n}\n"]}
@@ -18,7 +18,7 @@
18
18
  * ── 판정을 순수 핚수로 (읎 파음) ────────────────────────────────────────────
19
19
  * 「읎 튞윈에 저장된 자극을 싀을 것읞가」에는 사람읎 틀늬Ʞ 쉬욎 갈늌읎 셋 있닀: 믞러에 싀윌멎 **현싀을
20
20
  * 였엌**시킀고, 잘못된 선얞을 싀윌멎 **닀음 틱에서 서버가 낎렀가고**(싀제로 ê·ž 읎력읎 있닀), 시나늬였
21
- * 엔진읎 없는 런타임에 싀윌멎 조용히 아묎 음도 없닀. 귞래서 판정을 값윌로 만듀고 시험한닀.
21
+ * 엔진읎 없는 런타임에 싀윌멎 알늬지 않고 아묎 음도 없닀. 귞래서 판정을 값윌로 만듀고 시험한닀.
22
22
  */
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.planStimulus = planStimulus;
@@ -1 +1 @@
1
- {"version":3,"file":"declared-stimulus.js","sourceRoot":"","sources":["../../server/engine/declared-stimulus.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;AAsBH,oCAcC;AAOD,oCAEC;AA9BD;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,MAAW,EACX,OAA8D,EAC9D,QAAuH;IAEvH,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAA;IACjC,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;IACxF,+DAA+D;IAC/D,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;IAC1E,IAAI,CAAC,OAAO,CAAC,iBAAiB;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;IAC9E,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAA;IAC7F,MAAM,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC5B,IAAI,CAAC,CAAC,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAG,CAAS,EAAE,SAAS,IAAI,UAAU,EAAE,CAAA;IACrG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;AACrC,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY,CAAC,MAAW,EAAE,QAAa;IACrD,OAAO,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAA;AACxC,CAAC","sourcesContent":["/*\n * **자극은 원볞읎 선얞한닀** — 튞윈읎 아니띌.\n *\n * ── 묎엇읎 났나 (2026-08-19) ────────────────────────────────────────────────\n * 데몚의 자극(시나늬였)은 시드 윔드가 **메몚늬에만** 싀었닀: `runtime.scenario.load(...)`. 귞래서 튞윈을\n * 재Ʞ동하멎 자극읎 사띌지고, 구조만 서 있는 튞윈읎 낚는닀 — 작업 0·였더 0. 「삎아 있는 데몚」가\n * **첫 재Ʞ동까지만** 사는 것읎닀(였늘 서버륌 여러 번 띄우는 동안 싀제로 ê·ž 상태였닀).\n *\n * ── 왜 튞윈에 저장하지 않나 (ADR-0029 · plans/simulator-as-source.md §4) ────\n * 자극은 **원볞의 거동**읎닀: 묎엇읎 듀얎였고 묎슚 죌묞읎 나는지는 시뮬레읎터(원볞)가 정하는 사싀읎고,\n * 튞윈은 귞것을 반영한닀. 튞윈에 새 축을 만듀멎 ADR-0029 가 나쀑에 걷얎낎알 하는 표멎읎 하나 늘고\n * (ê·ž 계획서의 §2·§5 가 읎믞 ê·ž 부닎을 적얎 두었닀), 원볞에 두멎 ê·ž 계획의 **첫 조각 앞자늬**가 된닀:\n * 지ꞈ은 혞슀튞가 읜얎 컀널에 싣고, 나쀑에 `openLiveFeed` 뒀로 옮Ʞ멎 같은 선얞읎 귞대로 쓰읞닀.\n *\n * 귞래서 집은 `TwinReference.connectionConfig.scenario` — 얎댑터별 섀정 자늬(읎믞 `simple-json`)ë‹€.\n *\n * ── 판정을 순수 핚수로 (읎 파음) ────────────────────────────────────────────\n * 「읎 튞윈에 저장된 자극을 싀을 것읞가」에는 사람읎 틀늬Ʞ 쉬욎 갈늌읎 셋 있닀: 믞러에 싀윌멎 **현싀을\n * 였엌**시킀고, 잘못된 선얞을 싀윌멎 **닀음 틱에서 서버가 낎렀가고**(싀제로 ê·ž 읎력읎 있닀), 시나늬였\n * 엔진읎 없는 런타임에 싀윌멎 조용히 아묎 음도 없닀. 귞래서 판정을 값윌로 만듀고 시험한닀.\n */\n\n/** 자극을 싀을지 말지 — 귞늬고 왜. 부륎는 쪜은 읎 답만 볎고 움직읞닀. */\nexport type StimulusPlan =\n /** 싀얎띌 — 검사륌 통곌한 ì„ ì–ž. */\n | { action: 'load'; scenario: any }\n /**\n * 싣지 않는닀 — ê·ž 읎유.\n * · `none` — 원볞읎 자극을 선얞하지 않았닀(정상: 정적 구조만 반영하는 튞윈)\n * · `mirror` — 믞러닀. 왞부 싀묌읎 진싀읞 튞윈에 우늬가 자극을 만듀멎 귞것은 현싀읎 아니닀\n * · `no-engine` — 읎 런타임에 시나늬였 엔진읎 없닀(ꎀ잡 구동 컀널)\n * · `invalid` — 선얞읎 컀널 규앜을 얎ꞎ닀. **싣지 않고 말한닀**(닀음 틱에서 터지게 두지 않는닀)\n */\n | { action: 'skip'; reason: 'none' | 'observed' | 'no-engine' | 'invalid'; detail?: string }\n\n/**\n * 저장된 자극 선얞을 읜얎 **싀을지 판정한닀** — 컀널 검사Ʞ륌 귞대로 쓎닀(규칙을 두 벌로 만듀지 않는닀).\n *\n * `validate` 는 컀널의 `validateScenario` 륌 넘ꞎ닀(혞슀튞가 컀널 타입에 묶읎지 않게 핚수로 받는닀).\n * 검사Ʞ가 없윌멎 **싣지 않는닀**: 검사할 수 없는 선얞을 태우는 것읎 가장 비싌 선택읎닀(서버가 낎렀간\n * 읎력읎 있닀).\n */\nexport function planStimulus(\n config: any,\n runtime: { hasScenarioEngine: boolean; mode?: 'sim' | 'live' },\n validate?: (scenario: any) => { ok: boolean; errorCode?: string; errorParams?: any } | { ok: false; errorCode: string }\n): StimulusPlan {\n const scenario = config?.scenario\n if (!scenario || typeof scenario !== 'object') return { action: 'skip', reason: 'none' }\n /* ꎀ잡 튞윈을 뚌저 막는닀 — 「엔진읎 없닀」로 답하멎 읎유가 흐렀진닀(애쎈에 싀을 수 없는 튞윈읎닀). */\n if (runtime.mode === 'live') return { action: 'skip', reason: 'observed' }\n if (!runtime.hasScenarioEngine) return { action: 'skip', reason: 'no-engine' }\n if (!validate) return { action: 'skip', reason: 'invalid', detail: 'no validator available' }\n const v = validate(scenario)\n if (!v?.ok) return { action: 'skip', reason: 'invalid', detail: (v as any)?.errorCode ?? 'rejected' }\n return { action: 'load', scenario }\n}\n\n/**\n * 선얞을 원볞 섀정에 얹는닀(순수) — **Ʞ졎 섀정을 지우지 않는닀.**\n *\n * 얎댑터 섀정에는 접속 정볎가 핚께 ì‚°ë‹€. 자극을 넣윌멎서 ê·ž 옆을 덮윌멎 닀음 재동Ʞ가 원볞을 못 찟는닀.\n */\nexport function withStimulus(config: any, scenario: any): any {\n return { ...(config ?? {}), scenario }\n}\n"]}
1
+ {"version":3,"file":"declared-stimulus.js","sourceRoot":"","sources":["../../server/engine/declared-stimulus.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;AAsBH,oCAcC;AAOD,oCAEC;AA9BD;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,MAAW,EACX,OAA8D,EAC9D,QAAuH;IAEvH,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAA;IACjC,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;IACxF,+DAA+D;IAC/D,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;IAC1E,IAAI,CAAC,OAAO,CAAC,iBAAiB;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;IAC9E,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAA;IAC7F,MAAM,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC5B,IAAI,CAAC,CAAC,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAG,CAAS,EAAE,SAAS,IAAI,UAAU,EAAE,CAAA;IACrG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;AACrC,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY,CAAC,MAAW,EAAE,QAAa;IACrD,OAAO,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAA;AACxC,CAAC","sourcesContent":["/*\n * **자극은 원볞읎 선얞한닀** — 튞윈읎 아니띌.\n *\n * ── 묎엇읎 났나 (2026-08-19) ────────────────────────────────────────────────\n * 데몚의 자극(시나늬였)은 시드 윔드가 **메몚늬에만** 싀었닀: `runtime.scenario.load(...)`. 귞래서 튞윈을\n * 재Ʞ동하멎 자극읎 사띌지고, 구조만 서 있는 튞윈읎 낚는닀 — 작업 0·였더 0. 「삎아 있는 데몚」가\n * **첫 재Ʞ동까지만** 사는 것읎닀(였늘 서버륌 여러 번 띄우는 동안 싀제로 ê·ž 상태였닀).\n *\n * ── 왜 튞윈에 저장하지 않나 (ADR-0029 · plans/simulator-as-source.md §4) ────\n * 자극은 **원볞의 거동**읎닀: 묎엇읎 듀얎였고 묎슚 죌묞읎 나는지는 시뮬레읎터(원볞)가 정하는 사싀읎고,\n * 튞윈은 귞것을 반영한닀. 튞윈에 새 축을 만듀멎 ADR-0029 가 나쀑에 걷얎낎알 하는 표멎읎 하나 늘고\n * (ê·ž 계획서의 §2·§5 가 읎믞 ê·ž 부닎을 적얎 두었닀), 원볞에 두멎 ê·ž 계획의 **첫 조각 앞자늬**가 된닀:\n * 지ꞈ은 혞슀튞가 읜얎 컀널에 싣고, 나쀑에 `openLiveFeed` 뒀로 옮Ʞ멎 같은 선얞읎 귞대로 쓰읞닀.\n *\n * 귞래서 집은 `TwinReference.connectionConfig.scenario` — 얎댑터별 섀정 자늬(읎믞 `simple-json`)ë‹€.\n *\n * ── 판정을 순수 핚수로 (읎 파음) ────────────────────────────────────────────\n * 「읎 튞윈에 저장된 자극을 싀을 것읞가」에는 사람읎 틀늬Ʞ 쉬욎 갈늌읎 셋 있닀: 믞러에 싀윌멎 **현싀을\n * 였엌**시킀고, 잘못된 선얞을 싀윌멎 **닀음 틱에서 서버가 낎렀가고**(싀제로 ê·ž 읎력읎 있닀), 시나늬였\n * 엔진읎 없는 런타임에 싀윌멎 알늬지 않고 아묎 음도 없닀. 귞래서 판정을 값윌로 만듀고 시험한닀.\n */\n\n/** 자극을 싀을지 말지 — 귞늬고 왜. 부륎는 쪜은 읎 답만 볎고 움직읞닀. */\nexport type StimulusPlan =\n /** 싀얎띌 — 검사륌 통곌한 ì„ ì–ž. */\n | { action: 'load'; scenario: any }\n /**\n * 싣지 않는닀 — ê·ž 읎유.\n * · `none` — 원볞읎 자극을 선얞하지 않았닀(정상: 정적 구조만 반영하는 튞윈)\n * · `mirror` — 믞러닀. 왞부 싀묌읎 진싀읞 튞윈에 우늬가 자극을 만듀멎 귞것은 현싀읎 아니닀\n * · `no-engine` — 읎 런타임에 시나늬였 엔진읎 없닀(ꎀ잡 구동 컀널)\n * · `invalid` — 선얞읎 컀널 규앜을 얎ꞎ닀. **싣지 않고 말한닀**(닀음 틱에서 터지게 두지 않는닀)\n */\n | { action: 'skip'; reason: 'none' | 'observed' | 'no-engine' | 'invalid'; detail?: string }\n\n/**\n * 저장된 자극 선얞을 읜얎 **싀을지 판정한닀** — 컀널 검사Ʞ륌 귞대로 쓎닀(규칙을 두 벌로 만듀지 않는닀).\n *\n * `validate` 는 컀널의 `validateScenario` 륌 넘ꞎ닀(혞슀튞가 컀널 타입에 묶읎지 않게 핚수로 받는닀).\n * 검사Ʞ가 없윌멎 **싣지 않는닀**: 검사할 수 없는 선얞을 태우는 것읎 가장 비싌 선택읎닀(서버가 낎렀간\n * 읎력읎 있닀).\n */\nexport function planStimulus(\n config: any,\n runtime: { hasScenarioEngine: boolean; mode?: 'sim' | 'live' },\n validate?: (scenario: any) => { ok: boolean; errorCode?: string; errorParams?: any } | { ok: false; errorCode: string }\n): StimulusPlan {\n const scenario = config?.scenario\n if (!scenario || typeof scenario !== 'object') return { action: 'skip', reason: 'none' }\n /* ꎀ잡 튞윈을 뚌저 막는닀 — 「엔진읎 없닀」로 답하멎 읎유가 흐렀진닀(애쎈에 싀을 수 없는 튞윈읎닀). */\n if (runtime.mode === 'live') return { action: 'skip', reason: 'observed' }\n if (!runtime.hasScenarioEngine) return { action: 'skip', reason: 'no-engine' }\n if (!validate) return { action: 'skip', reason: 'invalid', detail: 'no validator available' }\n const v = validate(scenario)\n if (!v?.ok) return { action: 'skip', reason: 'invalid', detail: (v as any)?.errorCode ?? 'rejected' }\n return { action: 'load', scenario }\n}\n\n/**\n * 선얞을 원볞 섀정에 얹는닀(순수) — **Ʞ졎 섀정을 지우지 않는닀.**\n *\n * 얎댑터 섀정에는 접속 정볎가 핚께 ì‚°ë‹€. 자극을 넣윌멎서 ê·ž 옆을 덮윌멎 닀음 재동Ʞ가 원볞을 못 찟는닀.\n */\nexport function withStimulus(config: any, scenario: any): any {\n return { ...(config ?? {}), scenario }\n}\n"]}
@@ -16,7 +16,7 @@ exports.buildEnergyTopology = buildEnergyTopology;
16
16
  * 닚선도륌 귞늬멎 갖지 않은 공학적 충싀도륌 죌장하게 된닀. 여Ʞ서 귞늬는 것은 **튞윈읎 선얞한 ꎀ계**
17
17
  * (자늬의 계잵 + 섀비의 소속)와 **계량읎 싀제로 덮는 범위**뿐읎닀. 한계는 소비처가 화멎에 적는닀.
18
18
  *
19
- * ── 조용히 빠뜚늬지 않는닀 ─────────────────────────────────────────────────
19
+ * ── 알늬지 않고 빠뜚늬지 않는닀 ─────────────────────────────────────────────────
20
20
  * 자늬륌 몚륎는 섀비, 계량Ʞ가 없는 자늬, 계량읎 덮지 않는 몫은 **각자 자Ʞ 칞윌로** 나옚닀. 귞늌에서
21
21
  * 사띌지멎 사용자는 자Ʞ 현장읎 ë‹€ 귞렀졌닀고 믿는닀.
22
22
  */