@things-factory/headless-twin 10.0.8 → 10.0.10

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 (381) hide show
  1. package/dist-server/engine/attention-digest.d.ts +52 -0
  2. package/dist-server/engine/attention-digest.js +76 -0
  3. package/dist-server/engine/attention-digest.js.map +1 -0
  4. package/dist-server/engine/canonical-ingest.d.ts +2 -2
  5. package/dist-server/engine/canonical-ingest.js +24 -2
  6. package/dist-server/engine/canonical-ingest.js.map +1 -1
  7. package/dist-server/engine/command-routing.d.ts +33 -0
  8. package/dist-server/engine/command-routing.js +53 -0
  9. package/dist-server/engine/command-routing.js.map +1 -0
  10. package/dist-server/engine/energy-topology.d.ts +86 -0
  11. package/dist-server/engine/energy-topology.js +144 -0
  12. package/dist-server/engine/energy-topology.js.map +1 -0
  13. package/dist-server/engine/index.d.ts +11 -0
  14. package/dist-server/engine/index.js +17 -0
  15. package/dist-server/engine/index.js.map +1 -1
  16. package/dist-server/engine/kpi-baseline.d.ts +78 -0
  17. package/dist-server/engine/kpi-baseline.js +123 -0
  18. package/dist-server/engine/kpi-baseline.js.map +1 -0
  19. package/dist-server/engine/kpi-fold.d.ts +137 -1
  20. package/dist-server/engine/kpi-fold.js +225 -0
  21. package/dist-server/engine/kpi-fold.js.map +1 -1
  22. package/dist-server/engine/kpi-query.d.ts +32 -1
  23. package/dist-server/engine/kpi-query.js +262 -20
  24. package/dist-server/engine/kpi-query.js.map +1 -1
  25. package/dist-server/engine/kpi-target.d.ts +17 -0
  26. package/dist-server/engine/kpi-target.js +24 -2
  27. package/dist-server/engine/kpi-target.js.map +1 -1
  28. package/dist-server/engine/live-attentions.d.ts +1 -0
  29. package/dist-server/engine/live-attentions.js +7 -1
  30. package/dist-server/engine/live-attentions.js.map +1 -1
  31. package/dist-server/engine/live-feed-registry.d.ts +25 -0
  32. package/dist-server/engine/live-feed-registry.js +51 -0
  33. package/dist-server/engine/live-feed-registry.js.map +1 -0
  34. package/dist-server/engine/load-meter.d.ts +181 -0
  35. package/dist-server/engine/load-meter.js +267 -0
  36. package/dist-server/engine/load-meter.js.map +1 -0
  37. package/dist-server/engine/local-declarations.d.ts +262 -0
  38. package/dist-server/engine/local-declarations.js +528 -0
  39. package/dist-server/engine/local-declarations.js.map +1 -0
  40. package/dist-server/engine/model-basis.d.ts +39 -6
  41. package/dist-server/engine/model-basis.js +69 -9
  42. package/dist-server/engine/model-basis.js.map +1 -1
  43. package/dist-server/engine/model-vocabulary.d.ts +17 -0
  44. package/dist-server/engine/model-vocabulary.js +81 -0
  45. package/dist-server/engine/model-vocabulary.js.map +1 -0
  46. package/dist-server/engine/oee-accumulator.d.ts +28 -0
  47. package/dist-server/engine/oee-accumulator.js +26 -1
  48. package/dist-server/engine/oee-accumulator.js.map +1 -1
  49. package/dist-server/engine/operation-basis.d.ts +32 -0
  50. package/dist-server/engine/operation-basis.js +87 -0
  51. package/dist-server/engine/operation-basis.js.map +1 -0
  52. package/dist-server/engine/property-effects.d.ts +30 -0
  53. package/dist-server/engine/property-effects.js +192 -0
  54. package/dist-server/engine/property-effects.js.map +1 -0
  55. package/dist-server/engine/runtime-key.d.ts +15 -0
  56. package/dist-server/engine/runtime-key.js +64 -0
  57. package/dist-server/engine/runtime-key.js.map +1 -0
  58. package/dist-server/engine/spec-coverage.js +3 -3
  59. package/dist-server/engine/spec-coverage.js.map +1 -1
  60. package/dist-server/engine/state-axes.d.ts +21 -0
  61. package/dist-server/engine/state-axes.js +59 -0
  62. package/dist-server/engine/state-axes.js.map +1 -0
  63. package/dist-server/engine/structure-diff.js +1 -1
  64. package/dist-server/engine/structure-diff.js.map +1 -1
  65. package/dist-server/engine/travel-estimator.d.ts +9 -2
  66. package/dist-server/engine/travel-estimator.js +11 -6
  67. package/dist-server/engine/travel-estimator.js.map +1 -1
  68. package/dist-server/engine/twin-engine.d.ts +418 -57
  69. package/dist-server/engine/twin-engine.js +1599 -306
  70. package/dist-server/engine/twin-engine.js.map +1 -1
  71. package/dist-server/engine/warm-start.d.ts +93 -13
  72. package/dist-server/engine/warm-start.js +114 -14
  73. package/dist-server/engine/warm-start.js.map +1 -1
  74. package/dist-server/index.d.ts +1 -0
  75. package/dist-server/index.js +17 -11
  76. package/dist-server/index.js.map +1 -1
  77. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.d.ts +5 -0
  78. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js +48 -0
  79. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +1 -0
  80. package/dist-server/migrations/index.d.ts +2 -0
  81. package/dist-server/migrations/index.js +10 -0
  82. package/dist-server/migrations/index.js.map +1 -0
  83. package/dist-server/service/index.d.ts +3 -2
  84. package/dist-server/service/index.js +25 -17
  85. package/dist-server/service/index.js.map +1 -1
  86. package/dist-server/service/reference/discovery-result.d.ts +34 -0
  87. package/dist-server/service/reference/discovery-result.js +84 -0
  88. package/dist-server/service/reference/discovery-result.js.map +1 -0
  89. package/dist-server/service/reference/ingest-space.d.ts +53 -0
  90. package/dist-server/service/reference/ingest-space.js +79 -0
  91. package/dist-server/service/reference/ingest-space.js.map +1 -0
  92. package/dist-server/service/reference/knob-defaults.d.ts +20 -0
  93. package/dist-server/service/reference/knob-defaults.js +59 -0
  94. package/dist-server/service/reference/knob-defaults.js.map +1 -0
  95. package/dist-server/service/reference/reference-live.d.ts +23 -0
  96. package/dist-server/service/reference/reference-live.js +123 -6
  97. package/dist-server/service/reference/reference-live.js.map +1 -1
  98. package/dist-server/service/reference/reference-master.d.ts +227 -11
  99. package/dist-server/service/reference/reference-master.js +206 -25
  100. package/dist-server/service/reference/reference-master.js.map +1 -1
  101. package/dist-server/service/reference/reference-resolver.d.ts +33 -3
  102. package/dist-server/service/reference/reference-resolver.js +290 -23
  103. package/dist-server/service/reference/reference-resolver.js.map +1 -1
  104. package/dist-server/service/reference/template-registry.d.ts +19 -3
  105. package/dist-server/service/reference/template-registry.js.map +1 -1
  106. package/dist-server/service/twin-attention/twin-attention-query.d.ts +8 -1
  107. package/dist-server/service/twin-attention/twin-attention-query.js +39 -8
  108. package/dist-server/service/twin-attention/twin-attention-query.js.map +1 -1
  109. package/dist-server/service/twin-audit/command-audit.d.ts +37 -0
  110. package/dist-server/service/twin-audit/command-audit.js +53 -0
  111. package/dist-server/service/twin-audit/command-audit.js.map +1 -0
  112. package/dist-server/service/twin-audit/index.d.ts +4 -0
  113. package/dist-server/service/twin-audit/index.js +8 -0
  114. package/dist-server/service/twin-audit/index.js.map +1 -0
  115. package/dist-server/service/twin-audit/twin-audit-event.d.ts +24 -0
  116. package/dist-server/service/twin-audit/twin-audit-event.js +125 -0
  117. package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -0
  118. package/dist-server/service/twin-audit/twin-audit-query.d.ts +4 -0
  119. package/dist-server/service/twin-audit/twin-audit-query.js +76 -0
  120. package/dist-server/service/twin-audit/twin-audit-query.js.map +1 -0
  121. package/dist-server/service/twin-control/twin-control-mutation.d.ts +2 -0
  122. package/dist-server/service/twin-control/twin-control-mutation.js +50 -11
  123. package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
  124. package/dist-server/service/twin-event/twin-event-keys.d.ts +1 -1
  125. package/dist-server/service/twin-event/twin-event-keys.js +1 -1
  126. package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
  127. package/dist-server/service/twin-event/twin-event.d.ts +14 -5
  128. package/dist-server/service/twin-event/twin-event.js +46 -14
  129. package/dist-server/service/twin-event/twin-event.js.map +1 -1
  130. package/dist-server/service/twin-forecast/forecast-metrics.d.ts +13 -0
  131. package/dist-server/service/twin-forecast/forecast-metrics.js +57 -0
  132. package/dist-server/service/twin-forecast/forecast-metrics.js.map +1 -0
  133. package/dist-server/service/twin-forecast/forecast-tuning.d.ts +12 -0
  134. package/dist-server/service/twin-forecast/forecast-tuning.js +44 -0
  135. package/dist-server/service/twin-forecast/forecast-tuning.js.map +1 -0
  136. package/dist-server/service/twin-forecast/gap-analytics.d.ts +28 -2
  137. package/dist-server/service/twin-forecast/gap-analytics.js +43 -17
  138. package/dist-server/service/twin-forecast/gap-analytics.js.map +1 -1
  139. package/dist-server/service/twin-forecast/twin-forecast-query.js +219 -39
  140. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
  141. package/dist-server/service/twin-instance/twin-instance.d.ts +38 -5
  142. package/dist-server/service/twin-instance/twin-instance.js +66 -18
  143. package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
  144. package/dist-server/service/twin-journal/twin-journal-query.d.ts +11 -4
  145. package/dist-server/service/twin-journal/twin-journal-query.js +95 -15
  146. package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
  147. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +11 -5
  148. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +46 -27
  149. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
  150. package/dist-server/service/twin-metrics/twin-metrics-query.d.ts +1 -0
  151. package/dist-server/service/twin-metrics/twin-metrics-query.js +63 -1
  152. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
  153. package/dist-server/service/twin-model/epcis-coverage.d.ts +14 -0
  154. package/dist-server/service/twin-model/epcis-coverage.js +174 -0
  155. package/dist-server/service/twin-model/epcis-coverage.js.map +1 -0
  156. package/dist-server/service/twin-model/iec61850-coverage.d.ts +14 -0
  157. package/dist-server/service/twin-model/iec61850-coverage.js +98 -0
  158. package/dist-server/service/twin-model/iec61850-coverage.js.map +1 -0
  159. package/dist-server/service/twin-model/index.d.ts +13 -0
  160. package/dist-server/service/twin-model/index.js +29 -0
  161. package/dist-server/service/twin-model/index.js.map +1 -0
  162. package/dist-server/service/twin-model/isa95-coverage.d.ts +48 -0
  163. package/dist-server/service/twin-model/isa95-coverage.js +155 -0
  164. package/dist-server/service/twin-model/isa95-coverage.js.map +1 -0
  165. package/dist-server/service/twin-model/project-structure.d.ts +16 -0
  166. package/dist-server/service/twin-model/project-structure.js +173 -0
  167. package/dist-server/service/twin-model/project-structure.js.map +1 -0
  168. package/dist-server/service/twin-model/standard-coverage.d.ts +9 -0
  169. package/dist-server/service/twin-model/standard-coverage.js +37 -0
  170. package/dist-server/service/twin-model/standard-coverage.js.map +1 -0
  171. package/dist-server/service/twin-model/twin-equipment.d.ts +64 -0
  172. package/dist-server/service/twin-model/twin-equipment.js +134 -0
  173. package/dist-server/service/twin-model/twin-equipment.js.map +1 -0
  174. package/dist-server/service/twin-model/twin-lineage-query.d.ts +3 -0
  175. package/dist-server/service/twin-model/twin-lineage-query.js +206 -0
  176. package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -0
  177. package/dist-server/service/twin-model/twin-location.d.ts +58 -0
  178. package/dist-server/service/twin-model/twin-location.js +130 -0
  179. package/dist-server/service/twin-model/twin-location.js.map +1 -0
  180. package/dist-server/service/twin-model/twin-model-item-query.d.ts +141 -0
  181. package/dist-server/service/twin-model/twin-model-item-query.js +852 -0
  182. package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -0
  183. package/dist-server/service/twin-model/twin-model-mutation.d.ts +57 -0
  184. package/dist-server/service/twin-model/twin-model-mutation.js +490 -0
  185. package/dist-server/service/twin-model/twin-model-mutation.js.map +1 -0
  186. package/dist-server/service/twin-model/twin-model-query.d.ts +43 -0
  187. package/dist-server/service/twin-model/twin-model-query.js +551 -0
  188. package/dist-server/service/twin-model/twin-model-query.js.map +1 -0
  189. package/dist-server/service/twin-model/twin-model-tree-query.d.ts +3 -0
  190. package/dist-server/service/twin-model/twin-model-tree-query.js +158 -0
  191. package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -0
  192. package/dist-server/service/twin-model/twin-operation.d.ts +61 -0
  193. package/dist-server/service/twin-model/twin-operation.js +137 -0
  194. package/dist-server/service/twin-model/twin-operation.js.map +1 -0
  195. package/dist-server/service/twin-space/move-space.d.ts +65 -0
  196. package/dist-server/service/twin-space/move-space.js +166 -0
  197. package/dist-server/service/twin-space/move-space.js.map +1 -0
  198. package/dist-server/service/twin-space/space-integrity.d.ts +97 -0
  199. package/dist-server/service/twin-space/space-integrity.js +182 -0
  200. package/dist-server/service/twin-space/space-integrity.js.map +1 -0
  201. package/dist-server/service/twin-space/twin-space-area.js +4 -4
  202. package/dist-server/service/twin-space/twin-space-area.js.map +1 -1
  203. package/dist-server/service/twin-space/twin-space-representation.js +6 -6
  204. package/dist-server/service/twin-space/twin-space-representation.js.map +1 -1
  205. package/dist-server/service/twin-space/twin-space-resolver.d.ts +63 -1
  206. package/dist-server/service/twin-space/twin-space-resolver.js +365 -18
  207. package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
  208. package/dist-server/service/twin-space/twin-space.d.ts +17 -1
  209. package/dist-server/service/twin-space/twin-space.js +15 -5
  210. package/dist-server/service/twin-space/twin-space.js.map +1 -1
  211. package/dist-server/service/twin-state/twin-state-subscription.js +1 -1
  212. package/dist-server/service/twin-state/twin-state-subscription.js.map +1 -1
  213. package/dist-server/service/twin-structure/twin-structure.d.ts +1 -1
  214. package/dist-server/service/twin-structure/twin-structure.js +8 -7
  215. package/dist-server/service/twin-structure/twin-structure.js.map +1 -1
  216. package/dist-server/service/twin-target/twin-target-resolver.js +21 -4
  217. package/dist-server/service/twin-target/twin-target-resolver.js.map +1 -1
  218. package/dist-shared/axis-read.d.ts +12 -0
  219. package/dist-shared/axis-read.js +32 -0
  220. package/dist-shared/axis-read.js.map +1 -0
  221. package/dist-shared/entity-delta.d.ts +29 -0
  222. package/dist-shared/entity-delta.js +287 -0
  223. package/dist-shared/entity-delta.js.map +1 -0
  224. package/dist-shared/kpi-broadcast.d.ts +4 -0
  225. package/dist-shared/kpi-broadcast.js +16 -0
  226. package/dist-shared/kpi-broadcast.js.map +1 -0
  227. package/dist-shared/twin-level.d.ts +23 -0
  228. package/dist-shared/twin-level.js +52 -0
  229. package/dist-shared/twin-level.js.map +1 -0
  230. package/package.json +14 -12
  231. package/server/engine/attention-digest.ts +102 -0
  232. package/server/engine/canonical-ingest.ts +36 -4
  233. package/server/engine/command-routing.ts +67 -0
  234. package/server/engine/energy-topology.ts +189 -0
  235. package/server/engine/index.ts +17 -0
  236. package/server/engine/kpi-baseline.ts +202 -0
  237. package/server/engine/kpi-fold.ts +389 -1
  238. package/server/engine/kpi-query.ts +295 -22
  239. package/server/engine/kpi-target.ts +24 -2
  240. package/server/engine/live-attentions.ts +7 -2
  241. package/server/engine/live-feed-registry.ts +58 -0
  242. package/server/engine/load-meter.ts +384 -0
  243. package/server/engine/local-declarations.ts +700 -0
  244. package/server/engine/model-basis.ts +78 -10
  245. package/server/engine/model-vocabulary.ts +82 -0
  246. package/server/engine/oee-accumulator.ts +34 -1
  247. package/server/engine/operation-basis.ts +100 -0
  248. package/server/engine/property-effects.ts +199 -0
  249. package/server/engine/runtime-key.ts +58 -0
  250. package/server/engine/spec-coverage.ts +3 -3
  251. package/server/engine/state-axes.ts +60 -0
  252. package/server/engine/structure-diff.ts +1 -1
  253. package/server/engine/travel-estimator.ts +11 -6
  254. package/server/engine/twin-engine.ts +1710 -297
  255. package/server/engine/warm-start.ts +207 -22
  256. package/server/index.ts +13 -10
  257. package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +43 -0
  258. package/server/migrations/index.ts +7 -0
  259. package/server/service/index.ts +9 -1
  260. package/server/service/reference/discovery-result.ts +95 -0
  261. package/server/service/reference/ingest-space.ts +104 -0
  262. package/server/service/reference/knob-defaults.ts +59 -0
  263. package/server/service/reference/reference-live.ts +121 -6
  264. package/server/service/reference/reference-master.ts +362 -35
  265. package/server/service/reference/reference-resolver.ts +307 -23
  266. package/server/service/reference/template-registry.ts +20 -5
  267. package/server/service/twin-attention/twin-attention-query.ts +43 -6
  268. package/server/service/twin-audit/command-audit.ts +81 -0
  269. package/server/service/twin-audit/index.ts +5 -0
  270. package/server/service/twin-audit/twin-audit-event.ts +112 -0
  271. package/server/service/twin-audit/twin-audit-query.ts +72 -0
  272. package/server/service/twin-control/twin-control-mutation.ts +53 -13
  273. package/server/service/twin-event/twin-event-keys.ts +1 -1
  274. package/server/service/twin-event/twin-event.ts +52 -15
  275. package/server/service/twin-forecast/forecast-metrics.ts +60 -0
  276. package/server/service/twin-forecast/forecast-tuning.ts +40 -0
  277. package/server/service/twin-forecast/gap-analytics.ts +48 -9
  278. package/server/service/twin-forecast/twin-forecast-query.ts +211 -38
  279. package/server/service/twin-instance/twin-instance.ts +127 -22
  280. package/server/service/twin-journal/twin-journal-query.ts +108 -14
  281. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +40 -23
  282. package/server/service/twin-metrics/twin-metrics-query.ts +60 -3
  283. package/server/service/twin-model/epcis-coverage.ts +195 -0
  284. package/server/service/twin-model/iec61850-coverage.ts +117 -0
  285. package/server/service/twin-model/index.ts +25 -0
  286. package/server/service/twin-model/isa95-coverage.ts +190 -0
  287. package/server/service/twin-model/project-structure.ts +199 -0
  288. package/server/service/twin-model/standard-coverage.ts +35 -0
  289. package/server/service/twin-model/twin-equipment.ts +150 -0
  290. package/server/service/twin-model/twin-lineage-query.ts +193 -0
  291. package/server/service/twin-model/twin-location.ts +140 -0
  292. package/server/service/twin-model/twin-model-item-query.ts +848 -0
  293. package/server/service/twin-model/twin-model-mutation.ts +503 -0
  294. package/server/service/twin-model/twin-model-query.ts +537 -0
  295. package/server/service/twin-model/twin-model-tree-query.ts +180 -0
  296. package/server/service/twin-model/twin-operation.ts +150 -0
  297. package/server/service/twin-space/move-space.ts +262 -0
  298. package/server/service/twin-space/space-integrity.ts +293 -0
  299. package/server/service/twin-space/twin-space-area.ts +4 -4
  300. package/server/service/twin-space/twin-space-representation.ts +6 -6
  301. package/server/service/twin-space/twin-space-resolver.ts +365 -22
  302. package/server/service/twin-space/twin-space.ts +40 -6
  303. package/server/service/twin-state/twin-state-subscription.ts +1 -1
  304. package/server/service/twin-structure/twin-structure.ts +10 -7
  305. package/server/service/twin-target/twin-target-resolver.ts +22 -4
  306. package/shared/axis-read.ts +28 -0
  307. package/shared/entity-delta.ts +286 -0
  308. package/shared/kpi-broadcast.ts +13 -0
  309. package/shared/twin-level.ts +48 -0
  310. package/test/adopt-structure-live.test.ts +133 -0
  311. package/test/attention-digest.test.ts +135 -0
  312. package/test/axis-read.test.ts +87 -0
  313. package/test/boot-resume.test.ts +205 -0
  314. package/test/canonical-ingest-vocabularies.test.ts +118 -0
  315. package/test/capability-mapping.test.ts +5 -5
  316. package/test/command-routing.test.ts +61 -0
  317. package/test/declaration-reaches-model.test.ts +178 -0
  318. package/test/discovery-result.test.ts +75 -0
  319. package/test/energy-topology.test.ts +113 -0
  320. package/test/entity-delta.test.ts +195 -25
  321. package/test/event-time-column.test.ts +67 -0
  322. package/test/forecast-metrics.test.ts +71 -0
  323. package/test/forecast-tuning.test.ts +42 -0
  324. package/test/gap-analytics.test.ts +34 -7
  325. package/test/ingest-bench.test.ts +9 -9
  326. package/test/ingest-running-guard.test.ts +136 -0
  327. package/test/ingest-space.test.ts +78 -0
  328. package/test/instance-cache-lifecycle.test.ts +110 -0
  329. package/test/kernel-kind-guard.test.ts +96 -0
  330. package/test/knob-defaults.test.ts +72 -0
  331. package/test/kpi-baseline-db.test.ts +216 -0
  332. package/test/kpi-baseline.test.ts +196 -0
  333. package/test/kpi-fold.test.ts +393 -2
  334. package/test/kpi-query-bench.test.ts +130 -0
  335. package/test/lineage-survives-restart.test.ts +203 -0
  336. package/test/live-feed-registry.test.ts +67 -0
  337. package/test/live-kernel-facts.test.ts +161 -0
  338. package/test/live-mirror-parity.test.ts +54 -14
  339. package/test/load-meter.test.ts +314 -0
  340. package/test/local-declarations.test.ts +554 -0
  341. package/test/master-to-twin.test.ts +128 -36
  342. package/test/model-basis.test.ts +56 -1
  343. package/test/model-vocabulary.test.ts +114 -0
  344. package/test/move-space.test.ts +149 -0
  345. package/test/mutation-gate.test.ts +122 -0
  346. package/test/oee-accumulator.test.ts +90 -7
  347. package/test/operation-basis.test.ts +100 -0
  348. package/test/operations-capability-db.test.ts +165 -0
  349. package/test/project-structure-db.test.ts +226 -0
  350. package/test/projection-reaches-screen.test.ts +272 -0
  351. package/test/property-effects.test.ts +96 -0
  352. package/test/registry-key-guard.test.ts +80 -0
  353. package/test/resync-origin-site.test.ts +77 -0
  354. package/test/runtime-key.test.ts +66 -0
  355. package/test/scale-twin-bench.test.ts +7 -7
  356. package/test/snapshot-freshness.test.ts +60 -0
  357. package/test/space-integrity.test.ts +223 -0
  358. package/test/standard-coverage.test.ts +94 -0
  359. package/test/state-axes.test.ts +74 -0
  360. package/test/streamline-e2e.test.ts +16 -16
  361. package/test/structure-revision-db.test.ts +16 -15
  362. package/test/tenant-registry-db.test.ts +149 -0
  363. package/test/twin-audit.test.ts +83 -0
  364. package/test/twin-model-item-db.test.ts +275 -0
  365. package/test/twin-model-tree-db.test.ts +176 -0
  366. package/test/twin-origin-resync.test.ts +114 -0
  367. package/test/warm-start-seam.test.ts +140 -0
  368. package/test/warm-start.test.ts +223 -4
  369. package/tsconfig.json +6 -1
  370. package/tsconfig.shared.json +23 -0
  371. package/tsconfig.shared.tsbuildinfo +1 -0
  372. package/tsconfig.tsbuildinfo +1 -0
  373. package/dist-server/engine/entity-delta.d.ts +0 -19
  374. package/dist-server/engine/entity-delta.js +0 -161
  375. package/dist-server/engine/entity-delta.js.map +0 -1
  376. package/dist-server/service/twin-event/backfill-keys.d.ts +0 -11
  377. package/dist-server/service/twin-event/backfill-keys.js +0 -63
  378. package/dist-server/service/twin-event/backfill-keys.js.map +0 -1
  379. package/dist-server/tsconfig.tsbuildinfo +0 -1
  380. package/server/engine/entity-delta.ts +0 -169
  381. package/server/service/twin-event/backfill-keys.ts +0 -72
@@ -1,8 +1,12 @@
1
+ import type { ReducerCheckpoint } from '@operato/twin-kernel';
2
+ import type { OeeCheckpoint } from './oee-accumulator.js';
1
3
  import { type ReferenceMaster } from '../service/reference/reference-master.js';
4
+ import { type IngestWarning } from '../service/reference/reference-master.js';
2
5
  import { type ModelBasis } from './model-basis.js';
6
+ import { type LoadMeter, type LoadPhase } from './load-meter.js';
3
7
  import { type StructureDiff } from './structure-diff.js';
4
8
  import { OeeAccumulator } from './oee-accumulator.js';
5
- import type { BoardDef, TwinRuntime as TwinRuntimeType, CanonicalEnvelope } from '@operato/twin-kernel';
9
+ import type { TwinModelDef, StructureShift, TwinRuntime as TwinRuntimeType, CanonicalEnvelope } from '@operato/twin-kernel';
6
10
  interface TwinMetrics {
7
11
  ingestedTotal: number;
8
12
  broadcastTotal: number;
@@ -19,6 +23,8 @@ interface TwinMetrics {
19
23
  export type RealityMode = 'mirror' | 'sim-world' | 'sim-experiment';
20
24
  export declare const DEFAULT_REALITY_MODE: RealityMode;
21
25
  interface InstanceRuntime {
26
+ /** 부하 계기판 — 작업별 소요. 시뮬·라이브 모두 붙는다(누가 루프를 점유하는지 보려면 둘 다 필요하다). */
27
+ load?: LoadMeter;
22
28
  /** 현실 출처 선언(§0 프레임 ①). 부팅 거동(reset/resume/resync)의 근거. */
23
29
  realityMode?: RealityMode;
24
30
  id: string;
@@ -27,6 +33,8 @@ interface InstanceRuntime {
27
33
  runtime?: TwinRuntimeType;
28
34
  kernel?: any;
29
35
  mode?: 'sim' | 'live';
36
+ /** 이 트윈이 선 현장 — 같은 현장의 트윈끼리 서로의 설비 상태를 읽을 수 있게 하는 열쇠. */
37
+ spaceId?: string;
30
38
  /**
31
39
  * live 의 상태 접근 어댑터 — 이제 **관측 모드 커널**을 가리킨다(`kernel` 과 같은 것).
32
40
  * 이름은 소비처 호환으로 남았고, P3 에서 커널 어휘로 정리하면 사라진다.
@@ -34,6 +42,11 @@ interface InstanceRuntime {
34
42
  projector?: any;
35
43
  oee?: OeeAccumulator;
36
44
  unsub: () => void;
45
+ /**
46
+ * 방금 인입한 봉투들 — 커널이 그것을 재방출할 때 **저널에 두 번 적지 않기** 위한 표시.
47
+ * 라이브만 쓴다(sim 은 커널이 스스로 낸 것만 흘린다). 약한 참조라 따로 비울 것이 없다.
48
+ */
49
+ applying?: WeakSet<object>;
37
50
  timer?: any;
38
51
  /** 엔티티별 마지막 발행 시그니처 — 값이 바뀐 엔티티만 재발행(무변화 반복 push 방지). */
39
52
  entitySigs?: Map<string, string>;
@@ -46,22 +59,93 @@ interface InstanceRuntime {
46
59
  /** live 처리량 계측(모니터, ④-1). */
47
60
  metrics?: TwinMetrics;
48
61
  }
62
+ /**
63
+ * 트윈이 **스스로 멈춘 이유** — 문장이 아니라 코드다.
64
+ *
65
+ * 서버가 만든 영어 문장을 그대로 실으면 한국어·일본어 화면에 그 영어가 뜬다. 이 시스템은 거절 메시지에서
66
+ * 같은 결론에 이르렀다(코드+파라미터를 내고 화면이 옮긴다). `reason` 만은 원문 그대로다 — 커널·런타임이
67
+ * 낸 오류 문구는 옮길 수 있는 어휘가 아니고, 옮기려 들면 원인을 잃는다.
68
+ */
69
+ export interface StopNote {
70
+ code: 'starved' | 'tick-failed';
71
+ params: Record<string, string | number>;
72
+ }
49
73
  export declare class TwinEngine {
50
74
  static instances: Record<string, InstanceRuntime>;
51
75
  /** 라이브 런타임이 없을 때(복구 후 미기동) 저널에서 재구성한 상태 캐시. */
76
+ /** 웜스타트 씨앗 — `instances` 와 **같은 키**(겹치면 남의 스냅샷으로 재고가 섞인다). */
52
77
  static recovered: Record<string, any>;
53
78
  static TICK_MS: number;
79
+ /** 굶김 문턱 — 틱 간격의 배수(1초 간격이면 5초). 이 시간만큼 호스트가 멈춘다. */
80
+ static STARVE_FACTOR: number;
81
+ /** 연속 몇 번이면 멈추나 — 3번이면 15초를 굶긴 셈이고, 그건 우연이 아니다. */
82
+ static STARVE_STREAK: number;
83
+ private static starveStreak;
84
+ /**
85
+ * 왜 멈췄나 — **화면이 그대로 말할 수 있게.** 스스로 멈춘 트윈이 이유 없이 「정지」로만 보이면
86
+ * 사람은 자기가 멈춘 줄 안다. 메모리에만 둔다(재기동하면 사라진다 — 그때는 「모른다」가 사실이다).
87
+ */
88
+ private static stopNotes;
54
89
  static SNAPSHOT_CACHE_ID: string;
90
+ static CHAIN_CACHE_ID: string;
91
+ static CHAIN_INDEX_CACHE_ID: string;
92
+ static CHAIN_STRIDE: number;
93
+ static CHAIN_KEEP: number;
55
94
  static SNAPSHOT_TTL_S: number;
56
95
  static CHECKPOINT_MS: number;
57
96
  private static checkpointTimer?;
58
97
  /** 최신 스냅샷을 cache-service 에 체크포인트(도메인+instanceId 키). display-only·비차단·오류흡수. */
59
98
  static persistSnapshot(domainId: string, instanceId: string): Promise<void>;
99
+ /**
100
+ * 접기의 **재개점** — 리듀서 내부 상태 전부 + 가동 누적기.
101
+ *
102
+ * 스냅샷(`state`)은 소비처가 보는 값이라 이어 접기의 씨앗이 되지 못한다(보류된 담김·집합·반영 못 한
103
+ * 사건 집계가 없다 — 그 상태로 뒤를 접으면 0부터 접은 결과와 조용히 달라진다). 그래서 씨앗은 따로 든다.
104
+ */
105
+ private static readonly FOLD_NOTE;
60
106
  /** 체크포인트된 최신 스냅샷 로드(없으면 null). getFromCache 는 CacheStore 엔티티를 반환 → 페이로드는 .value. */
61
107
  static loadSnapshot(domainId: string, instanceId: string): Promise<{
62
108
  revision: number;
63
109
  state: any;
110
+ structureRev?: number | null;
111
+ fold?: {
112
+ reducer: ReducerCheckpoint;
113
+ oee: OeeCheckpoint;
114
+ };
64
115
  } | null>;
116
+ /**
117
+ * 접은 상태를 스냅샷으로 남긴다 — **라이브가 아니어도.**
118
+ *
119
+ * `persistSnapshot` 은 기동 중인 인스턴스에서만 뜬다(메모리가 진실이므로 옳다). 그런데 **멈춘**
120
+ * 트윈을 조회할 때마다 저널을 전량 다시 접고 있었다(23,731건짜리 트윈에서 4.6초). 그 폴드의 결과를
121
+ * 남겨 두면 **처음 한 번만 느리다.**
122
+ *
123
+ * `structureRev` 를 함께 적는다: 이벤트가 하나도 안 늘어도 구조를 갈아치우면(재프로비저닝) 그
124
+ * 상태는 낡은 것이다. 리비전만 보면 새 설비가 없는 옛 상태를 "지금" 으로 내게 된다.
125
+ */
126
+ static saveFoldedSnapshot(domainId: string, instanceId: string, value: {
127
+ revision: number;
128
+ state: any;
129
+ structureRev?: number | null;
130
+ fold?: {
131
+ reducer: ReducerCheckpoint;
132
+ oee: OeeCheckpoint;
133
+ };
134
+ }): Promise<void>;
135
+ /** 사슬 색인 — 어떤 리비전 지점을 들고 있나(최신순 아님, 오름차순). */
136
+ private static chainIndex;
137
+ /**
138
+ * 목표 이전의 **가장 가까운 지점**을 고른다 — 없으면 `null`(0부터 접는다).
139
+ *
140
+ * 시각으로 물었으면 그 지점의 마지막 사실 시각이 목표 이내여야 한다(리비전만 보면 목표보다 뒤의
141
+ * 사실이 씨앗에 섞인다). 구조가 바뀐 트윈에서는 쓰지 않는다 — 마디를 건너뛴 씨앗은 그 경계의
142
+ * 판정을 잃는다(그 경우는 0부터 접는 것이 옳다).
143
+ */
144
+ private static chainSeedFor;
145
+ /** 눈금을 넘었으면 한 지점을 남긴다 — 오래된 것은 버린다(색인도 함께 줄인다). */
146
+ private static keepChainPoint;
147
+ /** 이 트윈 저널의 끝 리비전 · 최신 구조 리비전 — 스냅샷이 지금의 사실인지 가리는 두 값. */
148
+ private static tipOf;
65
149
  /** 체크포인트 루프 기동(1회) — 라이브 인스턴스들의 최신 스냅샷을 주기 영속. */
66
150
  static startCheckpointLoop(): void;
67
151
  /**
@@ -70,31 +154,59 @@ export declare class TwinEngine {
70
154
  */
71
155
  static bootstrap(): Promise<void>;
72
156
  /**
73
- * 웜스타트 — 기동하는 커널에 **직전 관측 상태**를 심는다.
157
+ * 부팅 때 **도는 트윈을 실제로 되살린다** — 「도는 중」이 사실이 되게.
158
+ *
159
+ * ── 무엇이 거짓말이었나 (2026-08-14) ────────────────────────────────────────
160
+ * `bootstrap()` 은 상태만 되찾아 `recovered` 에 담았고, 커널을 세우는 것은 **명시 mutation 뿐**이었다
161
+ * (이 파일 위쪽 주석이 「향후」라고 적어 둔 그 자리다). 그래서 서버를 한 번 재기동하면 등록부는
162
+ * `running` 이라 말하는데 **아무 커널도 돌지 않았다** — 화면은 도는 트윈을, 실제로는 멈춘 트윈을.
163
+ * 미러 트윈에서는 더 나쁘다: 계측이 조용히 끊기고, 사람은 「값이 안 변하네」로 알게 된다.
164
+ *
165
+ * ── 모드를 지어내지 않는다 ──────────────────────────────────────────────────
166
+ * 미러였던 트윈을 시뮬로 되살리면 **없던 움직임을 만들어 낸다**(관측 트윈이 스스로 물건을 옮긴다).
167
+ * 그래서 선언된 `realityMode` 그대로 되살린다 — 미러는 관측 구동으로, 시뮬은 시뮬로.
168
+ *
169
+ * ── 되살릴 수 없으면 그렇게 적는다 ──────────────────────────────────────────
170
+ * 실패를 삼키면 등록부가 계속 `running` 이라 말한다 — 우리가 고치려던 그 거짓말이다. 그래서 실패한
171
+ * 행은 `stopped` 로 적고 이유를 남긴다. 「멈췄다」는 사실이고, 「도는 중」은 사실이 아니었다.
172
+ */
173
+ private static resumeRow;
174
+ /** 되살리지 못한 행을 정직하게 적는다 — 「도는 중」이라 말하는 채로 두지 않는다. */
175
+ private static markStopped;
176
+ /**
177
+ * 웜스타트 — 기동하는 커널에 **직전 관측 상태**를 주입한다.
74
178
  *
75
179
  * ── 왜 필요한가 ─────────────────────────────────────────────────────────────
76
- * `loadBoard` 는 **구조만** 싣는다(노드·무버). 상태(무엇이 어디에 얼마나)는 없다. 그래서 재기동한
180
+ * `loadTwinModel` 는 **구조만** 싣는다(자리·설비). 상태(무엇이 어디에 얼마나)는 없다. 그래서 재기동한
77
181
  * 트윈은 저널에 입고 540건이 남아 있어도 재고가 0 이었고, 화면은 "보유 중인 것이 없습니다" 라고
78
182
  * 말했다 — 있는 재고를 없다고 하는 셈이다(2026-07-31 hatiolab-wms 실측으로 확인).
79
183
  * `bootstrap()` 이 이미 체크포인트 캐시(없으면 저널 replay)로 상태를 복구해 `recovered` 에 담아 두는데,
80
184
  * 기동 순간 그걸 **버리고** 있었다. 반만 연결돼 있던 장치를 잇는다.
81
185
  *
82
- * ── 정직한 한계 ─────────────────────────────────────────────────────────────
83
- * · **오더는 복원하지 않는다.** `hydrateObserved` 의 오더 인자는 requested/fulfilled/lines 를 요구하는데
84
- * 스냅샷의 `OrderState` 에는 `progress` 밖에 없다. progress 에서 역산하면 없는 숫자를 지어내는 것이라
85
- * 넘기지 않는다 — 재고·노드·무버만 복원되고 진행 중 오더는 비어서 시작한다.
86
- * · 진행 중 개별 task 의 내부 상태도 관측만으로는 복원되지 않는다(커널이 명시한 한계, 재계획에 맡김).
87
- * · 근본 해법(상태 영속 계약·revision 이어붙임)은 별도 과제.
186
+ * ── 반쪽이던 복구를 마무리한다 (2026-08-05) ─────────────────────────────────
187
+ * 재고는 살아났는데 **진행 중 주문이 통째로 사라진** 화면이 남아 있었다. 씨앗이 자리·물품·설비
188
+ * 셋만 넘겼기 때문이다. 그 근거는 "스냅샷 오더에 progress 밖에 없다" 였고, 그때는 맞았다 —
189
+ * 그러나 커널 `OrderState` 가 원값(`requested`·`fulfilled`·`lines`)을 되찾은 뒤에도 이 자리만
190
+ * 그대로 남았다. 오류를 내지 않는 종류라 오래 버텼다.
191
+ *
192
+ * 지금은 **관측 스냅샷 전체**를 넘긴다(오더·작업·사람·자산 포함). 시뮬은 커널 `snapshot()`,
193
+ * 라이브는 `StateProjector` 가 그 일곱 축을 모두 담는다. 무엇을 심을 수 있는지 판정하는 규칙
194
+ * (이행 완료 오더 제외·고아 작업 제외)은 커널에 있고, 호스트가 미리 골라내지 않는다.
195
+ *
196
+ * ── 남은 한계는 숨기지 않고 센다 ────────────────────────────────────────────
197
+ * · 원값이 없는 오더(progress 만 있는 것)는 남은 수량을 알 수 없어 주입하지 않는다. **지어내지 않는
198
+ * 대신 몇 건인지 말한다** — 세지 않으면 "주문이 없다" 와 "주문을 못 심었다" 가 화면에서 같아진다.
199
+ * · 진행 중 개별 작업의 내부 상태는 관측만으로 완전히 복원되지 않는다(커널이 명시한 한계, 재계획에 맡김).
88
200
  *
89
201
  * ── 벤치는 시드하지 않는다 ──────────────────────────────────────────────────
90
- * 부하 벤치는 **새 시작에서 용량을 재는 것**이 목적이라 현재 상태를 심으면 측정이 오염된다.
202
+ * 부하 벤치는 **새 시작에서 용량을 재는 것**이 목적이라 현재 상태를 주입하면 측정이 오염된다.
91
203
  */
92
204
  private static warmStart;
93
- /** 트윈 인스턴스 시작 — 커널 생성 + 보드 로드 + 직전 상태 웜스타트 + State 스트림 브리지 + 워커 tick + 레지스트리 영속. */
205
+ /** 트윈 인스턴스 시작 — 커널 생성 + 모델 로드 + 직전 상태 웜스타트 + State 스트림 브리지 + 워커 tick + 레지스트리 영속. */
94
206
  /**
95
207
  * 공정 명세를 커널에 싣는다 — **시뮬레이션의 시간을 데이터가 말하게 하는 마지막 한 칸.**
96
208
  *
97
- * `board.operations`(마스터 인제스트가 통과시킨 ISA-95 OperationsSegment 명세)를 커널이 소비한다.
209
+ * `model.operations`(마스터 인제스트가 통과시킨 ISA-95 OperationsSegment 명세)를 커널이 소비한다.
98
210
  * 없으면 커널 기본 상수로 굴러가고, 커널 `specCoverage()` 가 무엇을 기본값으로 썼는지 보고한다.
99
211
  *
100
212
  * 커널이 아직 이 API 를 갖지 않은 버전이면(발행 이전) **조용히 넘어가지 않고 경고한다** — 명세를
@@ -106,14 +218,14 @@ export declare class TwinEngine {
106
218
  *
107
219
  * 커널 `durationOf` 의 우선순위는 추정기 > 명세 > 상수다. 그 추정기 자리에 두 가지를 사슬로 넣는다:
108
220
  * ① **실측**(저널의 작업 종류별 작업시간 p50) — 그 현장에서 실제로 얼마 걸렸나. 가장 강한 근거.
109
- * ② **거리 × 속도**(board.layout + 설비 속도 속성) — 이동은 거리에 비례한다. 커널은 좌표를 모르므로
221
+ * ② **거리 × 속도**(model.layout + 설비 속도 속성) — 이동은 거리에 비례한다. 커널은 좌표를 모르므로
110
222
  * 호스트가 계산해 넣는다.
111
223
  * 둘 다 못 만들면 주입하지 않는다 — 커널이 명세·상수로 굴러가고 `specCoverage()` 가 그 사실을 남긴다.
112
224
  *
113
225
  * 실측은 DB 조회라 비동기다. 그래서 이 함수는 **await 하지 않는 쪽에서도 안전**하도록 실패를 삼키되,
114
226
  * 무엇을 왜 못 넣었는지는 로그로 남긴다(조용한 무효화 금지).
115
227
  */
116
- static installEstimators(kernel: any, domainId: string, instanceId: string, board: any): Promise<void>;
228
+ static installEstimators(kernel: any, domainId: string, instanceId: string, model: any): Promise<void>;
117
229
  /**
118
230
  * 실측 추정기 — **예측 요청마다 저널을 다시 접지 않는다.**
119
231
  *
@@ -123,7 +235,33 @@ export declare class TwinEngine {
123
235
  */
124
236
  private static measuredCache;
125
237
  private static readonly MEASURED_TTL_MS;
238
+ /**
239
+ * 캐시 항목 상한 — **라이프사이클이 놓친 것까지 막는 두 번째 방어.**
240
+ *
241
+ * 지움은 `forgetInstance` 가 한다(그것이 첫 번째 방어이고 정확한 쪽이다). 그런데 트윈이 우리 API 를
242
+ * 지나지 않고 사라지는 길이 있다: 도메인(테넌트)째로 지워지거나 DB 를 직접 손대는 경우다. 그때
243
+ * 남은 항목을 지울 주인이 없으므로 상한이 필요하다.
244
+ *
245
+ * 넘치면 **가장 오래 손대지 않은 것**부터 버린다(Map 의 삽입 순서가 곧 그 순서다 — 값을 쓸 때마다
246
+ * 다시 넣으므로). 버리는 것이 손해가 아닌 이유: 이 값은 캐시이고, 없으면 다시 계산한다.
247
+ *
248
+ * 수를 크게 잡는다 — 트윈 규모는 늘 크고, 항목 하나는 작업 종류별 소요 몇 줄이다. 상한이 작으면
249
+ * 정상 규모에서 서로 밀어내며 캐시가 무의미해진다(그게 더 나쁘다: 조용히 느려진다).
250
+ */
251
+ private static readonly MEASURED_MAX;
126
252
  private static measuredEstimator;
253
+ /**
254
+ * 이 트윈이 **이력에서 시간을 배운 작업 종류들** — 재기동에도 남는 근거.
255
+ *
256
+ * ── 왜 필요한가 (2026-08-18 실측) ────────────────────────────────────────
257
+ * 커널의 자기보고(`specCoverage()`)는 **작업이 새로 생길 때** 채워진다. 그래서 재기동 직후에는 이력이
258
+ * 풍부한 트윈에서도 목록이 비고, 「이 트윈이 무슨 공정을 돌리나」 화면이 빈칸이 된다 — 값을 채울 곳을
259
+ * 보여야 하는 화면이 정작 그때 아무 말도 못 한다.
260
+ *
261
+ * 그 빈칸을 이력로 메운다: 저널에서 배운 종류는 **추정기가 이미 답할 수 있는 종류**이므로, 지어내는
262
+ * 것이 아니라 있는 사실을 꺼내는 것이다. 같은 캐시(60초)를 쓰므로 조회마다 저널을 다시 접지 않는다.
263
+ */
264
+ static measuredOperationKinds(domainId: string, instanceId: string): Promise<string[]>;
127
265
  /**
128
266
  * 지금 이 트윈이 어떤 모델로 굴러가는가 — 예측 출력 보정이 **자기가 배운 모델**에만 적용되도록
129
267
  * 비교하는 지문. 재료는 호스트가 아는 것(실측·속도·선언 명세)이라 커널 발행 상태와 무관하다.
@@ -131,13 +269,13 @@ export declare class TwinEngine {
131
269
  */
132
270
  static modelBasis(domainId: string, instanceId: string): Promise<ModelBasis | undefined>;
133
271
  /**
134
- * **이 트윈이 하루 몇 대를 낼 수 있는가** — 굴려 보지 않고 답한다.
272
+ * **이 트윈이 하루 몇 대를 낼 수 있는가** — 실행해 보지 않고 답한다.
135
273
  *
136
274
  * 계산은 커널이 자기 상태에서 한다(`kernel.capacity`). 여기서 하는 일은 **기준 주를 정해 주는
137
275
  * 것**뿐이다: 공휴일이 없는 평상주여야 한다 — 공휴일은 연간 가용량을 따로 깎지, 이 공장의 평상시
138
- * 천장을 정하지 않는다. 커널이 임의로 고르게 두면 그 주에 공휴일이 끼었을 때 천장이 조용히 낮아진다.
276
+ * 상한을 정하지 않는다. 커널이 임의로 고르게 두면 그 주에 공휴일이 끼었을 때 상한이 조용히 낮아진다.
139
277
  *
140
- * 트윈이 안 떠 있으면 `undefined` 다 — 0 이 아니다. 안 뜬 트윈의 천장을 0 이라고 답하면 화면은
278
+ * 트윈이 기동 중이 아니면 `undefined` 다 — 0 이 아니다. 기동하지 않은 트윈의 상한을 0 이라고 답하면 화면은
141
279
  * "이 공장은 아무것도 못 만든다" 고 말한다.
142
280
  */
143
281
  static capacity(domainId: string, target: {
@@ -149,7 +287,33 @@ export declare class TwinEngine {
149
287
  analysis?: any;
150
288
  reason?: 'not-running' | 'no-operations';
151
289
  }[]>;
152
- static start(id: string, domainId: string, kind: string, board: BoardDef, realityMode?: RealityMode, purpose?: string, resumeFrom?: number): InstanceRuntime;
290
+ /**
291
+ * **생산 능력 보고서** — ISA-95 Part 4 `OperationsCapability`. 구간의 양을 종류로 구분한다
292
+ * (약정·가용·달성불가). 용량(`capacity`)은 비율을 내고 이것은 **구간의 양**을 낸다.
293
+ *
294
+ * 대상 선정·거절 사유는 `capacity` 와 **같은 규율**이다: 등록부가 대상을 정하고(안 기동 중인 것과
295
+ * 없는 것을 구별한다), 공정을 선언하지 않은 트윈은 판정 대상이 아니라고 말한다(0 으로 채우면
296
+ * "야드가 병목" 이라는 없는 사실이 생긴다).
297
+ */
298
+ static operationsCapability(domainId: string, target: {
299
+ instanceId?: string;
300
+ spaceId?: string;
301
+ }, unitsPerDay: number, sampleWeekStartMs: number, window: {
302
+ fromTime: string;
303
+ toTime: string;
304
+ }): Promise<{
305
+ instanceId: string;
306
+ kind?: string;
307
+ report?: any;
308
+ reason?: 'not-running' | 'no-operations';
309
+ }[]>;
310
+ /**
311
+ * 미러 기동의 연속성 씨앗 — 이어받은 것은 **말한다**(조용히 잇지 않는다).
312
+ *
313
+ * 커널이 그 문을 열어 두지 않았으면 그 사실도 말한다: 그 트윈은 재기동마다 열린 구간을 잃는다.
314
+ */
315
+ private static seedLiveContinuity;
316
+ static start(id: string, domainId: string, kind: string, model: TwinModelDef, realityMode?: RealityMode, purpose?: string, resumeFrom?: number): InstanceRuntime;
153
317
  /**
154
318
  * live-모드 기동 — **관측 모드 커널**로 실 이벤트를 미러한다(통합 P2).
155
319
  *
@@ -163,47 +327,77 @@ export declare class TwinEngine {
163
327
  * 실 이벤트원 = reference 어댑터 openLiveFeed → face2-adapter.ingest → CanonicalEnvelope → ingestLive().
164
328
  */
165
329
  /**
166
- * 보드가 실은 **생산 정의**(레시피·라우트·바인딩)를 꺼낸다 — 커널의 정의-구동 모드 입구.
330
+ * 모델이 실은 **생산 정의**(레시피·라우트·바인딩)를 꺼낸다 — 커널의 정의-구동 모드 입구.
167
331
  *
168
332
  * ── 없을 때 무엇이 일어났나 ──────────────────────────────────────────────
169
333
  * 커널에는 정의-구동 MES 경로가 있는데 **호스트가 그것을 한 번도 넘기지 않았다.** 그래서 모든 MES
170
334
  * 트윈이 **하드코딩된 레거시 흐름**으로 돌았다 — 현장 레시피를 아무리 정성껏 적어도 커널은 그것을
171
335
  * 보지 못하고 토이 부품으로 토이 제품을 만들었다. 선언과 실행이 갈라져 있던 자리다.
172
336
  *
173
- * 보드에 없으면 `undefined` — 레거시 경로 그대로다(기존 트윈의 거동을 바꾸지 않는다).
337
+ * 모델에 없으면 `undefined` — 레거시 경로 그대로다(기존 트윈의 거동을 바꾸지 않는다).
174
338
  */
175
- private static mesSpecOf;
176
339
  /**
177
- * 현장(공간)의 **시각 기준**을 보드에 얹는다 — 커널이 교대의 `HH:MM` 을 읽을 기준.
340
+ * 생산 선언을 꺼낸다 — 커널 생성자에 넘긴다.
341
+ *
342
+ * **옛 이름(`mesSpec`)은 읽지 않는다.** 그것은 계약에 선언조차 없던 필드였고(MES 커널 생성자 인자
343
+ * 이름이 그대로 굳은 것), 일반 기제에 한 시스템 이름이 붙어 있었기 때문에 창고 트윈이 이 자리를
344
+ * 쓰지 못했다. 별명으로 남겨 두면 그 혼동이 계속되므로 하나로 통일했다.
345
+ *
346
+ * 옛 이름만 가진 모델이 있으면 **조용히 생산 선언을 잃는 대신 분명히 멈춘다** — 그 트윈은 공정이
347
+ * 없는 채로 돌게 되고(라인이 서 있는 창고), 원인을 찾기 어렵다.
348
+ */
349
+ private static productionSpecOf;
350
+ /**
351
+ * 현장(공간)의 **시각 기준**을 모델에 얹는다 — 커널이 교대의 `HH:MM` 을 읽을 기준.
178
352
  *
179
353
  * **테넌트가 아니라 공간이 권위다.** 한 테넌트가 Rosarito(태평양)와 한국 공장을 함께 가질 수 있고,
180
- * 테넌트 단위(`Domain.timezone`)로 두면 둘 중 하나는 반드시 틀린다. 그래서 인스턴스가 묶인 공간의
354
+ * 테넌트 단위(`Domain.timezone`)로 두면 둘 중 하나는 반드시 틀린다. 그래서 인스턴스가 연결된 공간의
181
355
  * `timezone` 을 읽는다. 공간이 말하지 않으면 **테넌트로 내려가지 않는다** — 잘못된 입자로 답하는 것이
182
356
  * 모르는 것보다 나쁘다(그때는 커널이 UTC 로 읽고, 그 기본값은 계약에 밝혀져 있다).
183
357
  *
184
358
  * 커널은 zero-dep 이라 시간대 데이터베이스를 갖지 않으므로 **분 오프셋**으로 풀어 넘긴다. 그 값은
185
359
  * 지금 계절의 것이다(일광절약시간) — 계절을 넘는 긴 예측은 한 시간 어긋난다(계약에 명시).
186
360
  */
187
- static withSpaceTimeBase(board: BoardDef, domainId: string, spaceId?: string): Promise<BoardDef>;
188
- static startLive(id: string, domainId: string, kind: string, board: BoardDef): InstanceRuntime;
361
+ static withSpaceTimeBase(model: TwinModelDef, domainId: string, spaceId?: string): Promise<TwinModelDef>;
362
+ static startLive(id: string, domainId: string, kind: string, model: TwinModelDef): InstanceRuntime;
189
363
  /**
190
364
  * live 이벤트 인제스트 — projector 구동 + data(tag) 방송(폐루프의 인바운드 도착 지점, command-routing §8.2).
191
365
  * reference 어댑터가 낸 records → 커널 face2-adapter.ingest → CanonicalEnvelope 를 여기로 밀어넣는다.
192
366
  * (State 채널 델타/저널 결선은 후속 — 스켈레톤은 data(tag) 미러 중심.)
193
367
  */
194
- static ingestLive(id: string, envelopes: CanonicalEnvelope[]): void;
368
+ static ingestLive(domainId: string, id: string, envelopes: CanonicalEnvelope[]): void;
369
+ /**
370
+ * 구간 성과 방송은 **없앴다**(2026-08-06). 카드가 `twinKpi` 를 직접 묻는다.
371
+ *
372
+ * 왜: 카드를 여러 단계(공간·트윈·구역·자리·설비)에 붙이려면 방송으로는 태그가 트윈당 1,200개가 되고,
373
+ * **모델에 카드를 하나도 안 놓아도** 30초마다 트윈마다 저널을 접었다. 질의로 바꾸니 보고 있는 카드
374
+ * 수만큼만 들고, 같은 (대상·창·축) 은 클라이언트가 하나로 합친다.
375
+ *
376
+ * 덤으로 질의만 할 수 있는 것이 둘 생겼다 — **과거 시각**(`toTime`)과 **공간 단위 합산**(여러 트윈을
377
+ * 한 번에 접기). 방송 루프는 트윈별이라 둘 다 못 했다.
378
+ *
379
+ * 축을 나눠도 폴드 비용이 같다는 실측이 근거다(`test/kpi-query-bench.test.ts`).
380
+ */
195
381
  /** 방송 병합 주기(ms) — 방송률 상한. 인제스트가 아무리 빨라도 이 주기로만 방송. */
196
382
  static BROADCAST_COALESCE_MS: number;
197
383
  private static broadcastTimer?;
198
384
  /** live 방송 coalescer — dirty 인 live 인스턴스만 주기적으로 1회 방송(entitySigs 로 변경 엔티티만). */
199
385
  private static ensureBroadcastCoalescer;
200
- /** dirty live 인스턴스 방송 flush(주기 tick 또는 명시 호출). 테스트/즉시 방송용으로 public. */
386
+ /**
387
+ * dirty 인스턴스 방송 flush(주기 tick 또는 명시 호출) — **시뮬과 라이브 둘 다.**
388
+ *
389
+ * 예전에는 라이브만 봤다(`mode !== 'live'` 면 건너뜀). 시뮬은 delta 마다 곧바로 방송했고, 그것이
390
+ * 한 tick 에서 수백 번 반복되며 이벤트 루프를 막았다(위 `start()` 주석의 35초 틱). 방송을 모으는
391
+ * 규율은 모드의 성질이 아니라 **채널의 성질**이다 — 최신-상태 채널이면 중간 상태는 보낼 값이 없다.
392
+ */
201
393
  static flushLiveBroadcasts(): void;
202
394
  /**
203
395
  * 저널 행 한 줄 — **기록 경로가 둘이라(라이브 벌크·심 단건) 행 모양은 반드시 한 곳에서 만든다.**
204
396
  * 두 곳에 각자 적으면 승격 검색 키가 한쪽에만 채워지고, 반쯤 빈 색인은 "저널에는 있는데
205
397
  * 검색으로는 안 나오는 이벤트" 를 만든다 — 저널에서 가장 나쁜 종류의 결함이다.
206
398
  */
399
+ /** 저널의 시각 축은 날짜다 — 못 읽는 값은 비운다(0 이나 지금으로 위장하지 않는다). */
400
+ private static toEventTimeValue;
207
401
  private static journalRow;
208
402
  /**
209
403
  * 이 트윈이 지금 어느 구조로 도는가 — 이벤트에 찍을 번호. 한 번 읽고 캐시한다(쓰기마다 조회 금지).
@@ -216,33 +410,72 @@ export declare class TwinEngine {
216
410
  /** live 저널 배치 기록 — 모아둔 CanonicalEnvelope 들에 startRevision+1.. 을 부여해 벌크 저장(coalescer tick 당 1회). */
217
411
  static persistBatch(domainId: string, instanceId: string, envelopes: any[], startRevision: number): Promise<void>;
218
412
  /** 레지스트리 upsert(도메인+instanceId 유니크). status 인자로 provision(stopped)/start(running) 공용. */
219
- static register(domainId: string, instanceId: string, kind: string, board: BoardDef, status?: 'running' | 'stopped', realityMode?: RealityMode): Promise<void>;
413
+ static register(domainId: string, instanceId: string, kind: string, model: TwinModelDef, status?: 'running' | 'stopped', realityMode?: RealityMode, origin?: any, meta?: {
414
+ name?: string;
415
+ description?: string;
416
+ actor?: {
417
+ id: string;
418
+ };
419
+ }): Promise<void>;
220
420
  /**
221
- * 라이브 구조 변이(resource.add 등)를 저장된 board 에 반영 — 런타임 커널의 무버를 registry board.equipment 에 동기.
222
- * 이게 없으면 런타임엔 추가돼도(상태·저널엔 반영) 저장 board 는 원본이라 프로비저닝 편집기·재기동(loadBoard)이
223
- * 추가분을 잃는다. 기존 board.equipment 항목은 보존(homeLocation 유지)하고 새 id 만 append(추가 시점 location=homeLocation).
421
+ * 라이브 구조 변이(resource.add 등)를 저장된 model 에 반영 — 런타임 커널의 무버를 registry model.equipment 에 동기.
422
+ * 이게 없으면 런타임엔 추가돼도(상태·저널엔 반영) 저장 model 는 원본이라 프로비저닝 편집기·재기동(loadTwinModel)이
423
+ * 추가분을 잃는다. 기존 model.equipment 항목은 보존(homeLocation 유지)하고 새 id 만 append(추가 시점 location=homeLocation).
224
424
  * 좌표(layout)만 다루는 register 와 달리 equipment 집합을 갱신하나, 재프로비전(purge)이 아니라 in-place 갱신이라
225
425
  * 저널은 보존된다(추가는 이미 equipment 델타로 저널됨 → replay 는 id-keyed upsert 라 이중계산 없음).
226
426
  */
227
427
  static syncBoardEquipment(domainId: string, instanceId: string): Promise<void>;
228
428
  /**
229
- * 프로비저닝 — 레지스트리에 구조(board)를 등록만 하고 기동하지 않음(status='stopped').
429
+ * 프로비저닝 — 레지스트리에 구조(model)를 등록만 하고 기동하지 않음(status='stopped').
230
430
  * 재프로비전 시 구조 시그니처가 바뀌면(노드·무버 집합/속성 변경) 기존 저널을 purge 한다(ADR-0015):
231
- * board 는 replay 의 마스터라 구조가 바뀌면 과거 이벤트의 전제가 깨진다. 좌표(layout)만 바뀌면 저널 보존.
431
+ * model 는 replay 의 마스터라 구조가 바뀌면 과거 이벤트의 전제가 깨진다. 좌표(layout)만 바뀌면 저널 보존.
432
+ */
433
+ /**
434
+ * 실행 중이면 구조를 교체하지 않는다 — **판정 문장을 한 곳에 둔다.**
435
+ *
436
+ * 인제스트는 전량 교체라, 이벤트를 접고 있는 커널 밑에서 바닥을 바꾸는 셈이 된다. 지금은 거절이
437
+ * 유일한 답이지만 최종형은 아니다(`adoptStructure` 배선). 두 곳에서 같은 문장으로 거절해야
438
+ * 나중에 이 규칙을 걷어낼 때 걷어낼 것이 하나로 보인다.
232
439
  */
233
- static provision(domainId: string, instanceId: string, kind: string, board: BoardDef, comment?: string): Promise<void>;
440
+ private static assertNotRunning;
441
+ /**
442
+ * 돌면서 공장을 전환한다 — **미러 전용.**
443
+ *
444
+ * 미러가 비추는 현실은 안 멈춘다. 설비 한 대가 늘었다고 트윈을 멈췄다 세우면 그 사이의 사실을
445
+ * 잃고, 라이브에서 유실은 곧 거짓이다. 그래서 미러는 **동작 중에** 새 구조를 받는다.
446
+ *
447
+ * 시뮬레이션은 여기 오지 않는다. 조건이 바뀐 실험은 다른 실험이므로 멈추고 다시 세우는 것이
448
+ * 옳다 — 커널이 그렇게 거절한다(`FlowEngine.adoptStructure`).
449
+ *
450
+ * 세 가지가 **함께** 일어나야 한다. 하나라도 빠지면 층이 어긋난다:
451
+ * ① 리비전 — 이 시점 이후의 이벤트가 새 번호를 달고 다닌다(재생이 마디를 나눌 수 있게)
452
+ * ② 저장 model·구조 행 — 조회가 새 구조를 본다
453
+ * ③ 커널 — 지금 접히는 이벤트가 새 구조 위에서 접힌다
454
+ */
455
+ static adoptStructure(domainId: string, instanceId: string, model: TwinModelDef, comment?: string, origin?: any): Promise<{
456
+ rev: number;
457
+ } & StructureShift>;
458
+ static provision(domainId: string, instanceId: string, kind: string, model: TwinModelDef, comment?: string, origin?: any,
459
+ /** 이름·저자 — 업무키를 나눠 둔 대가로 이름을 함께 남긴다(`register` 의 `meta` 그대로). */
460
+ meta?: {
461
+ name?: string;
462
+ description?: string;
463
+ actor?: {
464
+ id: string;
465
+ };
466
+ }): Promise<void>;
234
467
  /**
235
468
  * 이 구조를 리비전으로 남기고 그 번호를 돌려준다 — **바뀌었을 때만** 새 번호가 생긴다.
236
469
  *
237
470
  * 프로비저닝은 부팅마다 다시 도는데, 그때마다 리비전이 늘면 이력이 뜻 없는 마디로 잘게 쪼개진다.
238
471
  * 그래서 **구조 서명이 같으면 있던 리비전을 그대로 쓴다.**
239
472
  */
240
- static recordStructure(domainId: string, instanceId: string, board: BoardDef, comment?: string): Promise<number>;
473
+ static recordStructure(domainId: string, instanceId: string, model: TwinModelDef, comment?: string): Promise<number>;
241
474
  /**
242
475
  * 이 트윈이 거쳐 온 구조들 — **무엇이 언제 달라졌나.**
243
476
  *
244
477
  * 리비전은 그 시절 공장을 통째로 담지만(재생에 필요하다), 사람이 보고 싶은 것은 통째가 아니라
245
- * 차이다. 보드는 빼고 **차이 요약만** 내보낸다 — 62KB 짜리 보드를 화면에 실어 보낼 이유가 없다.
478
+ * 차이다. 모델은 빼고 **차이 요약만** 내보낸다 — 62KB 짜리 보드를 화면에 실어 보낼 이유가 없다.
246
479
  */
247
480
  static structureHistory(domainId: string, instanceId: string): Promise<{
248
481
  rev: number;
@@ -252,7 +485,7 @@ export declare class TwinEngine {
252
485
  diff: StructureDiff;
253
486
  }[]>;
254
487
  /** 지금 쓰이는 구조 리비전 — 이벤트에 찍을 번호. 아직 없으면 기록하며 만든다. */
255
- static currentStructureRev(domainId: string, instanceId: string, board?: BoardDef): Promise<number | undefined>;
488
+ static currentStructureRev(domainId: string, instanceId: string, model?: TwinModelDef): Promise<number | undefined>;
256
489
  /** 구조 동일성 지문 — 좌표(layout) 등 뷰 관심사는 제외하고 커널이 보는 위상·용량·무버만. */
257
490
  /**
258
491
  * 지문을 **64자로 줄인다** — 컬럼이 varchar(64) 다.
@@ -263,10 +496,10 @@ export declare class TwinEngine {
263
496
  */
264
497
  private static structureFingerprint;
265
498
  private static structureSignature;
266
- /** 레지스트리 board 로 기동(프로비전된 인스턴스 start). board 인자 없이 저장된 구조로 재기동. */
499
+ /** 레지스트리 model 로 기동(프로비전된 인스턴스 start). model 인자 없이 저장된 구조로 재기동. */
267
500
  static startFromRegistry(domainId: string, instanceId: string, realityMode?: RealityMode): Promise<InstanceRuntime>;
268
501
  /**
269
- * 선언 기반 부팅(§0 프레임 ① → 부팅 거동 매핑) — 트윈이 선언한 realityMode 에 따라 재기동 방식을 가른다.
502
+ * 선언 기반 부팅(§0 프레임 ① → 부팅 거동 매핑) — 트윈이 선언한 realityMode 에 따라 재기동 방식을 구분한다.
270
503
  * 부팅 경로를 한 곳에 모아 "런타임 ≠ 현실" 범주오류를 코드로 강제한다.
271
504
  * - 'mirror' : 현실=외부 실물 → startLive(재동기). 이벤트는 어댑터 ingest 로 유입, 커널 tick 없음.
272
505
  * - 'sim-world' : 생성 타임라인 지속 → 저널 보존 + resume(현실 이어감).
@@ -284,11 +517,20 @@ export declare class TwinEngine {
284
517
  static resetJournal(domainId: string, instanceId: string): Promise<void>;
285
518
  /** 삭제 — 정지 + 레지스트리 삭제 + 저널 purge(domain 스코프). */
286
519
  static remove(domainId: string, instanceId: string): Promise<void>;
520
+ /**
521
+ * 이 트윈에 대해 **메모리에 남은 것을 전부 잊는다** — 지움의 한 자리.
522
+ *
523
+ * 캐시가 라이프사이클과 어긋나 있었다: 저널·등록부는 지우면서 인스턴스별 캐시는 남겨, 삭제된 트윈의
524
+ * 항목이 **서버 재기동까지 살아 있었다.** 항목 하나가 하루치 KPI 그룹을 물고 있으므로 잊지 않으면
525
+ * 지운 트윈이 계속 메모리를 차지한다. TTL 은 값이 낡는 것을 막을 뿐 **없어진 주인을 지우지 않는다.**
526
+ *
527
+ * 잊을 것을 여기 모아 두는 이유: 캐시를 새로 만드는 사람이 지우는 자리를 찾아 헤매지 않게 한다.
528
+ * 새 인스턴스별 캐시를 만들면 **이 함수에 한 줄을 더한다** — 그러지 않으면 같은 누수가 다시 생긴다.
529
+ */
530
+ private static forgetInstance;
287
531
  /** 관리 목록 — domain 의 등록 인스턴스 전체(라이브 여부·최신 저널 revision·노드/무버 수 포함). */
288
532
  static list(domainId: string): Promise<any[]>;
289
- /** 레거시 벤치 잔재 가드 — purpose 도입 전 만들어진 벤치/부하 공간(이름 규약)까지 걸러낸다. */
290
- static isBenchSpace(spaceId?: string): boolean;
291
- /** 운영 공간 목록(벤치 소스 선택기) — 이름·규모 포함, 벤치 사본·잔재 제외. */
533
+ /** 운영 공간 목록(벤치 소스 선택기) — 이름·규모 포함, 벤치 사본 제외. */
292
534
  static listSpaces(domainId: string): Promise<{
293
535
  spaceId: string;
294
536
  name: string;
@@ -299,17 +541,23 @@ export declare class TwinEngine {
299
541
  /** 인스턴스 목적 표식(운영/벤치) 설정 — 벤치 사본을 1급 속성으로 구별(이름 접두사 아님). */
300
542
  static setPurpose(domainId: string, instanceId: string, purpose: 'operational' | 'bench', copyOf?: string): Promise<void>;
301
543
  /**
302
- * 공간 구조 판독 — 완전복제(벤치 사본)의 소스. 저장물이 board(위상)·TwinSpace.content(치수·geo·표현)·TwinArea(영역)로
544
+ * 공간 구조 판독 — 완전복제(벤치 사본)의 소스. 저장물이 model(위상)·TwinSpace.content(치수·geo·표현)·TwinArea(영역)로
303
545
  * 분산돼 있으므로 셋을 모아 돌려준다. 호출측이 ReferenceMaster 로 재구성 → 재식별 → ingestMaster.
304
546
  */
305
547
  static spaceStructure(domainId: string, spaceId: string): Promise<{
306
548
  name?: string;
307
- content: any;
549
+ /** 설계 좌표계 범위(미터)와 지오레퍼런스 — 사본이 원본과 같은 자리에 서려면 함께 가야 한다. */
550
+ frame: {
551
+ extentX?: number;
552
+ extentY?: number;
553
+ geo?: any;
554
+ primaryRepresentationId?: string;
555
+ };
308
556
  areas: any[];
309
557
  instances: {
310
558
  instanceId: string;
311
559
  kind?: string;
312
- board: any;
560
+ model: any;
313
561
  }[];
314
562
  } | null>;
315
563
  /** 공간(+표현·영역) 삭제 — 벤치 정리 등. 호출측이 바인딩 인스턴스를 먼저 제거하는 전제(가드 없음). deleteTwinSpace 리졸버와 동형. */
@@ -318,24 +566,49 @@ export declare class TwinEngine {
318
566
  * Face2 마스터 인제스트(ADR-0018) — 레퍼런스 시스템(실 또는 가상)의 마스터를 읽어 트윈을 생성.
319
567
  * 엔티티를 손배선/발명하지 않고 마스터에서 반영: 공간(Space) upsert + 인스턴스 provision(미기동).
320
568
  * 노드타입은 커널 카탈로그로 검증(warning). start 는 호출측(bootstrap/mutation)이 결정.
569
+ *
570
+ * `into.spaceId` — **이 현장에 더한다.** 한 현실을 여러 렌즈(WMS·MES·YMS)가 비추므로 새 트윈이
571
+ * 기존 공간으로 들어갈 수 있다. 아래 병합은 원래 그 경우를 위해 있었는데(N:1) 만드는 흐름에서
572
+ * 공간을 고를 방법이 없었다 — 마스터가 파생한 id 만 쓰였다. 판정은 `resolveIngestSpace`(순수).
321
573
  */
322
- static ingestMaster(domainId: string, master: ReferenceMaster): Promise<{
574
+ static ingestMaster(domainId: string, master: ReferenceMaster, into?: {
575
+ spaceId?: string;
576
+ },
577
+ /** 누가 인제스트했나 — 사람이 없는 경로(부팅)는 주지 않는다(감사 기록을 지어내지 않는다). */
578
+ actor?: {
579
+ id: string;
580
+ }): Promise<{
323
581
  instanceId: string;
324
582
  spaceId: string;
325
- warnings: string[];
583
+ warnings: IngestWarning[];
326
584
  }>;
327
- /** 단건 상세 — 프로비저닝 에디터가 편집할 board(구조+layout) 포함. */
585
+ /** 단건 상세 — 프로비저닝 에디터가 편집할 model(구조+layout) 포함. */
328
586
  static detail(domainId: string, instanceId: string): Promise<any | null>;
329
587
  /**
330
588
  * 라이브 바인딩 브리지(P3, ADR-0018) — 트윈 엔티티 상태를 `data(tag=엔티티id)` 채널로 publish.
331
589
  * 보드 컴포넌트가 tag 로 구독(board-ui provider)해 `component.data` 로 라이브 갱신. delta 시에만(희소).
332
590
  * tag=엔티티 id(데모=단일 인스턴스). 멀티 인스턴스/보드 재사용 시 tag 네임스페이스는 후속.
333
591
  */
592
+ /** 방송 실패 로그 조절 — 창마다 한 줄(막힌 구독자는 초당 수십 번 실패한다). */
593
+ private static publishDrops;
594
+ private static readonly PUBLISH_DROP_LOG_MS;
595
+ /**
596
+ * 한 번의 방송 — **구독자 하나가 호스트를 죽이지 못하게.**
597
+ *
598
+ * ── 무엇이 죽였나 (2026-08-14) ─────────────────────────────────────────────
599
+ * 밀린 push 가 1024를 넘으면 pubsub 이 던진다(`RepeaterOverflowError`). 그 방송은 타이머 콜백
600
+ * 안에서 일어나므로 예외가 잡히는 곳 없이 올라가 **프로세스가 끝났다** — 트윈 14개가 도는 호스트가
601
+ * 소비를 멈춘 구독자 하나 때문에 통째로.
602
+ *
603
+ * 못 보낸 것은 **사실로 남긴다**(횟수를 세고 창마다 한 줄 남긴다). 삼키면 「보냈는데 화면이 낡았다」가
604
+ * 되고, 그건 가장 찾기 어려운 부류다.
605
+ */
606
+ private static publishGuarded;
334
607
  static publishEntityData(inst: InstanceRuntime): void;
335
608
  static persist(domainId: string, instanceId: string, msg: any): Promise<void>;
336
609
  /**
337
610
  * 재부팅 복구 / 시간여행 — DB 저널을 replay 해 상태 재구성.
338
- * board 는 레지스트리(TwinInstance)에서, 이벤트는 TwinEvent(revision ASC)에서.
611
+ * model 는 레지스트리(TwinInstance)에서, 이벤트는 TwinEvent(revision ASC)에서.
339
612
  * 커서 두 축(runtime-state-model §4): **시각(untilTime, 사용자 모국어·공간 공통축)** 우선, 없으면 리비전(untilRevision, 렌즈 내부).
340
613
  * - untilTime 주면 `eventTime ≤ T` 인 이벤트만(그 시점 watermark) — 공동배치 여러 트윈을 하나의 시각 T로 통일 해소.
341
614
  * - 둘 다 없으면 최신(라이브 인메모리 진실).
@@ -353,39 +626,127 @@ export declare class TwinEngine {
353
626
  /** 정지 훅 — 인스턴스 정지 시 부수자원 정리(예: reference-live 피드 unsubscribe). 순환 임포트 없이 결선. */
354
627
  static stopHooks: ((id: string) => void)[];
355
628
  static onStop(fn: (id: string) => void): void;
356
- static stop(id: string): Promise<void>;
357
- static runtime(id: string): TwinRuntimeType | undefined;
629
+ static stop(domainId: string, id: string): Promise<void>;
630
+ /**
631
+ * 같은 현장 트윈들의 **설비 상태**를 커널에 넘긴다 — 커널이 요청할 때만.
632
+ *
633
+ * ── 경계 (2026-08-14) ──────────────────────────────────────────────────────
634
+ * 호스트가 아는 것은 **누가 같은 현장에 있는가** 하나다. 무엇을 읽고 그것을 어떻게 부하로 바꿀지는
635
+ * 커널이 정한다(계수는 트윈의 모델이 선언한다). 호스트가 kW 를 계산해 주면 트윈마다 다른 규칙이
636
+ * 생기고, 그 규칙은 어디에도 적혀 있지 않게 된다.
637
+ *
638
+ * 상태만 넘긴다. 스냅샷을 통째로 넘기면 상태 크기에 비례한 비용을 매 tick 치르게 된다 —
639
+ * 설비 목록은 그 트윈의 커널이 이미 들고 있는 것이라 훑는 값이 싸다.
640
+ */
641
+ private static feedPeerEquipment;
642
+ private static tickGuarded;
643
+ /**
644
+ * 호스트를 굶기는 트윈을 멈춘다 — **도는 척하는 것보다 멈춘 것이 낫다.**
645
+ *
646
+ * 굶김 문턱을 넘는 틱이 연속 `STARVE_STREAK` 번이면 그 트윈은 구조적으로 무겁다(우연이 아니다).
647
+ * 문턱 아래로 한 번만 내려와도 연속을 끊는다 — 무거운 순간 하나로 트윈을 내리지 않는다.
648
+ */
649
+ private static guardStarvation;
650
+ /** 멈추고 **이유를 남긴다** — 이유 없는 「정지」는 사람이 자기가 멈춘 것으로 읽는다. */
651
+ private static stopWithNote;
652
+ /** 이 트윈이 스스로 멈춘 이유(있으면) — 화면이 옮겨 말한다. */
653
+ static stopNoteOf(domainId: string, id: string): StopNote | undefined;
654
+ /**
655
+ * 이 트윈이 **지금 실행 중인가** — 판정의 집 하나.
656
+ *
657
+ * "스냅샷이 있나" 로는 답이 되지 않는다: 웜스타트가 되살린 상태가 캐시에 남아 있으면 멈춘 트윈도
658
+ * 스냅샷을 낸다. 그것을 관측 중으로 읽으면 화면이 **멈춘 트윈의 작업을 0 건이라고 단언**한다
659
+ * (실제로 그렇게 나왔다 — 관측이 없는 것과 0 건은 다르다는 이 프로젝트의 규율을 화면이 어겼다).
660
+ *
661
+ * 목록이 쓰는 것과 **같은 술어**다(`list()` 의 `running`) — 두 벌이면 어긋난다.
662
+ */
663
+ static isRunning(domainId: string, id: string): boolean;
664
+ static runtime(domainId: string, id: string): TwinRuntimeType | undefined;
665
+ static dispatchCommand(domainId: string, instanceId: string, command: any): Promise<{
666
+ accepted: boolean;
667
+ error?: string;
668
+ errorCode?: string;
669
+ errorParams?: Record<string, string | number>;
670
+ }>;
358
671
  /**
359
672
  * 도메인 소유 게이트 — 인스턴스가 이 도메인 소유일 때만 true(테넌트 격리).
360
673
  * 없거나 다른 도메인이면 false. 노출 리졸버(per-id metrics/attentions/state/stop/forecast)가
361
674
  * this.instances[id] 를 만지기 전에 반드시 이걸로 확인해야 한다. 인스턴스 id 는 추측 가능하므로
362
675
  * 검증 없이 접근하면 크로스테넌트 읽기/정지가 가능해진다.
363
676
  */
677
+ /**
678
+ * 이 런타임의 **관측 모드** — `'live'`(외부 실물을 미러) 또는 `'sim'`(커널이 실행한다). 기동 중이 아니면 없다.
679
+ *
680
+ * 소비처가 `instances[id].mode` 를 직접 읽던 자리를 대신한다. 레지스트리를 밖에 열면 도메인 확인이
681
+ * 자리마다 제각각이 되고, 실제로 그렇게 됐다(테넌트 격리 전수 확인, 2026-08-06).
682
+ */
683
+ static modeOf(domainId: string, id: string): 'live' | 'sim' | undefined;
364
684
  static owns(domainId: string, id: string): boolean;
365
685
  /**
366
686
  * 이 트윈이 이 테넌트 것인가 — **떠 있든 아니든.**
367
687
  *
368
- * `owns()` 는 **떠 있는** 런타임만 안다. 그것을 이력 조회의 관문으로 쓰면, 꺼진 트윈의 저널을
688
+ * `owns()` 는 **기동 중인** 런타임만 안다. 그것을 이력 조회의 관문으로 쓰면, 꺼진 트윈의 저널을
369
689
  * 읽으려 할 때 "이 테넌트에 없다" 는 답이 돌아온다 — 두 가지가 틀렸다. 첫째, 저널은 트윈이 꺼져
370
690
  * 있을 때 **가장 필요한 것**이다(그게 이력의 존재 이유다). 둘째, 그 문장은 남의 것이라는 뜻이라
371
- * 사용자가 권한 문제로 오해한다. 실제로는 그냥 안 돌고 있을 뿐이다.
691
+ * 사용자가 권한 문제로 오해한다. 실제로는 그냥 실행 중이 아닐 뿐이다.
372
692
  *
373
693
  * 소유는 **등록부**가 안다. 이력·집계처럼 런타임과 무관한 질문은 이쪽에 묻는다.
374
694
  */
375
695
  static ownsRegistered(domainId: string, instanceId: string): Promise<boolean>;
696
+ /**
697
+ * **이 공간의 인스턴스들** — 한 현실을 여러 렌즈가 비추므로, 공간을 물으면 그 렌즈 전부를 답한다.
698
+ *
699
+ * 화면이 이 규칙을 손으로 짜지 않게 서버가 답한다. 예측 화면은 같은 확장을 **한 파일에서 두 번**
700
+ * 복제하고 있었다(전체 목록을 받아 클라이언트에서 걸렀다) — 규칙이 흩어지면 한쪽만 고쳐진다.
701
+ *
702
+ * 떠 있지 않은 것도 포함한다: 공간에 무엇이 있는지는 기동 여부와 다른 사실이다.
703
+ */
704
+ static instanceIdsOfSpace(domainId: string, spaceId: string): Promise<string[]>;
705
+ /**
706
+ * **이 공간에서 봐야 할 것** — 공간의 모든 렌즈에서 신호를 모은다.
707
+ *
708
+ * 합집합이 그대로 뜻이 있는 유일한 렌즈다(예측은 합칠 수 없다 — P50 두 개를 더할 수 없다).
709
+ * 정렬·잘라내기는 화면과 **같은 규칙**을 쓴다(`digestAttentions`) — 서버가 고른 상위 N 이 화면이
710
+ * 고를 N 과 달라지면 그 어긋남은 아무 데서도 오류로 드러나지 않는다.
711
+ *
712
+ * 신호마다 어느 트윈에서 왔는지(`instanceId`)를 붙인다. 공간에서 보면 같은 자리 id 가 렌즈마다
713
+ * 다른 것을 가리킬 수 있고, 조치는 결국 그 트윈에 보내야 한다.
714
+ */
715
+ static attentionsOfSpace(domainId: string, spaceId: string, limit?: number): Promise<{
716
+ attentions: any[];
717
+ attentionTotal: number;
718
+ severityByLocation: Record<string, string>;
719
+ }>;
376
720
  /** 라이브 커널(ForecastTwin) — forecast/divergence 예측 연산용. */
377
- static kernel(id: string): any;
721
+ static kernel(domainId: string, id: string): any;
378
722
  /** 라이브 처리량 계측 스냅샷(모니터, ④-1) — 내부 누적(_acc*) 제외한 공개 지표. live 아니면 null. */
379
- static metrics(id: string): any;
723
+ static metrics(domainId: string, id: string): any;
724
+ /**
725
+ * 부하 계기판만 따로 — **시뮬 트윈도 포함한다.**
726
+ *
727
+ * `metrics()` 는 라이브 지표(`inst.metrics`)가 있어야 무언가를 돌려준다. 그런데 이벤트 루프를 점유하는
728
+ * 것은 주로 **시뮬 틱**이고, 시뮬 인스턴스에는 그 지표가 없어 통째로 안 보였다.
729
+ */
730
+ static load(domainId: string, id: string): any;
731
+ /**
732
+ * **한 곳에서 보는 전체 부하** — 몇 개가 실행 중이고, 누가 루프를 점유하고 있나.
733
+ *
734
+ * 시뮬 트윈도 포함한다(`metrics()` 는 라이브 지표가 있어야 답해서 시뮬이 통째로 안 보였다).
735
+ */
736
+ static fleet(domainId?: string): any;
737
+ /** 이 트윈에서 fork 가 만들어졌다 — 예측 한 번이 수십 개를 만든다. */
738
+ static countForks(domainId: string, id: string, count: number): void;
739
+ /** 엔진 밖(예측 질의 등)에서 무거운 작업을 잰다 — 같은 계기판에 모인다. */
740
+ static recordLoad(domainId: string, id: string, phase: LoadPhase, tookMs: number): void;
380
741
  /** 전체 라이브 인스턴스 계측(모니터 대시보드용). */
381
742
  static allMetrics(domainId?: string): Promise<any[]>;
382
743
  /**
383
744
  * 예측용 커널을 **임의 시각 T 기준**으로 재구성 — 과거-vantage 예측(백테스트)·"그때 서서 본 미래".
384
- * recover(untilTime)로 T 시점 상태를, T 이하 오더 관측을 모아 hydrate → monteCarloForecast 가 T 에서 앞으로 굴린다.
745
+ * recover(untilTime)로 T 시점 상태를, T 이하 오더 관측을 모아 hydrate → monteCarloForecast 가 T 에서 앞으로 실행한다.
385
746
  * sim/live 무관(저널 기반 재구성). untilTime 생략 시 최신. 도메인 스코프(reg·journal 조회가 domainId).
386
747
  */
387
748
  static buildForecastKernelAt(domainId: string, instanceId: string, untilTime?: string): Promise<any | null>;
388
749
  /** 현재 전체 스냅샷 — 라이브 우선, 없으면 저널 복구 캐시. */
389
- static snapshot(id: string): any;
750
+ static snapshot(domainId: string, id: string): any;
390
751
  }
391
752
  export {};