@things-factory/headless-twin 10.0.11 → 10.0.13

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 (369) hide show
  1. package/dist-server/engine/canonical-ingest.d.ts +81 -3
  2. package/dist-server/engine/canonical-ingest.js +89 -10
  3. package/dist-server/engine/canonical-ingest.js.map +1 -1
  4. package/dist-server/engine/command-routing.js +1 -1
  5. package/dist-server/engine/command-routing.js.map +1 -1
  6. package/dist-server/engine/declared-stimulus.d.ts +43 -0
  7. package/dist-server/engine/declared-stimulus.js +57 -0
  8. package/dist-server/engine/declared-stimulus.js.map +1 -0
  9. package/dist-server/engine/index.d.ts +5 -0
  10. package/dist-server/engine/index.js +6 -0
  11. package/dist-server/engine/index.js.map +1 -1
  12. package/dist-server/engine/ingest-health.d.ts +335 -0
  13. package/dist-server/engine/ingest-health.js +434 -0
  14. package/dist-server/engine/ingest-health.js.map +1 -0
  15. package/dist-server/engine/integration-coverage.d.ts +76 -0
  16. package/dist-server/engine/integration-coverage.js +73 -0
  17. package/dist-server/engine/integration-coverage.js.map +1 -0
  18. package/dist-server/engine/integration-probes.d.ts +65 -0
  19. package/dist-server/engine/integration-probes.js +100 -0
  20. package/dist-server/engine/integration-probes.js.map +1 -0
  21. package/dist-server/engine/integration-runner.d.ts +45 -0
  22. package/dist-server/engine/integration-runner.js +59 -0
  23. package/dist-server/engine/integration-runner.js.map +1 -0
  24. package/dist-server/engine/integration-target-profile.d.ts +57 -0
  25. package/dist-server/engine/integration-target-profile.js +79 -0
  26. package/dist-server/engine/integration-target-profile.js.map +1 -0
  27. package/dist-server/engine/kpi-fold.d.ts +39 -0
  28. package/dist-server/engine/kpi-fold.js +68 -5
  29. package/dist-server/engine/kpi-fold.js.map +1 -1
  30. package/dist-server/engine/kpi-query.d.ts +3 -3
  31. package/dist-server/engine/kpi-query.js +132 -18
  32. package/dist-server/engine/kpi-query.js.map +1 -1
  33. package/dist-server/engine/live-feed-registry.d.ts +1 -1
  34. package/dist-server/engine/live-feed-registry.js +3 -17
  35. package/dist-server/engine/live-feed-registry.js.map +1 -1
  36. package/dist-server/engine/load-meter.d.ts +1 -1
  37. package/dist-server/engine/load-meter.js +12 -3
  38. package/dist-server/engine/load-meter.js.map +1 -1
  39. package/dist-server/engine/local-declarations.d.ts +3 -6
  40. package/dist-server/engine/local-declarations.js +97 -16
  41. package/dist-server/engine/local-declarations.js.map +1 -1
  42. package/dist-server/engine/log.d.ts +18 -0
  43. package/dist-server/engine/log.js +80 -0
  44. package/dist-server/engine/log.js.map +1 -0
  45. package/dist-server/engine/loop-lag.d.ts +54 -0
  46. package/dist-server/engine/loop-lag.js +87 -0
  47. package/dist-server/engine/loop-lag.js.map +1 -0
  48. package/dist-server/engine/measured-yield.d.ts +42 -0
  49. package/dist-server/engine/measured-yield.js +75 -0
  50. package/dist-server/engine/measured-yield.js.map +1 -0
  51. package/dist-server/engine/model-gap.d.ts +108 -0
  52. package/dist-server/engine/model-gap.js +95 -0
  53. package/dist-server/engine/model-gap.js.map +1 -0
  54. package/dist-server/engine/operation-basis.d.ts +16 -0
  55. package/dist-server/engine/operation-basis.js +20 -2
  56. package/dist-server/engine/operation-basis.js.map +1 -1
  57. package/dist-server/engine/property-effects.js +17 -0
  58. package/dist-server/engine/property-effects.js.map +1 -1
  59. package/dist-server/engine/restart-policy.d.ts +13 -0
  60. package/dist-server/engine/restart-policy.js +52 -0
  61. package/dist-server/engine/restart-policy.js.map +1 -0
  62. package/dist-server/engine/runtime-key.js +1 -1
  63. package/dist-server/engine/runtime-key.js.map +1 -1
  64. package/dist-server/engine/spec-coverage.d.ts +8 -0
  65. package/dist-server/engine/spec-coverage.js +3 -1
  66. package/dist-server/engine/spec-coverage.js.map +1 -1
  67. package/dist-server/engine/stage-path.d.ts +83 -0
  68. package/dist-server/engine/stage-path.js +118 -0
  69. package/dist-server/engine/stage-path.js.map +1 -0
  70. package/dist-server/engine/twin-engine.d.ts +400 -31
  71. package/dist-server/engine/twin-engine.js +1198 -187
  72. package/dist-server/engine/twin-engine.js.map +1 -1
  73. package/dist-server/index.js +35 -3
  74. package/dist-server/index.js.map +1 -1
  75. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.d.ts +5 -0
  76. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js +58 -0
  77. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +1 -0
  78. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.d.ts +5 -0
  79. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js +55 -0
  80. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +1 -0
  81. package/dist-server/migrations/index.js +7 -1
  82. package/dist-server/migrations/index.js.map +1 -1
  83. package/dist-server/service/index.d.ts +5 -2
  84. package/dist-server/service/index.js +18 -7
  85. package/dist-server/service/index.js.map +1 -1
  86. package/dist-server/service/reference/control-routing.d.ts +14 -0
  87. package/dist-server/service/reference/control-routing.js +64 -0
  88. package/dist-server/service/reference/control-routing.js.map +1 -0
  89. package/dist-server/service/reference/discovery-result.d.ts +1 -1
  90. package/dist-server/service/reference/discovery-result.js +1 -1
  91. package/dist-server/service/reference/discovery-result.js.map +1 -1
  92. package/dist-server/service/reference/index.d.ts +5 -1
  93. package/dist-server/service/reference/index.js +8 -1
  94. package/dist-server/service/reference/index.js.map +1 -1
  95. package/dist-server/service/reference/reference-adapter.d.ts +251 -3
  96. package/dist-server/service/reference/reference-adapter.js +43 -1
  97. package/dist-server/service/reference/reference-adapter.js.map +1 -1
  98. package/dist-server/service/reference/reference-assessment.d.ts +68 -0
  99. package/dist-server/service/reference/reference-assessment.js +136 -0
  100. package/dist-server/service/reference/reference-assessment.js.map +1 -0
  101. package/dist-server/service/reference/reference-live.d.ts +12 -1
  102. package/dist-server/service/reference/reference-live.js +119 -14
  103. package/dist-server/service/reference/reference-live.js.map +1 -1
  104. package/dist-server/service/reference/reference-master.d.ts +47 -1
  105. package/dist-server/service/reference/reference-master.js +34 -4
  106. package/dist-server/service/reference/reference-master.js.map +1 -1
  107. package/dist-server/service/reference/reference-probe.d.ts +92 -0
  108. package/dist-server/service/reference/reference-probe.js +186 -0
  109. package/dist-server/service/reference/reference-probe.js.map +1 -0
  110. package/dist-server/service/reference/reference-progress-subscription.d.ts +17 -0
  111. package/dist-server/service/reference/reference-progress-subscription.js +94 -0
  112. package/dist-server/service/reference/reference-progress-subscription.js.map +1 -0
  113. package/dist-server/service/reference/reference-progress.d.ts +38 -0
  114. package/dist-server/service/reference/reference-progress.js +71 -0
  115. package/dist-server/service/reference/reference-progress.js.map +1 -0
  116. package/dist-server/service/reference/reference-resolver.d.ts +3 -3
  117. package/dist-server/service/reference/reference-resolver.js +242 -58
  118. package/dist-server/service/reference/reference-resolver.js.map +1 -1
  119. package/dist-server/service/reference/twin-reference.d.ts +32 -0
  120. package/dist-server/service/reference/twin-reference.js +10 -0
  121. package/dist-server/service/reference/twin-reference.js.map +1 -1
  122. package/dist-server/service/twin-audit/command-audit.d.ts +34 -0
  123. package/dist-server/service/twin-audit/command-audit.js +15 -1
  124. package/dist-server/service/twin-audit/command-audit.js.map +1 -1
  125. package/dist-server/service/twin-audit/twin-audit-event.d.ts +3 -0
  126. package/dist-server/service/twin-audit/twin-audit-event.js +10 -0
  127. package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -1
  128. package/dist-server/service/twin-control/twin-control-mutation.d.ts +15 -2
  129. package/dist-server/service/twin-control/twin-control-mutation.js +88 -36
  130. package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
  131. package/dist-server/service/twin-event/journal-count.d.ts +21 -0
  132. package/dist-server/service/twin-event/journal-count.js +26 -0
  133. package/dist-server/service/twin-event/journal-count.js.map +1 -0
  134. package/dist-server/service/twin-event/twin-event-keys.d.ts +9 -0
  135. package/dist-server/service/twin-event/twin-event-keys.js +15 -18
  136. package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
  137. package/dist-server/service/twin-event/twin-event-type.d.ts +3 -1
  138. package/dist-server/service/twin-event/twin-event-type.js +18 -1
  139. package/dist-server/service/twin-event/twin-event-type.js.map +1 -1
  140. package/dist-server/service/twin-event/twin-event.d.ts +1 -0
  141. package/dist-server/service/twin-event/twin-event.js +9 -1
  142. package/dist-server/service/twin-event/twin-event.js.map +1 -1
  143. package/dist-server/service/twin-forecast/twin-forecast-query.js +2 -1
  144. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
  145. package/dist-server/service/twin-ingest-window/index.d.ts +5 -0
  146. package/dist-server/service/twin-ingest-window/index.js +10 -0
  147. package/dist-server/service/twin-ingest-window/index.js.map +1 -0
  148. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.d.ts +12 -0
  149. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js +123 -0
  150. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +1 -0
  151. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.d.ts +1 -0
  152. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js +51 -0
  153. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +1 -0
  154. package/dist-server/service/twin-ingest-window/twin-ingest-window.d.ts +16 -0
  155. package/dist-server/service/twin-ingest-window/twin-ingest-window.js +108 -0
  156. package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +1 -0
  157. package/dist-server/service/twin-instance/twin-instance.d.ts +1 -1
  158. package/dist-server/service/twin-instance/twin-instance.js +2 -2
  159. package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
  160. package/dist-server/service/twin-journal/twin-journal-query.js +58 -5
  161. package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
  162. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +14 -0
  163. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +74 -3
  164. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
  165. package/dist-server/service/twin-metrics/twin-metrics-query.d.ts +1 -0
  166. package/dist-server/service/twin-metrics/twin-metrics-query.js +78 -3
  167. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
  168. package/dist-server/service/twin-model/axis-journal-evidence.d.ts +2 -0
  169. package/dist-server/service/twin-model/axis-journal-evidence.js +89 -0
  170. package/dist-server/service/twin-model/axis-journal-evidence.js.map +1 -0
  171. package/dist-server/service/twin-model/epcis-coverage.d.ts +1 -1
  172. package/dist-server/service/twin-model/epcis-coverage.js +19 -7
  173. package/dist-server/service/twin-model/epcis-coverage.js.map +1 -1
  174. package/dist-server/service/twin-model/iec61850-coverage.d.ts +1 -1
  175. package/dist-server/service/twin-model/iec61850-coverage.js +18 -7
  176. package/dist-server/service/twin-model/iec61850-coverage.js.map +1 -1
  177. package/dist-server/service/twin-model/isa95-coverage.d.ts +14 -0
  178. package/dist-server/service/twin-model/isa95-coverage.js +23 -9
  179. package/dist-server/service/twin-model/isa95-coverage.js.map +1 -1
  180. package/dist-server/service/twin-model/item-ref.d.ts +24 -0
  181. package/dist-server/service/twin-model/item-ref.js +88 -0
  182. package/dist-server/service/twin-model/item-ref.js.map +1 -0
  183. package/dist-server/service/twin-model/name-index.d.ts +36 -0
  184. package/dist-server/service/twin-model/name-index.js +116 -0
  185. package/dist-server/service/twin-model/name-index.js.map +1 -0
  186. package/dist-server/service/twin-model/project-structure.js +1 -1
  187. package/dist-server/service/twin-model/project-structure.js.map +1 -1
  188. package/dist-server/service/twin-model/status-tally.d.ts +9 -0
  189. package/dist-server/service/twin-model/status-tally.js +37 -0
  190. package/dist-server/service/twin-model/status-tally.js.map +1 -0
  191. package/dist-server/service/twin-model/twin-lineage-query.js +40 -12
  192. package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
  193. package/dist-server/service/twin-model/twin-model-item-query.js +38 -39
  194. package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
  195. package/dist-server/service/twin-model/twin-model-query.js +157 -5
  196. package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
  197. package/dist-server/service/twin-model/twin-model-tree-query.js +7 -0
  198. package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
  199. package/dist-server/service/twin-readiness/index.d.ts +2 -0
  200. package/dist-server/service/twin-readiness/index.js +6 -0
  201. package/dist-server/service/twin-readiness/index.js.map +1 -0
  202. package/dist-server/service/twin-readiness/twin-readiness-query.d.ts +3 -0
  203. package/dist-server/service/twin-readiness/twin-readiness-query.js +103 -0
  204. package/dist-server/service/twin-readiness/twin-readiness-query.js.map +1 -0
  205. package/dist-server/service/twin-space/twin-space-resolver.d.ts +2 -2
  206. package/dist-server/service/twin-space/twin-space-resolver.js +5 -4
  207. package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
  208. package/dist-shared/entity-delta.d.ts +23 -3
  209. package/dist-shared/entity-delta.js +12 -8
  210. package/dist-shared/entity-delta.js.map +1 -1
  211. package/dist-shared/kpi-broadcast.js +1 -1
  212. package/dist-shared/kpi-broadcast.js.map +1 -1
  213. package/dist-shared/touched-items.d.ts +7 -0
  214. package/dist-shared/touched-items.js +80 -0
  215. package/dist-shared/touched-items.js.map +1 -0
  216. package/package.json +7 -7
  217. package/server/engine/canonical-ingest.ts +164 -15
  218. package/server/engine/command-routing.ts +1 -1
  219. package/server/engine/declared-stimulus.ts +66 -0
  220. package/server/engine/index.ts +6 -0
  221. package/server/engine/ingest-health.ts +704 -0
  222. package/server/engine/integration-coverage.ts +147 -0
  223. package/server/engine/integration-probes.ts +144 -0
  224. package/server/engine/integration-runner.ts +95 -0
  225. package/server/engine/integration-target-profile.ts +103 -0
  226. package/server/engine/kpi-fold.ts +101 -5
  227. package/server/engine/kpi-query.ts +137 -23
  228. package/server/engine/live-feed-registry.ts +4 -3
  229. package/server/engine/load-meter.ts +12 -3
  230. package/server/engine/local-declarations.ts +97 -19
  231. package/server/engine/log.ts +72 -0
  232. package/server/engine/loop-lag.ts +120 -0
  233. package/server/engine/measured-yield.ts +89 -0
  234. package/server/engine/model-gap.ts +168 -0
  235. package/server/engine/operation-basis.ts +33 -2
  236. package/server/engine/property-effects.ts +17 -0
  237. package/server/engine/restart-policy.ts +55 -0
  238. package/server/engine/runtime-key.ts +1 -1
  239. package/server/engine/spec-coverage.ts +23 -3
  240. package/server/engine/stage-path.ts +172 -0
  241. package/server/engine/twin-engine.ts +1318 -186
  242. package/server/index.ts +36 -3
  243. package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +54 -0
  244. package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +53 -0
  245. package/server/migrations/index.ts +7 -1
  246. package/server/service/index.ts +11 -0
  247. package/server/service/reference/control-routing.ts +62 -0
  248. package/server/service/reference/discovery-result.ts +1 -1
  249. package/server/service/reference/index.ts +7 -1
  250. package/server/service/reference/reference-adapter.ts +275 -5
  251. package/server/service/reference/reference-assessment.ts +215 -0
  252. package/server/service/reference/reference-live.ts +126 -14
  253. package/server/service/reference/reference-master.ts +64 -4
  254. package/server/service/reference/reference-probe.ts +264 -0
  255. package/server/service/reference/reference-progress-subscription.ts +73 -0
  256. package/server/service/reference/reference-progress.ts +95 -0
  257. package/server/service/reference/reference-resolver.ts +246 -19
  258. package/server/service/reference/twin-reference.ts +39 -1
  259. package/server/service/twin-audit/command-audit.ts +34 -1
  260. package/server/service/twin-audit/twin-audit-event.ts +20 -0
  261. package/server/service/twin-control/twin-control-mutation.ts +78 -30
  262. package/server/service/twin-event/journal-count.ts +53 -0
  263. package/server/service/twin-event/twin-event-keys.ts +16 -1
  264. package/server/service/twin-event/twin-event-type.ts +26 -2
  265. package/server/service/twin-event/twin-event.ts +7 -0
  266. package/server/service/twin-forecast/twin-forecast-query.ts +2 -1
  267. package/server/service/twin-ingest-window/index.ts +7 -0
  268. package/server/service/twin-ingest-window/twin-ingest-window-query.ts +125 -0
  269. package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +57 -0
  270. package/server/service/twin-ingest-window/twin-ingest-window.ts +113 -0
  271. package/server/service/twin-instance/twin-instance.ts +16 -10
  272. package/server/service/twin-journal/twin-journal-query.ts +59 -5
  273. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +79 -4
  274. package/server/service/twin-metrics/twin-metrics-query.ts +81 -3
  275. package/server/service/twin-model/axis-journal-evidence.ts +57 -0
  276. package/server/service/twin-model/epcis-coverage.ts +2 -8
  277. package/server/service/twin-model/iec61850-coverage.ts +2 -8
  278. package/server/service/twin-model/isa95-coverage.ts +22 -9
  279. package/server/service/twin-model/item-ref.ts +80 -0
  280. package/server/service/twin-model/name-index.ts +94 -0
  281. package/server/service/twin-model/project-structure.ts +1 -1
  282. package/server/service/twin-model/status-tally.ts +37 -0
  283. package/server/service/twin-model/twin-lineage-query.ts +38 -9
  284. package/server/service/twin-model/twin-model-item-query.ts +26 -27
  285. package/server/service/twin-model/twin-model-query.ts +156 -5
  286. package/server/service/twin-model/twin-model-tree-query.ts +7 -0
  287. package/server/service/twin-readiness/index.ts +3 -0
  288. package/server/service/twin-readiness/twin-readiness-query.ts +96 -0
  289. package/server/service/twin-space/twin-space-resolver.ts +5 -4
  290. package/shared/entity-delta.ts +31 -7
  291. package/shared/kpi-broadcast.ts +1 -1
  292. package/shared/touched-items.ts +73 -0
  293. package/test/adopt-structure-live.test.ts +7 -7
  294. package/test/axis-journal-evidence.test.ts +71 -0
  295. package/test/axis-read.test.ts +101 -1
  296. package/test/boot-resume.test.ts +93 -27
  297. package/test/broadcast-cost-baseline.test.ts +200 -0
  298. package/test/broadcast-period.test.ts +58 -0
  299. package/test/canonical-ingest-vocabularies.test.ts +36 -1
  300. package/test/canonical-quantity-door.test.ts +61 -0
  301. package/test/command-routing.test.ts +1 -1
  302. package/test/control-capability.test.ts +103 -0
  303. package/test/declared-location-types.test.ts +89 -0
  304. package/test/declared-stimulus.test.ts +88 -0
  305. package/test/discovery-result.test.ts +1 -1
  306. package/test/duration-estimators.test.ts +1 -1
  307. package/test/entity-delta.test.ts +2 -2
  308. package/test/ingest-bench.test.ts +3 -3
  309. package/test/ingest-health-engine.test.ts +248 -0
  310. package/test/ingest-health-wiring.test.ts +119 -0
  311. package/test/ingest-health.test.ts +306 -0
  312. package/test/ingest-history.test.ts +247 -0
  313. package/test/ingest-running-guard.test.ts +5 -5
  314. package/test/instance-cache-lifecycle.test.ts +1 -1
  315. package/test/integration-probes.test.ts +103 -0
  316. package/test/integration-runner.test.ts +95 -0
  317. package/test/item-ref.test.ts +78 -0
  318. package/test/journal-read-discipline.test.ts +177 -0
  319. package/test/journal-retention.test.ts +133 -0
  320. package/test/journal-sort-axis.test.ts +142 -0
  321. package/test/journal-write-door.test.ts +110 -0
  322. package/test/journal-write-trend.test.ts +115 -0
  323. package/test/kernel-kind-guard.test.ts +4 -4
  324. package/test/kpi-baseline-db.test.ts +1 -1
  325. package/test/kpi-fold.test.ts +90 -3
  326. package/test/kpi-query-bench.test.ts +3 -3
  327. package/test/lineage-survives-restart.test.ts +20 -4
  328. package/test/live-cursor-wiring.test.ts +87 -0
  329. package/test/live-feed-registry.test.ts +15 -7
  330. package/test/live-kernel-facts.test.ts +7 -7
  331. package/test/live-mirror-parity.test.ts +6 -0
  332. package/test/load-meter.test.ts +29 -15
  333. package/test/local-declarations.test.ts +109 -2
  334. package/test/log-stamp.test.ts +59 -0
  335. package/test/loop-lag.test.ts +82 -0
  336. package/test/measured-yield.test.ts +90 -0
  337. package/test/model-gap.test.ts +153 -0
  338. package/test/oee-accumulator.test.ts +4 -0
  339. package/test/operation-basis.test.ts +28 -1
  340. package/test/operational-vocabulary.test.ts +108 -0
  341. package/test/operations-capability-db.test.ts +4 -4
  342. package/test/project-structure-db.test.ts +1 -1
  343. package/test/projection-reaches-screen.test.ts +1 -1
  344. package/test/property-effects.test.ts +28 -0
  345. package/test/read-failure-visible.test.ts +145 -0
  346. package/test/reference-grounding.test.ts +70 -0
  347. package/test/resolve-ts-siblings.mjs +52 -0
  348. package/test/restart-policy.test.ts +111 -0
  349. package/test/resync-origin-site.test.ts +7 -1
  350. package/test/revision-axis.test.ts +93 -0
  351. package/test/runtime-key.test.ts +2 -2
  352. package/test/scale-twin-bench.test.ts +2 -2
  353. package/test/source-outcome-audit.test.ts +104 -0
  354. package/test/spec-coverage.test.ts +1 -1
  355. package/test/stage-path.test.ts +95 -0
  356. package/test/standard-coverage.test.ts +15 -3
  357. package/test/status-tally.test.ts +55 -0
  358. package/test/structure-revision-db.test.ts +31 -27
  359. package/test/tenant-registry-db.test.ts +3 -3
  360. package/test/time-range.test.ts +152 -0
  361. package/test/touched-items.test.ts +61 -0
  362. package/test/twin-event-keys.test.ts +10 -2
  363. package/test/twin-model-item-db.test.ts +5 -3
  364. package/test/twin-model-tree-db.test.ts +7 -7
  365. package/test/twin-origin-resync.test.ts +4 -4
  366. package/test/warm-start-seam.test.ts +4 -0
  367. package/test/yield-loop.test.ts +199 -0
  368. package/tsconfig.shared.tsbuildinfo +1 -1
  369. package/tsconfig.tsbuildinfo +1 -1
@@ -2,9 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TwinReferenceResolver = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const type_graphql_1 = require("type-graphql");
6
5
  const shell_1 = require("@things-factory/shell");
6
+ const reference_progress_js_1 = require("./reference-progress.js");
7
+ const reference_assessment_js_1 = require("./reference-assessment.js");
8
+ const type_graphql_1 = require("type-graphql");
9
+ const shell_2 = require("@things-factory/shell");
7
10
  const index_js_1 = require("../../engine/index.js");
11
+ const restart_policy_js_1 = require("../../engine/restart-policy.js");
8
12
  const twin_kernel_1 = require("@operato/twin-kernel");
9
13
  const knob_defaults_js_1 = require("./knob-defaults.js");
10
14
  const reference_master_js_1 = require("./reference-master.js");
@@ -84,7 +88,7 @@ async function resolveSiteEquipmentKnobs(knobs, effective, domainId, spaceId) {
84
88
  continue;
85
89
  }
86
90
  if (ids === undefined) {
87
- const rows = await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId }, spaceId } });
91
+ const rows = await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId }, spaceId } });
88
92
  const seen = new Map();
89
93
  for (const r of rows) {
90
94
  for (const e of (0, twin_kernel_1.readBoardEquipment)(r.model ?? {})) {
@@ -106,7 +110,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
106
110
  const domainId = context.state.domain.id;
107
111
  const out = [];
108
112
  for (const m of (0, reference_registry_js_1.listReferences)()) {
109
- const reg = await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: m.source } });
113
+ const reg = await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: m.source } });
110
114
  out.push({
111
115
  source: m.source,
112
116
  system: m.system,
@@ -121,7 +125,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
121
125
  return out;
122
126
  }
123
127
  /** 소스를 인제스트 → 공간 + 인스턴스 생성(provision). start 면 기동까지. */
124
- async importFromReference(source, context, start) {
128
+ async importFromReference(source, restartPolicy, context, start) {
125
129
  const master = (0, reference_registry_js_1.getReference)(source);
126
130
  if (!master)
127
131
  return { ok: false, error: `unknown reference source: ${source}` };
@@ -130,7 +134,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
130
134
  /* 어디서 왔는지 남긴다 — 이것이 없으면 이 트윈은 두 번 다시 읽을 수 없다.
131
135
  이 경로는 **메모리에 등록된 마스터 하나**를 그대로 쓰므로 사이트 서술자가 없다(사이트 정체를
132
136
  적을 것이 없다). 다시 읽기도 같은 등록본을 집으므로 사이트를 찾을 필요가 없다. */
133
- const res = await index_js_1.TwinEngine.ingestMaster(domainId, { ...master, origin: { kind: 'reference', source } }, undefined, context.state.user);
137
+ const res = await index_js_1.TwinEngine.ingestMaster(domainId, { ...master, origin: { kind: 'reference', source } }, (0, restart_policy_js_1.readRestartPolicy)(restartPolicy, 'importFromReference'), undefined, context.state.user);
134
138
  if (start)
135
139
  await index_js_1.TwinEngine.startFromRegistry(domainId, res.instanceId);
136
140
  return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings: res.warnings };
@@ -159,7 +163,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
159
163
  */
160
164
  async resyncTwin(instanceId, context) {
161
165
  const domainId = context.state.domain.id;
162
- const inst = await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } });
166
+ const inst = await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } });
163
167
  if (!inst)
164
168
  return { ok: false, error: `unknown twin: ${instanceId}` };
165
169
  const origin = inst.origin;
@@ -168,23 +172,81 @@ let TwinReferenceResolver = class TwinReferenceResolver {
168
172
  ok: false,
169
173
  error: `twin "${instanceId}" does not remember where it came from — it cannot be re-read. Re-create it from its template or reference so the origin is recorded.`
170
174
  };
175
+ /*
176
+ * 진행을 알리는 통로 — 만들 때와 **같은 것**이다. 레퍼런스에서 온 트윈만 알린다(템플릿에서 온
177
+ * 트윈은 원본을 읽지 않으므로 알릴 단계가 없다).
178
+ *
179
+ * 분모는 그 어댑터가 선언한 단계 수다(`masterSteps`) + 호스트 단계. 선언하지 않은 어댑터는
180
+ * `total` 이 없고, 그때 화면은 퍼센트를 만들지 않는다 — 모르는 진행률을 지어내지 않는다.
181
+ */
182
+ const progressSource = origin.kind === 'reference' ? origin.source : undefined;
183
+ const refRow = progressSource
184
+ ? await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source: progressSource } })
185
+ : null;
186
+ const adapterForSteps = refRow ? (0, reference_adapter_js_1.getAdapter)(refRow.adapterType) : undefined;
187
+ const declaredSteps = adapterForSteps?.masterSteps?.length;
188
+ const stepTotal = declaredSteps === undefined ? undefined : declaredSteps + reference_progress_js_1.HOST_STEPS.length;
189
+ const siteId = origin.siteId ?? instanceId;
190
+ let lastDone = 0;
191
+ let lastStep = (adapterForSteps?.masterSteps?.[0] ?? 'provision');
192
+ const emit = (p) => {
193
+ if (!progressSource)
194
+ return;
195
+ lastDone = p.done;
196
+ lastStep = p.step;
197
+ shell_1.pubsub.publish('twin-reference-progress', {
198
+ twinReferenceProgress: { ...p, siteId, siteIndex: 0, siteCount: 1, total: p.total ?? stepTotal, source: progressSource }
199
+ });
200
+ };
171
201
  try {
172
- const master = await this.masterFromOrigin(domainId, origin, instanceId);
202
+ const master = await this.masterFromOrigin(domainId, origin, instanceId, st => emit({ step: st.key, done: st.done, total: stepTotal, detail: st.detail }));
203
+ emit({ step: 'provision', done: declaredSteps ?? 0, total: stepTotal });
173
204
  /*
174
205
  * **어느 현장의 트윈이었나를 지킨다** — 다시 읽기는 구조만 새로 그리는 일이고, 현장 소속은 그때
175
206
  * 사람이 고른 것이다. 기억이 없는 옛 트윈은 **지금 있는 현장**을 그대로 쓴다(빈손으로 두면 템플릿
176
207
  * 기본 공간으로 옮겨 간다 — 조용히 현장을 떠나고 그 현장의 값도 잃는다).
177
208
  */
178
209
  const keepSpace = origin.spaceId || inst.spaceId;
179
- const res = await index_js_1.TwinEngine.ingestMaster(domainId, master, keepSpace ? { spaceId: keepSpace } : undefined, context.state.user);
210
+ /* 다시 읽기는 **구조만** 새로 그린다 재기동 정책은 트윈의 선언이므로 그대로 지킨다. */
211
+ const res = await index_js_1.TwinEngine.ingestMaster(domainId, master, (0, restart_policy_js_1.readRestartPolicy)(inst.restartPolicy, `resync of twin "${instanceId}"`), keepSpace ? { spaceId: keepSpace } : undefined, context.state.user);
212
+ emit({ step: 'start', done: (declaredSteps ?? 0) + 1, total: stepTotal });
213
+ /*
214
+ * **총평도 새로 남긴다.** 다시 읽었는데 총평이 옛것이면 화면이 지난 읽기를 현재로 보여 준다 —
215
+ * 그 표를 보고 사람이 원본을 고치러 간다.
216
+ */
217
+ if (refRow && progressSource) {
218
+ const prevSpec = refRow.scopeSpec ?? {};
219
+ await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).update({ id: refRow.id }, {
220
+ scopeSpec: { ...prevSpec, assessments: { ...(prevSpec.assessments ?? {}), [siteId]: (0, reference_assessment_js_1.assessMaster)(master, siteId) } }
221
+ });
222
+ }
180
223
  return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings: res.warnings };
181
224
  }
182
225
  catch (e) {
226
+ /* 막힌 자리를 그대로 알린다 — 「끝낸 수」의 다음 단계다(만들 때와 같은 규칙). */
227
+ emit({
228
+ step: (adapterForSteps?.masterSteps?.[lastDone] ?? lastStep),
229
+ done: lastDone,
230
+ total: stepTotal,
231
+ failed: true,
232
+ error: e?.message ?? String(e)
233
+ });
183
234
  return refusal(context, e, 'resync failed');
184
235
  }
185
236
  }
186
237
  /** 기억해 둔 원천에서 마스터를 다시 얻는다 — 어댑터든 템플릿이든 이 한 곳에서 갈린다. */
187
- async masterFromOrigin(domainId, origin, instanceId) {
238
+ async masterFromOrigin(domainId, origin, instanceId,
239
+ /*
240
+ * **다시 읽기도 진행을 보여야 한다** (2026-08-22).
241
+ *
242
+ * 만들 때는 8단계가 화면에 흐르는데 다시 읽을 때는 아무것도 없었다 — 사용자가 버튼을 누르고
243
+ * 「진행되고 있는지 확인할 수가 없다」고 했다. 실제로 chef 는 원본 읽기가 14~21초이고 그 사이
244
+ * 화면에 아무 변화가 없다.
245
+ *
246
+ * 통로는 만들 때와 **같은 것**이다(`twin-reference-progress`). 화면도 같은 표시를 쓴다 —
247
+ * 두 벌을 만들면 한쪽만 고쳐지고 사람은 같은 일이 다르게 보이는 것을 결함으로 읽는다.
248
+ */
249
+ onStep) {
188
250
  if (origin.kind === 'template') {
189
251
  const tpl = (0, template_registry_js_1.getTemplate)(origin.templateId);
190
252
  if (!tpl)
@@ -200,7 +262,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
200
262
  const inMemory = (0, reference_registry_js_1.getReference)(origin.source);
201
263
  if (inMemory)
202
264
  return { ...inMemory, origin };
203
- const ref = await (0, shell_1.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source: origin.source } });
265
+ const ref = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source: origin.source } });
204
266
  if (!ref)
205
267
  throw new Error(`reference "${origin.source}" is no longer registered — nothing to re-read from`);
206
268
  const adapter = (0, reference_adapter_js_1.getAdapter)(ref.adapterType);
@@ -223,7 +285,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
223
285
  */
224
286
  const picked = (0, reference_master_js_1.pickOriginSite)(sites, origin);
225
287
  if (picked.site)
226
- return { ...(await adapter.fetchMaster(cfg, picked.site)), origin };
288
+ return { ...(await adapter.fetchMaster(cfg, picked.site, onStep)), origin };
227
289
  if (picked.reason === 'site-gone')
228
290
  throw new Error(`reference "${origin.source}" no longer reports site "${origin.siteId}" — refusing to overwrite this twin with a different site`);
229
291
  for (const site of sites) {
@@ -239,7 +301,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
239
301
  return (0, template_registry_js_1.listTemplates)().map(t => ({ id: t.id, label: t.label, system: t.system, description: t.description, detail: t.detail, knobs: t.knobs }));
240
302
  }
241
303
  /** 템플릿 + 노브 → 합성 마스터 → 인제스트(+기동+시나리오). 레퍼런스 import 와 같은 경로, 원천만 합성. */
242
- async createFromTemplate(templateId, params, context, start, spaceId) {
304
+ async createFromTemplate(templateId, params, restartPolicy, context, start, spaceId) {
243
305
  const tpl = (0, template_registry_js_1.getTemplate)(templateId);
244
306
  if (!tpl)
245
307
  return { ok: false, error: `unknown template: ${templateId}` };
@@ -270,7 +332,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
270
332
  master.origin = { kind: 'template', templateId, params: effective, ...(spaceId ? { spaceId } : {}) };
271
333
  /* 공간 선택은 템플릿을 거치지 않는다 — 템플릿마다 이 노브를 알고 있어야 한다면 새 템플릿이
272
334
  조용히 무시하게 된다. 합성된 마스터에 한 곳에서 얹는다(레퍼런스 인제스트와 같은 경로). */
273
- const res = await index_js_1.TwinEngine.ingestMaster(domainId, master, { spaceId }, context.state.user);
335
+ const res = await index_js_1.TwinEngine.ingestMaster(domainId, master, (0, restart_policy_js_1.readRestartPolicy)(restartPolicy, `createFromTemplate("${templateId}")`), { spaceId }, context.state.user);
274
336
  if (start !== false) {
275
337
  await index_js_1.TwinEngine.startFromRegistry(domainId, res.instanceId);
276
338
  if (scenario) {
@@ -297,9 +359,16 @@ let TwinReferenceResolver = class TwinReferenceResolver {
297
359
  */
298
360
  async twinReferences(context) {
299
361
  const domainId = context.state.domain.id;
300
- const rows = await (0, shell_1.getRepository)(twin_reference_js_1.TwinReference).find({ where: { domain: { id: domainId } } });
301
- // provenance 라이브 대조 — 지워진 트윈은 producedCount 에서 자동 제외(상태 동기의 lazy 방식).
302
- const liveIds = new Set((await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId));
362
+ const rows = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).find({ where: { domain: { id: domainId } } });
363
+ /*
364
+ * provenance 라이브 대조 지워진 트윈은 producedCount 에서 자동 제외(상태 동기의 lazy 방식).
365
+ *
366
+ * **id 만 읽는다** (2026-08-21). 예전에는 인스턴스 행 전체를 읽었고, 그 행에는 **모델 JSON** 이
367
+ * 들어 있다(자리 수백 개 + 발자국 좌표). 그래서 이 목록을 여는 데 수 메가바이트를 읽고 파싱했고,
368
+ * 화면은 그동안 「아직 연결된 시스템이 없습니다」를 보이고 있었다 — 사용자에게는 「없다」는 답으로
369
+ * 읽힌다. 여기서 필요한 것은 살아 있는 id 집합 하나다.
370
+ */
371
+ const liveIds = new Set((await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } }, select: ['instanceId'] })).map(i => i.instanceId));
303
372
  return rows.map(r => {
304
373
  const produced = (r.scopeSpec?.produced ?? []).filter(p => liveIds.has(p.instanceId));
305
374
  return {
@@ -319,8 +388,8 @@ let TwinReferenceResolver = class TwinReferenceResolver {
319
388
  */
320
389
  async twinConnections(context) {
321
390
  const domainId = context.state.domain.id;
322
- const rows = await (0, shell_1.getRepository)(twin_reference_js_1.TwinReference).find({ where: { domain: { id: domainId } } });
323
- const liveIds = new Set((await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId));
391
+ const rows = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).find({ where: { domain: { id: domainId } } });
392
+ const liveIds = new Set((await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId));
324
393
  const groups = new Map();
325
394
  for (const r of rows) {
326
395
  const connectorType = r.scopeSpec?.connectorType ?? r.adapterType;
@@ -340,11 +409,11 @@ let TwinReferenceResolver = class TwinReferenceResolver {
340
409
  /** 한 Connection 그룹 노드 상세 — 그 아래 생성된 트윈 인스턴스(라이브 대조·상태·기동여부). */
341
410
  async twinConnection(source, context) {
342
411
  const domainId = context.state.domain.id;
343
- const r = await (0, shell_1.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source } });
412
+ const r = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source } });
344
413
  if (!r)
345
414
  return null;
346
415
  const produced = (r.scopeSpec?.produced ?? []);
347
- const instMap = new Map((await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => [i.instanceId, i]));
416
+ const instMap = new Map((await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => [i.instanceId, i]));
348
417
  const instances = produced
349
418
  .filter(p => instMap.has(p.instanceId))
350
419
  .map(p => {
@@ -364,24 +433,44 @@ let TwinReferenceResolver = class TwinReferenceResolver {
364
433
  }
365
434
  /** 단건 상세(뷰/편집) — connectionConfig 포함, 어댑터 스키마의 secret 필드는 마스킹(있으면 '••••••'). */
366
435
  async twinReference(source, context) {
367
- const r = await (0, shell_1.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } });
436
+ const r = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } });
368
437
  if (!r)
369
438
  return null;
370
439
  const secretKeys = new Set(((0, reference_adapter_js_1.getAdapter)(r.adapterType)?.meta?.configSchema ?? []).filter(f => f.secret).map(f => f.key));
371
440
  const cfg = {};
372
441
  for (const [k, v] of Object.entries(r.connectionConfig ?? {}))
373
442
  cfg[k] = secretKeys.has(k) ? (v ? '••••••' : '') : v;
443
+ /*
444
+ * **이 연결이 만든 트윈 id 를 함께 낸다.** 상세 화면이 「이 연결이 잘 동기화되고 있나」를 물으려면
445
+ * 어느 트윈을 물어야 하는지 알아야 한다. 예전에는 개수(`producedCount`)만 있어서 화면이 id 를
446
+ * 알 방법이 없었다.
447
+ */
448
+ const producedInstanceIds = [
449
+ ...new Set((r.scopeSpec?.produced ?? [])
450
+ .map((p) => p?.instanceId)
451
+ .filter((x) => typeof x === 'string' && !!x))
452
+ ];
374
453
  return {
375
454
  source: r.source, system: r.system, siteName: r.siteName, description: r.description,
376
- adapterType: r.adapterType, connectionConfig: cfg, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError
455
+ adapterType: r.adapterType, connectionConfig: cfg, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError,
456
+ producedInstanceIds
377
457
  };
378
458
  }
379
459
  referenceAdapters() {
380
- return (0, reference_adapter_js_1.listAdapters)().map(a => ({ type: a.type, ...(a.meta ?? {}) }));
460
+ /*
461
+ * **능력을 함께 낸다** (2026-08-21).
462
+ *
463
+ * `capabilities` 는 어댑터 뿌리에 있고 `meta` 에는 없었다. 그래서 연결 화면이 「이 원본이 라이브를
464
+ * 낼 수 있나」를 알 수 없었고, 트윈을 만들 때 `live` 를 말하지 못해 **재기동 정책이 없다고 거절**됐다
465
+ * (실 연동에서 그것에 막혔다 — 미러는 정의상 `resync` 이므로 `live` 하나로 정해진다).
466
+ *
467
+ * 화면이 그 사실을 알아야 정책을 사람에게 물을지 스스로 정할지 가를 수 있다.
468
+ */
469
+ return (0, reference_adapter_js_1.listAdapters)().map(a => ({ type: a.type, ...(a.meta ?? {}), capabilities: a.capabilities ?? [] }));
381
470
  }
382
471
  async saveTwinReference(source, patch, context) {
383
472
  const domainId = context.state.domain.id;
384
- const repo = (0, shell_1.getRepository)(twin_reference_js_1.TwinReference);
473
+ const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
385
474
  const existing = await repo.findOne({ where: { domain: { id: domainId }, source } });
386
475
  const saved = await repo.save(repo.create({
387
476
  ...(existing ?? {}),
@@ -404,7 +493,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
404
493
  /** 연결 해제 — removeTwins=true 면 이 레퍼런스가 만든 트윈(provenance)도 함께 제거(라이프사이클 연쇄). 기본은 트윈 보존(분리). */
405
494
  async deleteTwinReference(source, context, removeTwins) {
406
495
  const domainId = context.state.domain.id;
407
- const repo = (0, shell_1.getRepository)(twin_reference_js_1.TwinReference);
496
+ const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
408
497
  const ref = await repo.findOne({ where: { domain: { id: domainId }, source } });
409
498
  if (removeTwins && ref) {
410
499
  for (const p of (ref.scopeSpec?.produced ?? [])) {
@@ -420,7 +509,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
420
509
  return true;
421
510
  }
422
511
  async testReferenceConnection(source, context) {
423
- const repo = (0, shell_1.getRepository)(twin_reference_js_1.TwinReference);
512
+ const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
424
513
  const ref = await repo.findOne({ where: { domain: { id: context.state.domain.id }, source } });
425
514
  if (!ref)
426
515
  return { ok: false, error: `unknown reference: ${source}` };
@@ -448,7 +537,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
448
537
  * 연결에서 가장 자주 막히는 자리인데 자격이 틀렸는지 주소가 틀렸는지 알 수 없었다.
449
538
  * 판정과 문장 형태는 `discovery-result`(순수)가 갖는다.
450
539
  */
451
- const ref = await (0, shell_1.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } });
540
+ const ref = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } });
452
541
  if (!ref)
453
542
  return (0, discovery_result_js_1.failed)((0, discovery_result_js_1.referenceNotFound)(source));
454
543
  const adapter = (0, reference_adapter_js_1.getAdapter)(ref.adapterType);
@@ -482,9 +571,9 @@ let TwinReferenceResolver = class TwinReferenceResolver {
482
571
  * 판정은 그 순수 모듈이 갖는다: 없는 공간은 거절(`resolveIngestSpace`), 사이트 여럿을 한 공간에
483
572
  * 넣는 것도 거절(`refuseImportSpace`) — 서로 다른 현장이 조용히 합쳐지는 것을 막는다.
484
573
  */
485
- async importTwinReference(source, context, siteIds, start, live, spaceId) {
574
+ async importTwinReference(source, context, siteIds, start, live, spaceId, restartPolicy) {
486
575
  const domainId = context.state.domain.id;
487
- const repo = (0, shell_1.getRepository)(twin_reference_js_1.TwinReference);
576
+ const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
488
577
  const ref = await repo.findOne({ where: { domain: { id: domainId }, source } });
489
578
  if (!ref)
490
579
  return { ok: false, error: `unknown reference: ${source}` };
@@ -502,15 +591,74 @@ let TwinReferenceResolver = class TwinReferenceResolver {
502
591
  return { ok: false, error: refusal.message, errorCode: refusal.code, errorParams: refusal.params };
503
592
  const instances = [];
504
593
  const failed = [];
505
- for (const site of sites) {
594
+ /*
595
+ * **진행을 구독으로 흘린다** (2026-08-21).
596
+ *
597
+ * 마스터 읽기는 원본에 여러 질의를 보내는 긴 작업이고, 화면은 그 사이 아무것도 알 수 없었다.
598
+ * 단계를 아는 것은 어댑터뿐이므로 어댑터가 말하고(표준 낱말), 호스트가 자기 두 단계(생성·기동)를
599
+ * 더해 흘린다.
600
+ *
601
+ * **분모는 어댑터가 선언한 것**이다(`masterSteps`). 선언하지 않은 어댑터는 `total` 이 없고, 그때
602
+ * 화면은 퍼센트를 만들지 않는다 — 모르는 진행률을 지어내지 않는다.
603
+ */
604
+ const declared = adapter.masterSteps?.length;
605
+ const stepTotal = declared === undefined ? undefined : declared + reference_progress_js_1.HOST_STEPS.length;
606
+ const emit = (p) => shell_1.pubsub.publish('twin-reference-progress', {
607
+ twinReferenceProgress: { ...p, siteCount: sites.length, total: p.total ?? stepTotal, source }
608
+ });
609
+ /*
610
+ * **읽은 뒤의 총평을 사이트마다 남긴다** (2026-08-22).
611
+ *
612
+ * 총평은 읽는 순간에만 있었다 — 대화상자를 닫으면 사라지고, 다시 보려면 같은 읽기를 또 해야 했다.
613
+ * 그런데 사람이 그것을 묻는 자리는 「모델 살펴보기」다(트윈을 보다가 「이건 왜 비었나」를 묻는다).
614
+ * 그래서 레퍼런스 행에 남겨 그 화면이 언제든 읽게 한다.
615
+ *
616
+ * 사실만 담는다(`assessMaster`) — 문장은 화면이 만들고, 더 알고 싶을 때 AI 가 이 사실만 근거로
617
+ * 서술한다. 다시 읽으면 그 사이트의 총평이 새것으로 바뀐다(지난 읽기의 총평을 현재로 보이게
618
+ * 두지 않는다).
619
+ */
620
+ const assessments = {};
621
+ for (const [siteIndex, site] of sites.entries()) {
622
+ /*
623
+ * **실패를 실제로 막힌 단계에 적는다** (2026-08-22).
624
+ *
625
+ * 예전에는 실패를 무조건 `provision` 으로 적었다. 그래서 원본을 읽다 끊긴 것도 화면에는
626
+ * 「트윈 생성에서 실패」로 떴다 — 사람이 원인을 엉뚱한 자리에서 찾는다(실제로 그렇게 됐다).
627
+ *
628
+ * 규약이 답을 준다: `done` 은 **끝낸 단계 수**다(`ReferenceProgress.done`). 그러면 지금 막힌 것은
629
+ * 그 다음 단계, 즉 `masterSteps[done]` 이다. 그 표를 넘어서면(호스트 단계) 마지막으로 알린 것을 쓴다.
630
+ *
631
+ * 이 규칙은 두 가지 보고 방식에 함께 맞는다 — 단계 **시작**에 알리는 어댑터(`done` 이 아직 0)와
632
+ * 단계 **완료**에 알리는 어댑터(`done` 이 1 늘어난다) 모두 「끝낸 수」만 지키면 된다.
633
+ */
634
+ let lastDone = 0;
635
+ let lastStep = (adapter.masterSteps?.[0] ?? 'provision');
636
+ const track = (p) => {
637
+ lastDone = p.done;
638
+ lastStep = p.step;
639
+ emit(p);
640
+ };
506
641
  try {
507
- const master = await adapter.fetchMaster(cfg, site);
642
+ const master = await adapter.fetchMaster(cfg, site, st => track({ siteId: site.siteId, siteIndex, step: st.key, done: st.done, total: stepTotal, detail: st.detail }));
508
643
  /* 어느 레퍼런스의 **어느 사이트**에서 왔는지 남긴다 — 다시 읽기가 같은 어댑터·같은 사이트로 돌아오려면
509
644
  사이트 정체가 있어야 한다(`source` 는 참조 이름이라 사이트 전부에 같다). */
510
- const res = await index_js_1.TwinEngine.ingestMaster(domainId, { ...master, origin: { kind: 'reference', source, siteId: site.siteId, ...(spaceId ? { spaceId } : {}) } }, { spaceId }, context.state.user);
645
+ /*
646
+ * 정책은 **선언이거나 의도에서 곧바로 따라오는 것**이다: `live=true` 는 미러를 띄우겠다는 뜻이고
647
+ * 미러는 정의상 `resync` 다(외부가 진실이므로 우리 과거를 이어 붙이지 않는다). 시뮬로 띄우려면
648
+ * 스스로 선언해야 한다 — 그 자리에서 우리가 고르면 재기동마다 이력을 지우는 트윈이 조용히 생긴다.
649
+ */
650
+ assessments[site.siteId] = (0, reference_assessment_js_1.assessMaster)(master, site.siteId);
651
+ const policy = (0, restart_policy_js_1.readRestartPolicy)(restartPolicy ?? (live ? 'resync' : undefined), `importTwinReference("${source}")`);
652
+ track({ siteId: site.siteId, siteIndex, step: 'provision', done: declared ?? 0, total: stepTotal });
653
+ const res = await index_js_1.TwinEngine.ingestMaster(domainId, { ...master, origin: { kind: 'reference', source, siteId: site.siteId, ...(spaceId ? { spaceId } : {}) } }, policy, { spaceId }, context.state.user);
654
+ track({ siteId: site.siteId, siteIndex, step: 'start', done: (declared ?? 0) + 1, total: stepTotal });
511
655
  if (start !== false) {
512
656
  // live=true + 어댑터가 openLiveFeed 지원 → mirror(실 이벤트 미러). 아니면 sim 기동(fallback).
513
- const wentLive = live ? await (0, reference_live_js_1.startReferenceLiveFeed)(domainId, ref.adapterType, cfg, site, res.instanceId) : false;
657
+ /* 읽기 커서를 저장할 자리를 함께 넘긴다 레퍼런스의 이름은 호스트가 붙이는 것이고
658
+ 커넥터는 그것을 알 수 없다(§`startReferenceLiveFeed`). */
659
+ const wentLive = live
660
+ ? await (0, reference_live_js_1.startReferenceLiveFeed)(domainId, ref.adapterType, cfg, site, res.instanceId, ref.source)
661
+ : false;
514
662
  if (!wentLive)
515
663
  await index_js_1.TwinEngine.startFromRegistry(domainId, res.instanceId);
516
664
  instances.push({ siteId: site.siteId, instanceId: res.instanceId, spaceId: res.spaceId, mode: wentLive ? 'live' : 'sim', warnings: res.warnings });
@@ -520,6 +668,12 @@ let TwinReferenceResolver = class TwinReferenceResolver {
520
668
  }
521
669
  }
522
670
  catch (e) {
671
+ /*
672
+ * **실패한 단계를 그대로 알린다.** 화면이 진행 표시를 지우지 않고 그 자리를 붉게 두어야
673
+ * 사람이 「어디까지 갔는지」를 안다. 막힌 자리는 「끝낸 수」의 다음 단계다(위 주석).
674
+ */
675
+ const at = (adapter.masterSteps?.[lastDone] ?? lastStep);
676
+ emit({ siteId: site.siteId, siteIndex, step: at, done: lastDone, total: stepTotal, failed: true, error: e?.message ?? String(e) });
523
677
  failed.push({ siteId: site.siteId, error: e?.message ?? 'failed' });
524
678
  }
525
679
  }
@@ -529,6 +683,10 @@ let TwinReferenceResolver = class TwinReferenceResolver {
529
683
  await repo.update({ id: ref.id }, {
530
684
  status: 'connected',
531
685
  lastSyncedAt: new Date().toISOString(),
686
+ /* 못 옮긴 값을 **세어 남긴다**. 아무 인스턴스도 보고하지 않았으면 `null` — 「없었다」로 위장하지 않는다. */
687
+ lastWarningCount: instances.some((i) => Array.isArray(i.warnings))
688
+ ? instances.reduce((n, i) => n + (Array.isArray(i.warnings) ? i.warnings.length : 0), 0)
689
+ : null,
532
690
  /*
533
691
  * **영어 canonical 로 남긴다.** 이 값은 DB 에 저장되고 연결 화면이 그대로 뿌린다 — 예전에는
534
692
  * 한글 산문(`N개 사이트 실패`)이라 다섯 언어 화면에 한글이 새어 나갔다. 어댑터가 주는 사유도
@@ -536,7 +694,24 @@ let TwinReferenceResolver = class TwinReferenceResolver {
536
694
  * 어느 사이트가 왜 실패했는지는 `failed[]` 가 답한다 — 화면이 그것을 보여 준다.
537
695
  */
538
696
  lastError: failed.length ? `${failed.length} of ${sites.length} site(s) failed: ${failed.map((f) => f.siteId).join(', ')}` : null,
539
- scopeSpec: { ...(ref.scopeSpec ?? {}), produced: [...prev, ...producedNew] }
697
+ /*
698
+ * ── 실패 사유를 **남긴다** (2026-08-21) ────────────────────────────────
699
+ *
700
+ * 사유는 대화상자에만 있었다. 닫으면 사라지고, 다시 보려면 같은 실패를 다시 만들어야 했다 —
701
+ * 실제로 「승화푸드」 연결이 그 상태였다(요약 한 줄만 남고 원인은 어디에도 없었다).
702
+ *
703
+ * `scopeSpec` 은 이미 이 레퍼런스의 부속 사실을 담는 자리이므로(`produced`) 스키마를 늘리지 않고
704
+ * 여기 적는다. 성공한 회차에는 **비운다** — 지나간 실패를 현재 상태처럼 보이게 두지 않는다.
705
+ */
706
+ scopeSpec: {
707
+ ...(ref.scopeSpec ?? {}),
708
+ produced: [...prev, ...producedNew],
709
+ /* 이번에 읽은 사이트의 총평만 갈아 끼운다 — 읽지 않은 사이트의 것은 그대로 둔다. */
710
+ assessments: { ...((ref.scopeSpec ?? {}).assessments ?? {}), ...assessments },
711
+ ...(failed.length
712
+ ? { lastFailures: failed.map((f) => ({ siteId: f.siteId, error: f.error, at: new Date().toISOString() })) }
713
+ : { lastFailures: [] })
714
+ }
540
715
  });
541
716
  return { ok: instances.length > 0, instances, failed };
542
717
  }
@@ -549,7 +724,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
549
724
  };
550
725
  exports.TwinReferenceResolver = TwinReferenceResolver;
551
726
  tslib_1.__decorate([
552
- (0, type_graphql_1.Query)(returns => [shell_1.ScalarObject], { description: 'List registered reference sources (virtual or real adapters) available to ingest.' }),
727
+ (0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List registered reference sources (virtual or real adapters) available to ingest.' }),
553
728
  tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
554
729
  tslib_1.__metadata("design:type", Function),
555
730
  tslib_1.__metadata("design:paramtypes", [Object]),
@@ -557,17 +732,20 @@ tslib_1.__decorate([
557
732
  ], TwinReferenceResolver.prototype, "referenceSources", null);
558
733
  tslib_1.__decorate([
559
734
  (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
560
- (0, type_graphql_1.Mutation)(returns => shell_1.ScalarObject, { description: 'Ingest a registered reference source into a twin (space + instance). Optionally start it.' }),
735
+ (0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
736
+ description: "Ingest a registered reference source into a twin (space + instance). Optionally start it. restartPolicy declares how the new twin treats its own past on reboot: 'resync' (read the source again) | 'resume' (continue its journal) | 'reset' (wipe and replay from the seed). It has no default — a twin cannot exist without the declaration."
737
+ }),
561
738
  tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
562
- tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
563
- tslib_1.__param(2, (0, type_graphql_1.Arg)('start', { nullable: true })),
739
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('restartPolicy')),
740
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
741
+ tslib_1.__param(3, (0, type_graphql_1.Arg)('start', { nullable: true })),
564
742
  tslib_1.__metadata("design:type", Function),
565
- tslib_1.__metadata("design:paramtypes", [String, Object, Boolean]),
743
+ tslib_1.__metadata("design:paramtypes", [String, String, Object, Boolean]),
566
744
  tslib_1.__metadata("design:returntype", Promise)
567
745
  ], TwinReferenceResolver.prototype, "importFromReference", null);
568
746
  tslib_1.__decorate([
569
747
  (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
570
- (0, type_graphql_1.Mutation)(returns => shell_1.ScalarObject, {
748
+ (0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
571
749
  description: "Re-read a twin's structure from the source it remembers (TwinInstance.origin). Works for both reference- and template-born twins. A running mirror adopts the new structure without stopping; a running simulation is refused."
572
750
  }),
573
751
  tslib_1.__param(0, (0, type_graphql_1.Arg)('instanceId')),
@@ -577,7 +755,7 @@ tslib_1.__decorate([
577
755
  tslib_1.__metadata("design:returntype", Promise)
578
756
  ], TwinReferenceResolver.prototype, "resyncTwin", null);
579
757
  tslib_1.__decorate([
580
- (0, type_graphql_1.Query)(returns => [shell_1.ScalarObject], { description: 'List registered twin templates (parameterized archetypes) with their knob schema.' }),
758
+ (0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List registered twin templates (parameterized archetypes) with their knob schema.' }),
581
759
  tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
582
760
  tslib_1.__metadata("design:type", Function),
583
761
  tslib_1.__metadata("design:paramtypes", [Object]),
@@ -585,18 +763,21 @@ tslib_1.__decorate([
585
763
  ], TwinReferenceResolver.prototype, "twinTemplates", null);
586
764
  tslib_1.__decorate([
587
765
  (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
588
- (0, type_graphql_1.Mutation)(returns => shell_1.ScalarObject, { description: 'Instantiate a twin template with params → synthetic master → ingest (+start+scenario). Returns {ok, instanceId, spaceId}.' }),
766
+ (0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
767
+ description: "Instantiate a twin template with params → synthetic master → ingest (+start+scenario). restartPolicy declares how the new twin treats its own past on reboot ('resync' | 'resume' | 'reset') — there is no default. Returns {ok, instanceId, spaceId}."
768
+ }),
589
769
  tslib_1.__param(0, (0, type_graphql_1.Arg)('templateId')),
590
- tslib_1.__param(1, (0, type_graphql_1.Arg)('params', type => shell_1.ScalarObject)),
591
- tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
592
- tslib_1.__param(3, (0, type_graphql_1.Arg)('start', { nullable: true })),
593
- tslib_1.__param(4, (0, type_graphql_1.Arg)('spaceId', { nullable: true, description: 'Existing space to co-locate this twin into (add a lens to a site). Omit to create its own space.' })),
770
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('params', type => shell_2.ScalarObject)),
771
+ tslib_1.__param(2, (0, type_graphql_1.Arg)('restartPolicy')),
772
+ tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
773
+ tslib_1.__param(4, (0, type_graphql_1.Arg)('start', { nullable: true })),
774
+ tslib_1.__param(5, (0, type_graphql_1.Arg)('spaceId', { nullable: true, description: 'Existing space to co-locate this twin into (add a lens to a site). Omit to create its own space.' })),
594
775
  tslib_1.__metadata("design:type", Function),
595
- tslib_1.__metadata("design:paramtypes", [String, Object, Object, Boolean, String]),
776
+ tslib_1.__metadata("design:paramtypes", [String, Object, String, Object, Boolean, String]),
596
777
  tslib_1.__metadata("design:returntype", Promise)
597
778
  ], TwinReferenceResolver.prototype, "createFromTemplate", null);
598
779
  tslib_1.__decorate([
599
- (0, type_graphql_1.Query)(returns => [shell_1.ScalarObject], { description: 'List tenant-scoped persisted twin references (adapter-backed).' }),
780
+ (0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List tenant-scoped persisted twin references (adapter-backed).' }),
600
781
  tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
601
782
  tslib_1.__metadata("design:type", Function),
602
783
  tslib_1.__metadata("design:paramtypes", [Object]),
@@ -609,14 +790,14 @@ tslib_1.__decorate([
609
790
  tslib_1.__metadata("design:returntype", Array)
610
791
  ], TwinReferenceResolver.prototype, "referenceAdapterTypes", null);
611
792
  tslib_1.__decorate([
612
- (0, type_graphql_1.Query)(returns => [shell_1.ScalarObject], { description: 'Group integration items 2-tier: connector type ▸ connection ▸ produced twins. (reference-management §2.3)' }),
793
+ (0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'Group integration items 2-tier: connector type ▸ connection ▸ produced twins. (reference-management §2.3)' }),
613
794
  tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
614
795
  tslib_1.__metadata("design:type", Function),
615
796
  tslib_1.__metadata("design:paramtypes", [Object]),
616
797
  tslib_1.__metadata("design:returntype", Promise)
617
798
  ], TwinReferenceResolver.prototype, "twinConnections", null);
618
799
  tslib_1.__decorate([
619
- (0, type_graphql_1.Query)(returns => shell_1.ScalarObject, { nullable: true, description: 'One connection grouping location with its produced twin instances (live-checked). (reference-management §2.3)' }),
800
+ (0, type_graphql_1.Query)(returns => shell_2.ScalarObject, { nullable: true, description: 'One connection grouping location with its produced twin instances (live-checked). (reference-management §2.3)' }),
620
801
  tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
621
802
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
622
803
  tslib_1.__metadata("design:type", Function),
@@ -624,7 +805,7 @@ tslib_1.__decorate([
624
805
  tslib_1.__metadata("design:returntype", Promise)
625
806
  ], TwinReferenceResolver.prototype, "twinConnection", null);
626
807
  tslib_1.__decorate([
627
- (0, type_graphql_1.Query)(returns => shell_1.ScalarObject, { nullable: true, description: 'Get one tenant-scoped reference with its connection config (secret fields masked) for view/edit.' }),
808
+ (0, type_graphql_1.Query)(returns => shell_2.ScalarObject, { nullable: true, description: 'Get one tenant-scoped reference with its connection config (secret fields masked) for view/edit.' }),
628
809
  tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
629
810
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
630
811
  tslib_1.__metadata("design:type", Function),
@@ -632,16 +813,16 @@ tslib_1.__decorate([
632
813
  tslib_1.__metadata("design:returntype", Promise)
633
814
  ], TwinReferenceResolver.prototype, "twinReference", null);
634
815
  tslib_1.__decorate([
635
- (0, type_graphql_1.Query)(returns => [shell_1.ScalarObject], { description: 'List reference connector metadata (label, domain, config schema, availability) for the connect UI.' }),
816
+ (0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List reference connector metadata (label, domain, config schema, availability, capabilities) for the connect UI.' }),
636
817
  tslib_1.__metadata("design:type", Function),
637
818
  tslib_1.__metadata("design:paramtypes", []),
638
819
  tslib_1.__metadata("design:returntype", Array)
639
820
  ], TwinReferenceResolver.prototype, "referenceAdapters", null);
640
821
  tslib_1.__decorate([
641
822
  (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
642
- (0, type_graphql_1.Mutation)(returns => shell_1.ScalarObject, { description: 'Create or update a tenant-scoped twin reference (persisted).' }),
823
+ (0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, { description: 'Create or update a tenant-scoped twin reference (persisted).' }),
643
824
  tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
644
- tslib_1.__param(1, (0, type_graphql_1.Arg)('patch', type => shell_1.ScalarObject)),
825
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('patch', type => shell_2.ScalarObject)),
645
826
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
646
827
  tslib_1.__metadata("design:type", Function),
647
828
  tslib_1.__metadata("design:paramtypes", [String, Object, Object]),
@@ -659,7 +840,7 @@ tslib_1.__decorate([
659
840
  ], TwinReferenceResolver.prototype, "deleteTwinReference", null);
660
841
  tslib_1.__decorate([
661
842
  (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
662
- (0, type_graphql_1.Mutation)(returns => shell_1.ScalarObject, { description: 'Test a reference connection via its adapter; updates status.' }),
843
+ (0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, { description: 'Test a reference connection via its adapter; updates status.' }),
663
844
  tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
664
845
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
665
846
  tslib_1.__metadata("design:type", Function),
@@ -667,7 +848,7 @@ tslib_1.__decorate([
667
848
  tslib_1.__metadata("design:returntype", Promise)
668
849
  ], TwinReferenceResolver.prototype, "testReferenceConnection", null);
669
850
  tslib_1.__decorate([
670
- (0, type_graphql_1.Query)(returns => shell_1.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.' }),
851
+ (0, type_graphql_1.Query)(returns => shell_2.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.' }),
671
852
  tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
672
853
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
673
854
  tslib_1.__metadata("design:type", Function),
@@ -676,15 +857,18 @@ tslib_1.__decorate([
676
857
  ], TwinReferenceResolver.prototype, "discoverReferenceSites", null);
677
858
  tslib_1.__decorate([
678
859
  (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
679
- (0, type_graphql_1.Mutation)(returns => shell_1.ScalarObject, { description: 'Create twins from a reference: discover sites → filter by siteIds (if given) → fetch master(s) → provision. spaceId co-locates the twin into an existing space (one site only). start=false to only provision; live=true to run as a mirror (adapter openLiveFeed → live projector) instead of sim.' }),
860
+ (0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
861
+ description: "Create twins from a reference: discover sites → filter by siteIds (if given) → fetch master(s) → provision. spaceId co-locates the twin into an existing space (one site only). start=false to only provision; live=true to run as a mirror (adapter openLiveFeed → live projector) instead of sim. restartPolicy declares how each new twin treats its own past on reboot ('resync' | 'resume' | 'reset'); omit it and live=true implies 'resync' — a mirror reads the source again — while a simulation must declare 'resume' or 'reset' for itself."
862
+ }),
680
863
  tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
681
864
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
682
865
  tslib_1.__param(2, (0, type_graphql_1.Arg)('siteIds', type => [String], { nullable: true })),
683
866
  tslib_1.__param(3, (0, type_graphql_1.Arg)('start', { nullable: true })),
684
867
  tslib_1.__param(4, (0, type_graphql_1.Arg)('live', { nullable: true })),
685
868
  tslib_1.__param(5, (0, type_graphql_1.Arg)('spaceId', { nullable: true, description: 'Existing space to co-locate this twin into (add a lens to a site). Only when importing a single site. Omit to give each site its own space.' })),
869
+ tslib_1.__param(6, (0, type_graphql_1.Arg)('restartPolicy', { nullable: true, description: "How each new twin treats its own past on reboot: 'resync' | 'resume' | 'reset'. Required unless live=true (a mirror is 'resync' by definition)." })),
686
870
  tslib_1.__metadata("design:type", Function),
687
- tslib_1.__metadata("design:paramtypes", [String, Object, Array, Boolean, Boolean, String]),
871
+ tslib_1.__metadata("design:paramtypes", [String, Object, Array, Boolean, Boolean, String, String]),
688
872
  tslib_1.__metadata("design:returntype", Promise)
689
873
  ], TwinReferenceResolver.prototype, "importTwinReference", null);
690
874
  exports.TwinReferenceResolver = TwinReferenceResolver = tslib_1.__decorate([