@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
@@ -118,7 +118,7 @@ export interface RefTestResult {
118
118
  specId: string
119
119
  result: 'pass' | 'fail'
120
120
  at?: string
121
- /** 없으면 무기한 — 짐작으로 기한을 만들면 멀쩡한 자격자가 조용히 사라진다. */
121
+ /** 없으면 무기한 — 짐작으로 기한을 만들면 멀쩡한 자격자가 오류 없이 사라진다. */
122
122
  expiresAt?: string
123
123
  }
124
124
 
@@ -177,7 +177,7 @@ export interface RefEquipment {
177
177
  *
178
178
  * 없으면 **폐기한 것이 영구히 살아 있다**: 배정 대상에 남고, 가용 수에 들어가고, 화면에 뜬다.
179
179
  * 도입 예정인 것은 반대로 오늘부터 있는 것처럼 보인다. 기간 밖이면 커널이 그 시각의 모델에서
180
- * 빼고 **이유를 달아 남긴다**(`effectivity: 'not-yet' | 'expired'`) — 조용히 지우지 않는다.
180
+ * 빼고 **이유를 달아 남긴다**(`effectivity: 'not-yet' | 'expired'`) — 알리지 않고 지우지 않는다.
181
181
  */
182
182
  effectiveStart?: string
183
183
  effectiveEnd?: string
@@ -226,7 +226,7 @@ export interface RefOperationVariability {
226
226
  *
227
227
  * **이것이 없으면 시뮬레이션의 시간은 우리가 코드에 고정한 상수다.** 원 시스템(또는 가상 레퍼런스)이
228
228
  * 공정별 소요·변동·수율을 말해 줘야 예측이 그 현장의 예측이 된다. 주지 않으면 커널 기본값으로
229
- * 굴러가고, **기본값을 썼다는 사실은 커널 `specCoverage()` 가 밝힌다**(조용히 넘어가지 않는다).
229
+ * 굴러가고, **기본값을 썼다는 사실은 커널 `specCoverage()` 가 밝힌다**(알리지 않고 넘어가지 않는다).
230
230
  */
231
231
  export interface RefOperation {
232
232
  /** 작업 종류 키 — 커널 `FlowTask.kind` 와 같은 값이어야 명세가 그 작업에 붙는다. */
@@ -366,7 +366,7 @@ export type MasterOrigin =
366
366
  /**
367
367
  * 템플릿 + 노브로 합성했다 — 다시 읽기 = 같은 노브로 다시 짓는다(합성은 결정적이다).
368
368
  *
369
- * `spaceId` 는 **만들 때 고른 현장**이다(합쳐 넣기). 기억하지 않으면 다시 읽을 때 트윈이 조용히 자기
369
+ * `spaceId` 는 **만들 때 고른 현장**이다(합쳐 넣기). 기억하지 않으면 다시 읽을 때 트윈이 알리지 않고 자기
370
370
  * 현장을 떠난다 — 템플릿이 낸 기본 공간으로 돌아가기 때문이다. 그러면 그 현장의 값(요금 등)도 함께
371
371
  * 잃는다(2026-08-18 실측: 한 현장에 합쳐 둔 EMS 트윈 여덟이 재동기 뒤 각자 공간으로 흩어졌다).
372
372
  */
@@ -457,7 +457,7 @@ export interface ReferenceMaster {
457
457
  * 여기에 담아 보낸다 — 그러면 `masterToTwin` 의 경고와 한 줄기로 합쳐져 화면까지 간다.
458
458
  *
459
459
  * 이 자리가 없던 동안 커넥터는 할 말이 있어도 **말할 곳이 없었다.** 그래서 도크를 랙으로 바꿔
460
- * 놓고도 조용히 성공했다. 옮기는 사람만 아는 사실은 옮기는 자리에서 실어야 한다.
460
+ * 놓고도 알리지 않고 성공했다. 옮기는 사람만 아는 사실은 옮기는 자리에서 실어야 한다.
461
461
  */
462
462
  warnings?: IngestWarning[]
463
463
  /**
@@ -498,7 +498,7 @@ export interface IngestedTwin {
498
498
  * 호스트가 절대 구간(`StartDateTime`/`FinishDateTime`)을 계산해 넣는 것이고, 그때 이 함수는 사라진다.
499
499
  *
500
500
  * 모르는 이름에는 **0 을 답하지 않는다**(`undefined`) — 0 은 "UTC 라고 선언했다" 는 뜻이고, 모르는 것을
501
- * 그렇게 바꾸면 판정이 조용히 틀린다.
501
+ * 그렇게 바꾸면 판정이 오류 없이 틀린 값을 낸다.
502
502
  */
503
503
  export function utcOffsetOf(timezone?: string, at: Date = new Date()): number | undefined {
504
504
  if (!timezone) return undefined
@@ -553,7 +553,7 @@ export interface IngestWarning {
553
553
  * 형상은 **시각별 비율**이라, 시간대가 없으면 현장 정오가 아니라 UTC 정오에 피크가 선다(KST 현장이면
554
554
  * 밤 9시). 값이 그럴듯하게 나오므로 아무도 알아채지 못한다.
555
555
  *
556
- * 그래서 시간대를 **지어내지 않고**(서버 로컬이나 임의 기본값을 넣으면 그 트윈의 모든 시각 판정이 조용히
556
+ * 그래서 시간대를 **지어내지 않고**(서버 로컬이나 임의 기본값을 넣으면 그 트윈의 모든 시각 판정이 알리지 않고
557
557
  * 그 가정 위에 선다) 대신 **그 조합을 말한다** — 공간에 시간대를 선언하면 사라지는 경고다.
558
558
  */
559
559
  export const generationWithoutTimeZone = (spaceId: string, equipmentId: string): IngestWarning => ({
@@ -576,9 +576,20 @@ export const generationWithoutTimeZone = (spaceId: string, equipmentId: string):
576
576
  export const unknownLocationType = (system: string, type: string, id: string): IngestWarning => ({
577
577
  code: 'unknown-location-type',
578
578
  params: { system, type, id },
579
+ /*
580
+ * ── 무슨 일이 벌어지는지 말한다 (2026-08-25) ────────────────────────────────
581
+ * 예전 문장은 「흐름에 참여하지 못할 수 있다」였다. 물건이 흐르는 도메인에서는 맞는 말인데,
582
+ * 에너지 트윈에는 흐름이 없어서 그 문장이 아무것도 알려 주지 않았다(실제로 태양광 발전소를
583
+ * 붙이면서 이 경고를 받은 사람이 「이 경고가 뜻이 있는가」를 되물었다).
584
+ *
585
+ * 종류를 모르면 실제로 일어나는 일은 하나다: **그 자리에 능력이 붙지 않는다.** 능력이 없으면
586
+ * 상태 필드도 없고, 롤업에도 들어가지 않고, 저작면 팔레트에도 서지 않는다. 도메인을 가리지 않고
587
+ * 참인 문장이므로 이것을 적는다.
588
+ */
579
589
  message:
580
590
  `"${type}" is declared nowhere for ${system} (${id}) — neither in the master's own locationTypes nor in the built-in ` +
581
- `catalog, so the kernel may not include this location in the flow`
591
+ `catalog. A location whose type is unknown gets no capabilities, so it carries no state, joins no rollup, ` +
592
+ `and (in domains that move things) may be left out of the flow.`
582
593
  })
583
594
 
584
595
  /**
@@ -595,7 +606,7 @@ export function declaredLocationTypes(productionSpec: unknown): string[] | undef
595
606
  return keys.length ? keys : undefined
596
607
  }
597
608
 
598
- /** 시간대 문자열을 못 읽었다 — 시각 해석이 UTC 로 떨어진다(조용히 현지 시각으로 가정하지 않는다). */
609
+ /** 시간대 문자열을 못 읽었다 — 시각 해석이 UTC 로 떨어진다(알리지 않고 현지 시각으로 가정하지 않는다). */
599
610
  export const unknownTimezone = (timezone: string): IngestWarning => ({
600
611
  code: 'unknown-timezone',
601
612
  params: { timezone },
@@ -620,7 +631,7 @@ export const noViewableRepresentation = (): IngestWarning => ({
620
631
  *
621
632
  * 예전에는 이런 참조가 model JSON 안의 맨 문자열이라 화면만 경고할 수 있었고, 다른 경로로 들어온
622
633
  * 데이터는 아무도 안 봤다. 이제 행으로 풀면서 **인제스트가 직접 안다** — 그러니 인제스트가 말한다.
623
- * 막지는 않는다(트윈은 model 로 이미 동작한다). 다만 조용히 넘기지 않는다.
634
+ * 막지는 않는다(트윈은 model 로 이미 동작한다). 다만 알리지 않고 넘기지 않는다.
624
635
  */
625
636
  export const unresolvedReference = (field: string, ref: string): IngestWarning => ({
626
637
  code: 'unresolved-reference',
@@ -642,7 +653,7 @@ export const projectionFailed = (reason: string): IngestWarning => ({
642
653
  * **동작 중에 공장을 전환했다** — 미러는 멈추지 않으므로, 무엇이 사라졌는지 여기서 말한다.
643
654
  *
644
655
  * 멈췄다 세우는 구조 전환이라면 사용자가 "다시 세웠다" 는 것을 안다. 미러는 그 마디가 없어서
645
- * 자리 하나·설비 한 대가 조용히 없어질 수 있다 — 자리가 수천인 현장에서 화면의 수를 세어
656
+ * 자리 하나·설비 한 대가 알리지 않고 없어질 수 있다 — 자리가 수천인 현장에서 화면의 수를 세어
646
657
  * 눈치채기를 기대할 수는 없다. 늘어난 것도 함께 말한다(무엇이 반영되었나가 곧 인제스트의 답이다).
647
658
  */
648
659
  export const structureAdopted = (rev: number, shift: { locationsAdded: number; locationsDropped: number; equipmentDropped: number; personsDropped: number; assetsDropped: number }): IngestWarning => ({
@@ -659,7 +670,7 @@ export const structureAdopted = (rev: number, shift: { locationsAdded: number; l
659
670
  *
660
671
  * 예: Oracle WMS 가 우리 표에 없는 `locn_type` 을 주면 그 자리는 `storage` 가 된다 — 도크가 랙으로
661
672
  * 모델링되는 것이다. 인제스트를 통째로 실패시킬 일은 아니지만(로케이션 하나 때문에 현장 전체가
662
- * 안 들어오는 편이 더 나쁘다), **조용히 넘어가면 안 된다.** 트윈이 실물과 다르게 생겼는데
673
+ * 안 들어오는 편이 더 나쁘다), **알리지 않고 넘어가면 안 된다.** 트윈이 실물과 다르게 생겼는데
663
674
  * 아무도 그 사실을 모른 채 그 위에서 흐름을 논하게 된다.
664
675
  *
665
676
  * 값을 나열하는 이유: "3건" 만으로는 커넥터 매핑에 무엇을 더해야 하는지 알 수 없다.
@@ -678,7 +689,7 @@ export const describeWarnings = (warnings: readonly IngestWarning[]): string =>
678
689
  /**
679
690
  * 서버가 기본값으로 채운 노브들 — 사용자가 준 적 없는 값으로 트윈이 만들어졌음을 알린다.
680
691
  *
681
- * 조용히 채우면 나중에 "왜 이 수치인가" 를 아무도 답할 수 없다. 막을 일은 아니다(기본값은 템플릿이
692
+ * 알리지 않고 채우면 나중에 "왜 이 수치인가" 를 아무도 답할 수 없다. 막을 일은 아니다(기본값은 템플릿이
682
693
  * 확신을 갖고 선언한 값이다) — 다만 밝힌다.
683
694
  */
684
695
  export const knobDefaultsFilled = (keys: readonly string[]): IngestWarning => ({
@@ -688,7 +699,7 @@ export const knobDefaultsFilled = (keys: readonly string[]): IngestWarning => ({
688
699
  })
689
700
 
690
701
  /**
691
- * 이 현장의 설비를 노브 값으로 채웠다 — **조용히 채우지 않는다.**
702
+ * 이 현장의 설비를 노브 값으로 채웠다 — **알리지 않고 채우지 않는다.**
692
703
  *
693
704
  * 에너지 트윈의 부하를 이웃 설비 id 로 선언할 때 쓴다. 몇 개를 가져왔는지 말해 주지 않으면, 사용자는
694
705
  * 자기가 고르지 않은 설비들이 부하로 잡힌 것을 나중에 화면에서야 알게 된다.
@@ -722,7 +733,7 @@ export function masterToTwin(master: ReferenceMaster, catalog?: any): IngestedTw
722
733
  /*
723
734
  * **속성도 통과시킨다** — 설비와 같은 규율(손대지 않고 나른다). 여기가 없으면 자리에 실은 값이
724
735
  * 커널에 닿지 않는다: 에너지의 계약전력(`contract.kW`)이 그 경로이고, 통과하지 않으면 커널이
725
- * 계약을 모르는 채로 서서 **판정을 아예 하지 않는다**(오류 없이 조용히).
736
+ * 계약을 모르는 채로 서서 **판정을 아예 하지 않는다**(오류 없이 알리지 않고).
726
737
  */
727
738
  return { id: l.id, type: l.type, ...(l.name ? { name: l.name } : {}), ...(l.description ? { description: l.description } : {}), capacity: l.capacity ?? 0, ...(l.parallelism !== undefined ? { parallelism: l.parallelism } : {}), ...(l.level ? { level: l.level } : {}), ...(l.properties?.length ? { properties: l.properties } : {}), parentId: l.parentId, ...(l.upstreamId ? { upstreamId: l.upstreamId } : {}), gs1Id: l.gs1Id }
728
739
  })
@@ -831,11 +842,22 @@ export function masterToTwin(master: ReferenceMaster, catalog?: any): IngestedTw
831
842
  // 표현을 안 줘도 geo 만 있으면 위성 지도로 착지. (area 폴리곤 물질화는 좌표 투영 필요 → space #3.)
832
843
  const geo = master.space.geo
833
844
  const givenReps = master.space.representations ?? []
845
+ /*
846
+ * ── 이름을 지어내지 않는다 (2026-08-26) ────────────────────────────────────
847
+ * 여기가 합성한 표현에 `name: '위성 지도'` 를 넣고 있었다. 이 층은 언어 중립이어야 하는데 한국어가
848
+ * 그대로 저장됐다.
849
+ *
850
+ * 낱말 열쇠(`twin.representation.map` 같은 것)를 넣는 길도 있는데 택하지 않았다. **표현의 이름은
851
+ * 사람이 바꿀 수 있는 값**이고, 바꿀 수 있는 값 안에 열쇠가 들어 있으면 사람이 한 번 고치는 순간
852
+ * 그 자리만 열쇠가 아니게 되어 규칙이 둘이 된다.
853
+ *
854
+ * 그래서 이름을 넣지 않는다. 화면이 종류(`map`)로 부르고, 사람이 붙이면 그때부터 그 이름이다.
855
+ */
834
856
  const representations =
835
857
  givenReps.length > 0
836
858
  ? givenReps
837
859
  : geo
838
- ? [{ id: 'r-map', type: 'map', name: '위성 지도', primary: true, center: { lat: geo.lat, lon: geo.lon }, zoom: 17 }]
860
+ ? [{ id: 'r-map', type: 'map', primary: true, center: { lat: geo.lat, lon: geo.lon }, zoom: 17 }]
839
861
  : []
840
862
  if (representations.length === 0) {
841
863
  warnings.push(noViewableRepresentation())
@@ -853,7 +875,7 @@ export function masterToTwin(master: ReferenceMaster, catalog?: any): IngestedTw
853
875
  * 다시 읽을 사이트를 고른다 — **기억해 둔 사이트 하나만**.
854
876
  *
855
877
  * 못 찾으면 **첫 사이트로 때우지 않는다**: 다른 현장의 구조를 이 트윈에 덮어쓰는 일이고, 그것은 오류가
856
- * 아니라 **조용히 틀린 공장**으로 나타난다. 기억이 없는 옛 트윈은 `undefined` 를 돌려주고, 부르는 쪽이
878
+ * 아니라 **오류 없이 틀린 공장**으로 나타난다. 기억이 없는 옛 트윈은 `undefined` 를 돌려주고, 부르는 쪽이
857
879
  * 마스터의 정체(`source` = 인스턴스 id)로 찾는 길을 택한다.
858
880
  */
859
881
  export function pickOriginSite<T extends { siteId: string }>(
@@ -244,7 +244,7 @@ export class TwinReferenceResolver {
244
244
  /*
245
245
  * **어느 현장의 트윈이었나를 지킨다** — 다시 읽기는 구조만 새로 그리는 일이고, 현장 소속은 그때
246
246
  * 사람이 고른 것이다. 기억이 없는 옛 트윈은 **지금 있는 현장**을 그대로 쓴다(빈손으로 두면 템플릿
247
- * 기본 공간으로 옮겨 간다 — 조용히 현장을 떠나고 그 현장의 값도 잃는다).
247
+ * 기본 공간으로 옮겨 간다 — 알리지 않고 현장을 떠나고 그 현장의 값도 잃는다).
248
248
  */
249
249
  const keepSpace = origin.spaceId || inst.spaceId
250
250
  /* 다시 읽기는 **구조만** 새로 그린다 — 재기동 정책은 그 트윈의 선언이므로 그대로 지킨다. */
@@ -304,7 +304,7 @@ export class TwinReferenceResolver {
304
304
  const tpl = getTemplate(origin.templateId)
305
305
  if (!tpl) throw new Error(`unknown template: ${origin.templateId} — this twin cannot be rebuilt`)
306
306
  /* 저장해 둔 노브 그대로 다시 짓는다. 기본값을 다시 입히지 않는다 — 그 사이 템플릿의 기본값이
307
- 바뀌었다면, 사용자가 고르지 않은 값이 조용히 현장을 바꾸게 된다. */
307
+ 바뀌었다면, 사용자가 고르지 않은 값이 알리지 않고 현장을 바꾸게 된다. */
308
308
  const { master } = tpl.build(origin.params ?? {})
309
309
  master.origin = origin
310
310
  return master
@@ -333,7 +333,7 @@ export class TwinReferenceResolver {
333
333
  *
334
334
  * 이제 ① 기억해 둔 사이트로 곧장 간다(`origin.siteId`) ② 기억이 없는 옛 트윈은 사이트를 살펴
335
335
  * **마스터의 정체(=이 인스턴스 id)** 와 견준다. 어느 쪽도 못 찾으면 **첫 사이트로 때우지 않는다** —
336
- * 다른 현장의 구조를 이 트윈에 덮는 것은 오류가 아니라 조용히 틀린 공장으로 나타난다.
336
+ * 다른 현장의 구조를 이 트윈에 덮는 것은 오류가 아니라 오류 없이 틀린 공장으로 나타난다.
337
337
  */
338
338
  const picked = pickOriginSite(sites, origin)
339
339
  if (picked.site) return { ...(await adapter.fetchMaster(cfg, picked.site, onStep)), origin }
@@ -379,8 +379,8 @@ export class TwinReferenceResolver {
379
379
  /*
380
380
  * **빠진 노브를 서버가 채운다.** 기본값을 아는 곳은 노브 스키마(계약)인데 그것을 적용하는 곳이
381
381
  * 위자드뿐이었다 — 그래서 화면을 거치지 않는 호출자(AI·스크립트·API)가 파라미터를 일부만 주면
382
- * 템플릿 안에서 발생률이 0 이 되고 **아무것도 하지 않는 트윈**이 조용히 만들어졌다.
383
- * 채운 노브 이름은 경고로 함께 돌려준다 — 조용히 채우는 것도 조용히 비우는 것만큼 위험하다.
382
+ * 템플릿 안에서 발생률이 0 이 되고 **아무것도 하지 않는 트윈**이 알리지 않고 만들어졌다.
383
+ * 채운 노브 이름은 경고로 함께 돌려준다 — 알리지 않고 채우는 것도 알리지 않고 비우는 것만큼 위험하다.
384
384
  */
385
385
  const filled = filledKnobKeys(tpl.knobs, params)
386
386
  const effective = applyKnobDefaults(tpl.knobs, params)
@@ -400,7 +400,7 @@ export class TwinReferenceResolver {
400
400
  /* 고른 현장도 남긴다 — 없으면 다시 읽기가 트윈을 템플릿 기본 공간으로 옮겨 버린다(현장 값도 잃는다). */
401
401
  master.origin = { kind: 'template', templateId, params: effective, ...(spaceId ? { spaceId } : {}) }
402
402
  /* 공간 선택은 템플릿을 거치지 않는다 — 템플릿마다 이 노브를 알고 있어야 한다면 새 템플릿이
403
- 조용히 무시하게 된다. 합성된 마스터에 한 곳에서 얹는다(레퍼런스 인제스트와 같은 경로). */
403
+ 알리지 않고 무시하게 된다. 합성된 마스터에 한 곳에서 얹는다(레퍼런스 인제스트와 같은 경로). */
404
404
  const res = await TwinEngine.ingestMaster(
405
405
  domainId,
406
406
  master,
@@ -638,7 +638,7 @@ export class TwinReferenceResolver {
638
638
  @Query(returns => ScalarObject, { description: 'Discover sites/factories exposed by a reference. Returns { sites, error? } — an empty list with no error means the system genuinely has none, which is different from a failure.' })
639
639
  async discoverReferenceSites(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any> {
640
640
  /*
641
- * **"못 찾았다" 와 "없다" 를 구분한다.** 예전에는 넷을 빈 배열 하나로 접었고(레퍼런스 없음·어댑터
641
+ * **"못 찾았다" 와 "없다" 를 구분한다.** 예전에는 넷을 빈 배열 하나로 합쳤고(레퍼런스 없음·어댑터
642
642
  * 미상·조회 실패·정말 0건), 화면은 그 모두를 "사이트를 찾지 못했습니다" 라고만 말했다. 실 시스템
643
643
  * 연결에서 가장 자주 막히는 자리인데 자격이 틀렸는지 주소가 틀렸는지 알 수 없었다.
644
644
  * 판정과 문장 형태는 `discovery-result`(순수)가 갖는다.
@@ -650,7 +650,7 @@ export class TwinReferenceResolver {
650
650
  try {
651
651
  /*
652
652
  * **기다려도 답이 없으면 사유를 준다.** 어댑터 계약에 시간 제한이 없어서, 주소가 틀린 엔드포인트는
653
- * 화면을 무한히 돌게 만들었다 — 무한히 도는 화면은 조용한 실패의 다른 얼굴이다.
653
+ * 화면을 무한히 돌게 만들었다 — 무한히 도는 화면은 들어온 것이 없는 실패의 다른 얼굴이다.
654
654
  * 상한은 여기서 정한다(어댑터마다 다르게 두면 사용자가 어느 것을 기다리는지 알 수 없다).
655
655
  */
656
656
  const sites = await withTimeout(adapter.discoverSites(ref.connectionConfig ?? {}), DISCOVER_TIMEOUT_MS)
@@ -672,7 +672,7 @@ export class TwinReferenceResolver {
672
672
  * 데이터로는 가능한 일이 저작으로는 불가능한, `ingest-space` 가 이미 지적한 그 비대칭이다.
673
673
  *
674
674
  * 판정은 그 순수 모듈이 갖는다: 없는 공간은 거절(`resolveIngestSpace`), 사이트 여럿을 한 공간에
675
- * 넣는 것도 거절(`refuseImportSpace`) — 서로 다른 현장이 조용히 합쳐지는 것을 막는다.
675
+ * 넣는 것도 거절(`refuseImportSpace`) — 서로 다른 현장이 알리지 않고 합쳐지는 것을 막는다.
676
676
  */
677
677
  @Directive('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
678
678
  @Mutation(returns => ScalarObject, {
@@ -762,7 +762,7 @@ export class TwinReferenceResolver {
762
762
  /*
763
763
  * 정책은 **선언이거나 의도에서 곧바로 따라오는 것**이다: `live=true` 는 미러를 띄우겠다는 뜻이고
764
764
  * 미러는 정의상 `resync` 다(외부가 진실이므로 우리 과거를 이어 붙이지 않는다). 시뮬로 띄우려면
765
- * 스스로 선언해야 한다 — 그 자리에서 우리가 고르면 재기동마다 이력을 지우는 트윈이 조용히 생긴다.
765
+ * 스스로 선언해야 한다 — 그 자리에서 우리가 고르면 재기동마다 이력을 지우는 트윈이 알리지 않고 생긴다.
766
766
  */
767
767
  assessments[site.siteId] = assessMaster(master, site.siteId)
768
768
  const policy = readRestartPolicy(restartPolicy ?? (live ? 'resync' : undefined), `importTwinReference("${source}")`)
@@ -73,7 +73,7 @@ export class TwinReference {
73
73
  /**
74
74
  * 마지막 동기에서 **못 옮긴 값의 수**. `null` = 세지 않았다(0 과 다르다).
75
75
  *
76
- * 세지 않은 구조 인제스트는 도크를 랙으로 바꿔 놓고도 조용히 성공한다. 그 사실을 사후에 물을 수
76
+ * 세지 않은 구조 인제스트는 도크를 랙으로 바꿔 놓고도 성공이라 답하면서 아무 일도 하지 않는다. 그 사실을 사후에 물을 수
77
77
  * 있어야 단계 판정이 「구조는 됐다」를 말할 수 있다 — 없는 동안 판정은 늘 `unmeasured` 였다.
78
78
  * 기본값을 두지 않는다: 0 을 기본으로 깔면 「경고 없었다」와 「세지 않았다」가 같아진다.
79
79
  */
@@ -91,10 +91,10 @@ export class TwinReference {
91
91
  *
92
92
  * 커널이 그 갈림을 이미 적어 두었다(§`hydrateContinuity`): 「원천이 애초에 다시 말해 주지 않는 축」은
93
93
  * 재기동 연속성으로 이어받는다. 「우리가 어디까지 읽었나」가 정확히 그 성질이므로 **어댑터의 사물함이
94
- * 아니라 이 층**에 있다 — 원본이 늘 때마다 저장 기제가 늘고 그중 하나가 조용히 다르게 동작하지 않게.
94
+ * 아니라 이 층**에 있다 — 원본이 늘 때마다 저장 기제가 늘고 그중 하나가 알리지 않고 다르게 동작하지 않게.
95
95
  *
96
96
  * ── 왜 캐시가 아니라 표인가 ────────────────────────────────────────────────
97
- * 만료되면 창이 다시 미끄러지고, 그 손실은 오류 없이 조용하다. 스냅샷 체크포인트와 성질이 다르다
97
+ * 만료되면 창이 다시 미끄러지고, 그 손실은 오류 없이 들어온 것이 없다. 스냅샷 체크포인트와 성질이 다르다
98
98
  * (그쪽은 잃어도 원천이 정정해 준다 — 이 값은 **잃으면 원천에 묻지 않게 된다**).
99
99
  *
100
100
  * 모양은 `{ streams: { [흐름]: { since?, seen[] } }, firstAttachedAt? }` 다. **흐름 이름은 어댑터가
@@ -43,7 +43,7 @@ export class TwinAttentionQuery {
43
43
 
44
44
  /**
45
45
  * 잘랐다면 **몇 건을 잘랐는지**와 자리 색 요약까지 — 목록만 주면 화면이 "N건 더" 를 말할 수 없다.
46
- * 자리별 최고 심각도는 **전량을 근거로** 접는다(상위 N 으로 접으면 20위 밖 신호를 가진 자리가 색을 잃는다).
46
+ * 자리별 최고 심각도는 **전량을 근거로** 계산한다(상위 N 으로 줄이면 20위 밖 신호를 가진 자리가 색을 잃는다).
47
47
  */
48
48
  @Query(returns => ScalarObject, {
49
49
  description: 'Attention signals for a space (all its lenses) or one twin, with the total count and the per-location highest severity folded from all of them.'
@@ -21,7 +21,7 @@ export type CommandAuditInput = {
21
21
  * **원본(어댑터)이 준 답** — 허락과 일어남 사이에 끼어 있는 것을 같은 기록에 닫는다 (ADR-0029 §1 결정 C).
22
22
  *
23
23
  * ── 왜 이 칸이 필요한가 ──────────────────────────────────────────────────
24
- * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 조용히 실패하면 원장에는 승인만
24
+ * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 오류 없이 실패하면 원장에는 승인만
25
25
  * 남는다. 그래서 어댑터의 답을 **같은 행**에 되적는다.
26
26
  *
27
27
  * 셋을 구별한다:
@@ -103,7 +103,7 @@ export class TwinAuditEvent {
103
103
  * **원본이 그래서 어떻게 했나** — 허락과 일어남 사이에 끼어 있는 것을 같은 행에 닫는다
104
104
  * (ADR-0029 §1 결정 C, 2026-08-19).
105
105
  *
106
- * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 조용히 실패하면 원장에는 승인만
106
+ * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 오류 없이 실패하면 원장에는 승인만
107
107
  * 남는다. 그래서 어댑터의 답을 되적는다.
108
108
  *
109
109
  * · 비어 있음 — **원본에 묻지 않았다**(커널이 받은 명령이다). 「모른다」와 다르다.
@@ -142,7 +142,7 @@ export class TwinAuditEvent {
142
142
 
143
143
  /**
144
144
  * 명령 인자 — **원형 그대로.** 무엇에 대한 명령이었는지가 감사의 핵심이라 요약하지 않는다.
145
- * 지나치게 크면 자르되 `argsTruncated` 로 잘랐다는 사실을 남긴다(조용히 버리지 않는다).
145
+ * 지나치게 크면 자르되 `argsTruncated` 로 잘랐다는 사실을 남긴다(알리지 않고 버리지 않는다).
146
146
  */
147
147
  @Column({ type: 'simple-json', nullable: true })
148
148
  @Field(type => ScalarObject, { nullable: true, description: 'Command arguments as given.' })
@@ -46,7 +46,7 @@ export class TwinAuditQuery {
46
46
  ...(params ?? ({} as ListParam)),
47
47
  /* 기본 정렬 — 최근 것부터. 감사는 "요즘" 에서 시작한다. */
48
48
  sortings: params?.sortings?.length ? params.sortings : [{ name: 'eventTime', desc: true }],
49
- /* 시각 필터는 날짜로 옮겨서 넘긴다 — 문자열 그대로면 조용히 0건이 된다(저널과 같은 이유). */
49
+ /* 시각 필터는 날짜로 옮겨서 넘긴다 — 문자열 그대로면 알리지 않고 0건이 된다(저널과 같은 이유). */
50
50
  filters: (params?.filters ?? []).map(f => (f.name === 'eventTime' ? { ...f, value: toDateValue(f.value) } : f))
51
51
  }
52
52
 
@@ -50,7 +50,7 @@ export class TwinControlMutation {
50
50
  * 증명할 수 있다. 커널이 거절한 것도 남긴다 — 무엇을 시도했는지가 감사의 절반이다.
51
51
  *
52
52
  * 기록이 실패해도 커맨드 결과는 그대로 돌려준다. 감사가 본업을 막으면 안 되지만, 실패를 삼키지도
53
- * 않는다(로그에 남긴다) — 조용히 안 남으면 나중에 "기록이 없다" 와 "일이 없었다" 를 구분 못 한다.
53
+ * 않는다(로그에 남긴다) — 알리지 않고 안 남으면 나중에 "기록이 없다" 와 "일이 없었다" 를 구분 못 한다.
54
54
  */
55
55
  try {
56
56
  const audit = buildCommandAudit({ command: cmdWithOrigin, ack, actor: context.state.user, at: new Date() })
@@ -29,7 +29,7 @@ export interface TwinEventKeys {
29
29
 
30
30
  /*
31
31
  * 컬럼 길이 상한. GS1 식별자(EPC URN·GDTI·SGLN)는 규격상 이보다 훨씬 짧다.
32
- * 넘치는 값이 오면 **조용히 자르지 않고** 경고를 남긴다 — 색인이 원본과 다르면 검색 결과가 거짓이 되는데,
32
+ * 넘치는 값이 오면 **알리지 않고 자르지 않고** 경고를 남긴다 — 색인이 원본과 다르면 검색 결과가 거짓이 되는데,
33
33
  * 그 사실이 어디에도 안 남으면 아무도 모른다.
34
34
  */
35
35
  const MAX_KEY = 255
@@ -65,10 +65,30 @@ export function epcOf(envelope: any): string | undefined {
65
65
  return d.epcList?.[0] ?? d.parentID ?? d.quantityList?.[0]?.epcClass ?? undefined
66
66
  }
67
67
 
68
- /** 거래 식별자(PO/SO) — EPCIS bizTransactionList 우선, 운영 델타는 `order`. */
68
+ /**
69
+ * 오더 식별자 — 운영 델타의 `orderId` 우선, EPCIS 는 `bizTransactionList`.
70
+ *
71
+ * ── 실측 (2026-08-24) — 이 컬럼이 **전부 비어 있었다** ──────────────────────
72
+ * 여기가 찾던 이름이 `d.order` 였다. 그런데 커널이 내는 이름은 **`orderId`** 다
73
+ * (`OrderStatusDelta.orderId` · `TaskStatusDelta.orderId`). `d.order` 를 내는 코드는 커널에 **한 곳도
74
+ * 없다** — 죽은 가지였다. 그래서 운영 델타는 이 컬럼을 한 번도 채우지 못했다.
75
+ *
76
+ * order.status 29,403,565 행 — order_id 비어 있음 29,403,565 (100%)
77
+ * task.status 191,175 행 — 비어 있음 191,175 (100%)
78
+ *
79
+ * 그 결과 색인 `ix_twin_event_4` 가 **자기 주석이 적어 둔 용도**(「이 오더가 어디까지 갔나」)로 쓸 수
80
+ * 없었다. 화면은 오더를 눌러도 「연결된 이벤트가 없습니다」를 냈고, 그 답은 질의 결과로는 정직했다 —
81
+ * 시점을 어디로 옮겨도 0 이었다.
82
+ *
83
+ * 순서가 중요하다: 운영 델타가 먼저다. EPCIS 의 `bizTransactionList` 는 **거래**(PO/SO)이고 오더와
84
+ * 같은 것이 아닐 수 있으므로, 오더를 스스로 말하는 사건은 그 말을 그대로 쓴다.
85
+ *
86
+ * **과거 행은 채워지지 않는다**(사용자 결정 2026-08-24, `moverId` 때와 같은 방식). 앞으로 들어오는
87
+ * 사건부터 조회된다.
88
+ */
69
89
  export function orderOf(envelope: any): string | undefined {
70
90
  const d = envelope?.data ?? envelope ?? {}
71
- return d.bizTransactionList?.[0]?.bizTransaction ?? d.order ?? undefined
91
+ return d.orderId ?? d.bizTransactionList?.[0]?.bizTransaction ?? undefined
72
92
  }
73
93
 
74
94
  /**
@@ -89,14 +109,26 @@ export function locationOf(envelope: any): string | undefined {
89
109
  */
90
110
  export function equipmentIdOf(envelope: any): string | undefined {
91
111
  const d = envelope?.data ?? envelope ?? {}
92
- return d.moverId ?? undefined
112
+ /*
113
+ * ── 실측 (2026-08-24) — 두 갈래를 놓치고 있었다 ────────────────────────────
114
+ * 위 주석이 `task.status` 를 출처로 **적어 두었는데** 이 함수는 `d.moverId` 만 봤다. 작업이 자원을
115
+ * 가리키는 이름은 `resourceRef` 다(`TaskStatusDelta.resourceRef`) — 그래서 작업 191,175 행 전부
116
+ * 이 컬럼이 비었고, 「이 지게차가 오늘 무엇을 했나」에서 **작업이 통째로 빠졌다.**
117
+ *
118
+ * 그리고 에너지 사건은 `equipmentId` 를 쓴다(어휘가 `movers`→`equipment` 로 개명된 뒤에 생긴
119
+ * 채널이다). 실측 `energy.equipment` 31,079 행 전부 비어 있었다 — 「이 설비가 얼마를 먹었나」를
120
+ * 설비 축으로 물을 수 없었다.
121
+ *
122
+ * 셋을 함께 본다. 개명 세대가 섞여 있는 것은 저널의 성질이고, 읽는 쪽이 그것을 흡수한다.
123
+ */
124
+ return d.moverId ?? d.resourceRef ?? d.equipmentId ?? undefined
93
125
  }
94
126
 
95
127
  /**
96
128
  * EPCIS 행위 — `ADD`·`OBSERVE`·`DELETE`. 세 값이 아니면 `undefined`(원천의 잡값을 색인에 넣지 않는다).
97
129
  *
98
130
  * 이 키는 검색 축이 아니라 **판별식**이다: 되풀어 읽는 스냅샷은 원리적으로 `DELETE` 를 못 낸다.
99
- * 그래서 「이 트윈이 반출을 한 번이라도 접었는가」가 진짜 delta 피드의 증거인데, payload 안에 있는
131
+ * 그래서 「이 트윈이 반출을 한 번이라도 계산했는가」가 진짜 delta 피드의 증거인데, payload 안에 있는
100
132
  * 동안에는 5개 드라이버 어디에서도 그 질문을 할 수 없었다. 운영 델타에는 행위가 없다 — 비운다.
101
133
  */
102
134
  export function actionOf(envelope: any): string | undefined {
@@ -6,7 +6,7 @@ import { TwinEvent } from './twin-event.js'
6
6
  * 저널 목록 반환형 — things-factory 표준 `{ items, total }`(AttributeSetList·DomainList 등과 동형).
7
7
  *
8
8
  * `total` 이 이 타입의 존재 이유다. 기존 `twinEvents` 는 배열만 돌려줘서 **화면이 자기가 전체를 받은
9
- * 건지 잘린 건지 알 방법이 없었다** — 그래서 리스트가 조용히 잘린 채로 "이게 전부" 처럼 보였다.
9
+ * 건지 잘린 건지 알 방법이 없었다** — 그래서 리스트가 알리지 않고 잘린 채로 "이게 전부" 처럼 보였다.
10
10
  * 총건수를 함께 주면 화면은 "48 / 12,904" 라고 정직하게 말할 수 있고, 사용자는 좁혀야 한다는 걸 안다.
11
11
  */
12
12
  @ObjectType({ description: 'A page of twin journal events together with the total number of matching records.' })
@@ -48,4 +48,21 @@ export class TwinEventList {
48
48
  */
49
49
  @Field({ nullable: true, description: 'Opaque cursor for the next page. Pass it back as pagination.after to continue exactly where this page ended, without the duplicate or skipped rows that offset paging produces on a journal that keeps growing at the head. Null when this page is the last one.' })
50
50
  nextCursor?: string
51
+
52
+ /*
53
+ * **앞부분이 지워졌다** — 보관 기간 정리가 이 트윈의 오래된 사건을 지운 경우 (2026-08-27).
54
+ *
55
+ * 정리는 선언된 보관 기간(기본 7일)보다 오래된 사건을 지운다. 그러면 이 목록의 첫 페이지 뒤로 더
56
+ * 내려가도 어느 지점에서 기록이 끝난다. 화면이 그것을 말하지 않으면 사람은 「이 트윈은 그때부터
57
+ * 시작했다」로 읽는다. 없었던 것과 지워진 것은 다른 사실이다.
58
+ *
59
+ * 값은 저장하지 않고 조회할 때 구한다(남아 있는 가장 작은 리비전). 저장하면 실제 데이터와 어긋날 수
60
+ * 있고, 어긋나면 어느 쪽이 사실인지 알 수 없다.
61
+ */
62
+ @Field(type => Int, {
63
+ nullable: true,
64
+ description:
65
+ 'The oldest revision still stored for this twin. When it is greater than 1, older events were deleted by the journal retention policy: the screen must say the record starts here rather than implying the twin began at this point. NULL when the caller asked for more than one twin (the axis is per twin) or when nothing is stored.'
66
+ })
67
+ oldestRevision?: number
51
68
  }
@@ -34,8 +34,34 @@ import { Domain, ScalarObject } from '@things-factory/shell'
34
34
  @Index('ix_twin_event_4', (e: TwinEvent) => [e.domain, e.instanceId, e.orderId], { unique: false })
35
35
  /* ix_5 — "이 지시가 무엇을 일으켰나". 감사 기록의 commandId 로 저널을 다시 계산하는 축. */
36
36
  @Index('ix_twin_event_5', (e: TwinEvent) => [e.domain, e.correlationId], { unique: false })
37
- /* ix_6 — "반출을 한 번이라도 접었나". 없으면 그 질문이 인스턴스 저널 전량 주사가 된다. */
37
+ /* ix_6 — "반출을 한 번이라도 계산했나". 없으면 그 질문이 인스턴스 저널 전량 주사가 된다. */
38
38
  @Index('ix_twin_event_6', (e: TwinEvent) => [e.domain, e.instanceId, e.action], { unique: false })
39
+ /*
40
+ * ix_7 — **"이 종류의 사실을 시각순으로"** (2026-08-25 실측으로 추가)
41
+ *
42
+ * 이 축이 없어서 공정 타임라인이 22초였다. 종류로 거르고 시각으로 정렬하는 조회가 갈 곳이 없었다:
43
+ *
44
+ * ix_2 (…, eventType, revision) 종류는 걸러지고 정렬이 **적힌 순서**다 → 4월 사실을 최근으로 그렸다
45
+ * ix_1 (…, eventTime) 정렬은 맞고 **종류를 못 거른다** → 행마다 테이블을 열어 확인한다
46
+ *
47
+ * 뒤쪽으로 걸으면 그 트윈에서 찾는 종류가 멈춘 시점까지의 모든 행을 읽고 버린다. 승화푸드에서 작업
48
+ * 사실은 8월 22일에 멈춰 있고 그 뒤로 리비전이 110만 늘었으므로, 200건에 닿기까지 110만 행을 열었다.
49
+ *
50
+ * 위 주석이 「측정을 근거로 추가할 일이지 지레 얹을 일은 아니다」라고 적어 두었다. 그 측정이 나왔다.
51
+ */
52
+ @Index('ix_twin_event_7', (e: TwinEvent) => [e.domain, e.instanceId, e.eventType, e.eventTime], { unique: false })
53
+ /*
54
+ * ix_8 — **"이 트윈의 오래된 기록"** (2026-08-27 실측으로 추가)
55
+ *
56
+ * 보관 기간 정리가 `created_at` 으로 자르는데(보관은 저장 나이의 문제다) 그 축에 인덱스가 없었다.
57
+ * 그래서 정리가 매 배치마다 그 트윈의 저널을 전량 주사했다.
58
+ *
59
+ * hatio-mx2 의 7일 밖 행을 세기 208초 ← 1,029만 행을 전부 읽는다(7일 밖은 2,446건뿐이다)
60
+ * revision 으로 한 행 짚기 0.004초
61
+ *
62
+ * 정리는 한 창에 2초만 쓰도록 예산이 걸려 있어서, 그 2초를 주사에 다 쓰고 44건만 지우고 멈췄다.
63
+ */
64
+ @Index('ix_twin_event_8', (e: TwinEvent) => [e.domain, e.instanceId, e.createdAt], { unique: false })
39
65
  @ObjectType({ description: 'Append-only twin event journal record (EPCIS event or operational delta).' })
40
66
  export class TwinEvent {
41
67
  @PrimaryGeneratedColumn('uuid')
@@ -71,8 +97,8 @@ export class TwinEvent {
71
97
  * 이 사실이 **어느 공장에서** 일어났나 — `TwinStructure.rev`.
72
98
  *
73
99
  * 이것이 없던 시절에는 구조가 바뀌면 저널을 통째로 지우는 것이 유일한 길이었다(안 지우면 옛
74
- * 이벤트를 새 공장에 대고 접어 이력이 거짓말을 한다). 이 한 칸이 셋째 길을 연다 — 재생이
75
- * 구조가 바뀌는 지점에서 전환한 뒤 이어 접는다.
100
+ * 이벤트를 새 공장에 대고 계산해 이력이 거짓말을 한다). 이 한 칸이 셋째 길을 연다 — 재생이
101
+ * 구조가 바뀌는 지점에서 전환한 뒤 이어서 계산한다.
76
102
  *
77
103
  * **비어 있을 수 있다**: 컬럼이 생기기 전에 쓰인 행이다. 그 행들은 **가장 오래된 리비전**에
78
104
  * 속한다(0 을 채워 넣지 않는다 — 0 은 "모름" 이 아니라 유효한 번호처럼 보인다).
@@ -85,7 +111,7 @@ export class TwinEvent {
85
111
  * 이 사실이 일어난 시각(트윈의 시계). **날짜 타입이다.**
86
112
  *
87
113
  * 예전에는 문자열이었다. 읽을 때마다 `Date.parse` 했고, 정렬은 UTC ISO 만 들어온다는 전제 위에서
88
- * 사전식 비교가 우연히 맞았다 — `+09:00` 오프셋 표기가 하나 섞이면 조용히 순서가 틀린다.
114
+ * 사전식 비교가 우연히 맞았다 — `+09:00` 오프셋 표기가 하나 섞이면 알리지 않고 순서가 틀린다.
89
115
  * 그 전제는 컬럼 어디에도 적혀 있지 않았다.
90
116
  *
91
117
  * **타입 이름을 적지 않는다** (2026-08-19 Postgres 부팅 실패로 고침).
@@ -108,11 +134,11 @@ export class TwinEvent {
108
134
  * payload 가 여전히 정본이고 이것들은 **파생 색인**이다 — 새로운 진실이 아니라 찾을 수 있게 하는 장치.
109
135
  * simple-json(TEXT) 안의 값은 5개 DB 드라이버 공통으로 거를 방법이 없어서(멀티DB 호환 규칙상
110
136
  * DB별 JSON 연산자 금지) 승격 외의 선택지가 없다.
111
- * 길이 상한 255 는 GS1 식별자 규격 대비 충분하며, 넘치는 값은 조용히 잘리지 않고 경고를 남긴다.
137
+ * 길이 상한 255 는 GS1 식별자 규격 대비 충분하며, 넘치는 값은 알리지 않고 잘리지 않고 경고를 남긴다.
112
138
  *
113
139
  * ── 축을 새로 추가할 때 ──────────────────────────────────────────────────
114
140
  * 새 승격 컬럼을 만들면 **이미 쌓인 행은 비어 있다.** 그 행들은 새 축으로 검색되지 않고,
115
- * 사용자에게는 "과거가 없는 것" 으로 보인다(조용히 빠진 데이터).
141
+ * 사용자에게는 "과거가 없는 것" 으로 보인다(알리지 않고 빠진 데이터).
116
142
  *
117
143
  * 예전에는 기동 훅이 매번 테이블을 살펴 채웠다. 그건 두 가지로 틀렸다 — 저널이 커질수록 부팅이
118
144
  * 느려지고, "bizStep 이 비었으면 옛 행" 이라는 전제를 코드에 고정해 그 전제가 깨지는 순간
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * ── 왜 순수 모듈인가 (2026-08-15) ───────────────────────────────────────────
5
5
  * 이 표가 리졸버 안에 있어서 시험이 불러올 수 없었다(type-graphql·shell 을 물고 있다). 그런데 여기서
6
- * 틀리면 예측 그래프 전체가 조용히 다른 것을 그린다 — 오류 없이. 규칙은 시험이 닿는 자리에 둔다.
6
+ * 틀리면 예측 그래프 전체가 알리지 않고 다른 것을 그린다 — 오류 없이. 규칙은 시험이 닿는 자리에 둔다.
7
7
  *
8
8
  * ── 에너지 지표를 더한 이유 ─────────────────────────────────────────────────
9
9
  * 예측 화면의 지표가 물류 여섯(재고·점유·작업·오더·출고·백로그)으로 고정돼 있어서, 에너지 트윈을
@@ -23,7 +23,7 @@ export interface GapPoint {
23
23
  modelAbsError: number
24
24
  }
25
25
 
26
- /** 합산 결과 + **무엇을 못 넣었는지.** 조용히 줄이지 않는다. */
26
+ /** 합산 결과 + **무엇을 못 넣었는지.** 알리지 않고 줄이지 않는다. */
27
27
  export interface AggregateResult {
28
28
  points: GapPoint[]
29
29
  /** 한 트윈이라도 재지 못해 통째로 뺀 vantage 수. */