@things-factory/headless-twin 10.1.278 → 10.1.280

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 (614) hide show
  1. package/package.json +21 -7
  2. package/dist-server/engine/attention-digest.js.map +0 -1
  3. package/dist-server/engine/canonical-ingest.js.map +0 -1
  4. package/dist-server/engine/checkpoint-fold.js.map +0 -1
  5. package/dist-server/engine/command-routing.js.map +0 -1
  6. package/dist-server/engine/declared-stimulus.js.map +0 -1
  7. package/dist-server/engine/energy-topology.js.map +0 -1
  8. package/dist-server/engine/event-time.js.map +0 -1
  9. package/dist-server/engine/index.js.map +0 -1
  10. package/dist-server/engine/ingest-dedupe.js.map +0 -1
  11. package/dist-server/engine/ingest-health.js.map +0 -1
  12. package/dist-server/engine/integration-coverage.js.map +0 -1
  13. package/dist-server/engine/integration-probes.js.map +0 -1
  14. package/dist-server/engine/integration-runner.js.map +0 -1
  15. package/dist-server/engine/integration-target-profile.js.map +0 -1
  16. package/dist-server/engine/kpi-baseline.js.map +0 -1
  17. package/dist-server/engine/kpi-fold.js.map +0 -1
  18. package/dist-server/engine/kpi-query.js.map +0 -1
  19. package/dist-server/engine/kpi-target.js.map +0 -1
  20. package/dist-server/engine/live-attentions.js.map +0 -1
  21. package/dist-server/engine/live-feed-registry.js.map +0 -1
  22. package/dist-server/engine/load-meter.js.map +0 -1
  23. package/dist-server/engine/local-declarations.js.map +0 -1
  24. package/dist-server/engine/log.js.map +0 -1
  25. package/dist-server/engine/loop-lag.js.map +0 -1
  26. package/dist-server/engine/measured-estimator.js.map +0 -1
  27. package/dist-server/engine/measured-yield.js.map +0 -1
  28. package/dist-server/engine/model-basis.js.map +0 -1
  29. package/dist-server/engine/model-gap.js.map +0 -1
  30. package/dist-server/engine/model-refusal.js.map +0 -1
  31. package/dist-server/engine/model-vocabulary.js.map +0 -1
  32. package/dist-server/engine/oee-accumulator.js.map +0 -1
  33. package/dist-server/engine/operation-basis.js.map +0 -1
  34. package/dist-server/engine/producer-guard.js.map +0 -1
  35. package/dist-server/engine/property-effects.js.map +0 -1
  36. package/dist-server/engine/read-time.js.map +0 -1
  37. package/dist-server/engine/restart-policy.js.map +0 -1
  38. package/dist-server/engine/runtime-key.js.map +0 -1
  39. package/dist-server/engine/spec-coverage.js.map +0 -1
  40. package/dist-server/engine/stage-path.js.map +0 -1
  41. package/dist-server/engine/state-axes.js.map +0 -1
  42. package/dist-server/engine/structure-diff.js.map +0 -1
  43. package/dist-server/engine/travel-estimator.js.map +0 -1
  44. package/dist-server/engine/twin-engine.js.map +0 -1
  45. package/dist-server/engine/twin-state-channel.js.map +0 -1
  46. package/dist-server/engine/warm-start.js.map +0 -1
  47. package/dist-server/index.js.map +0 -1
  48. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +0 -1
  49. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +0 -1
  50. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +0 -1
  51. package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +0 -1
  52. package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +0 -1
  53. package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +0 -1
  54. package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +0 -1
  55. package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +0 -1
  56. package/dist-server/migrations/1786800000000-CreateTwinReferenceReconciliations.js.map +0 -1
  57. package/dist-server/migrations/index.js.map +0 -1
  58. package/dist-server/routes.js.map +0 -1
  59. package/dist-server/service/actuation/actuation-advisor.js.map +0 -1
  60. package/dist-server/service/actuation/actuation-outcome.js.map +0 -1
  61. package/dist-server/service/actuation/actuation-rule-resolver.js.map +0 -1
  62. package/dist-server/service/actuation/actuation-rule.js.map +0 -1
  63. package/dist-server/service/actuation/approval-gateway.js.map +0 -1
  64. package/dist-server/service/actuation/catch-up-effects.js.map +0 -1
  65. package/dist-server/service/actuation/command-dispatcher.js.map +0 -1
  66. package/dist-server/service/actuation/command-store.js.map +0 -1
  67. package/dist-server/service/actuation/dispatch-after-approval.js.map +0 -1
  68. package/dist-server/service/actuation/effect-match.js.map +0 -1
  69. package/dist-server/service/actuation/index.js.map +0 -1
  70. package/dist-server/service/actuation/retry-plan.js.map +0 -1
  71. package/dist-server/service/actuation/rule-evaluate.js.map +0 -1
  72. package/dist-server/service/actuation/rule-loop.js.map +0 -1
  73. package/dist-server/service/actuation/rule-runner.js.map +0 -1
  74. package/dist-server/service/actuation/rule-wiring.js.map +0 -1
  75. package/dist-server/service/actuation/settle-effects.js.map +0 -1
  76. package/dist-server/service/actuation/sweep-dispatch.js.map +0 -1
  77. package/dist-server/service/actuation/twin-command-resolver.js.map +0 -1
  78. package/dist-server/service/actuation/twin-command.js.map +0 -1
  79. package/dist-server/service/actuation/twin-now.js.map +0 -1
  80. package/dist-server/service/index.js.map +0 -1
  81. package/dist-server/service/reference/actuation-routing.js.map +0 -1
  82. package/dist-server/service/reference/actuation-target.js.map +0 -1
  83. package/dist-server/service/reference/actuation-verification.js.map +0 -1
  84. package/dist-server/service/reference/attention-lane.js.map +0 -1
  85. package/dist-server/service/reference/connection-portability-resolver.js.map +0 -1
  86. package/dist-server/service/reference/connection-portability.js.map +0 -1
  87. package/dist-server/service/reference/control-routing.js.map +0 -1
  88. package/dist-server/service/reference/discovery-result.js.map +0 -1
  89. package/dist-server/service/reference/fill-cadence.js.map +0 -1
  90. package/dist-server/service/reference/fill-dedupe.js.map +0 -1
  91. package/dist-server/service/reference/fill-loop.js.map +0 -1
  92. package/dist-server/service/reference/fill-span.js.map +0 -1
  93. package/dist-server/service/reference/hook-contract.js.map +0 -1
  94. package/dist-server/service/reference/hook-rejected.js.map +0 -1
  95. package/dist-server/service/reference/hook-store.js.map +0 -1
  96. package/dist-server/service/reference/index.js.map +0 -1
  97. package/dist-server/service/reference/ingest-space.js.map +0 -1
  98. package/dist-server/service/reference/knob-defaults.js.map +0 -1
  99. package/dist-server/service/reference/live-cadence.js.map +0 -1
  100. package/dist-server/service/reference/live-feed-lease.js.map +0 -1
  101. package/dist-server/service/reference/live-ingest.js.map +0 -1
  102. package/dist-server/service/reference/reference-adapter.js.map +0 -1
  103. package/dist-server/service/reference/reference-assessment.js.map +0 -1
  104. package/dist-server/service/reference/reference-fill-run.js.map +0 -1
  105. package/dist-server/service/reference/reference-fill.js.map +0 -1
  106. package/dist-server/service/reference/reference-hook.js.map +0 -1
  107. package/dist-server/service/reference/reference-link-groups.js.map +0 -1
  108. package/dist-server/service/reference/reference-links.js.map +0 -1
  109. package/dist-server/service/reference/reference-live.js.map +0 -1
  110. package/dist-server/service/reference/reference-master.js.map +0 -1
  111. package/dist-server/service/reference/reference-probe.js.map +0 -1
  112. package/dist-server/service/reference/reference-progress-channel.js.map +0 -1
  113. package/dist-server/service/reference/reference-progress-subscription.js.map +0 -1
  114. package/dist-server/service/reference/reference-progress.js.map +0 -1
  115. package/dist-server/service/reference/reference-reconciliation-query.js.map +0 -1
  116. package/dist-server/service/reference/reference-reconciliation-writer.js.map +0 -1
  117. package/dist-server/service/reference/reference-reconciliation.js.map +0 -1
  118. package/dist-server/service/reference/reference-registry.js.map +0 -1
  119. package/dist-server/service/reference/reference-resolver.js.map +0 -1
  120. package/dist-server/service/reference/template-registry.js.map +0 -1
  121. package/dist-server/service/reference/twin-reference-reconciliation.js.map +0 -1
  122. package/dist-server/service/reference/twin-reference.js.map +0 -1
  123. package/dist-server/service/twin-attention/index.js.map +0 -1
  124. package/dist-server/service/twin-attention/twin-attention-query.js.map +0 -1
  125. package/dist-server/service/twin-audit/command-audit.js.map +0 -1
  126. package/dist-server/service/twin-audit/index.js.map +0 -1
  127. package/dist-server/service/twin-audit/twin-audit-event.js.map +0 -1
  128. package/dist-server/service/twin-audit/twin-audit-query.js.map +0 -1
  129. package/dist-server/service/twin-backfill/backfill-period-facts.js.map +0 -1
  130. package/dist-server/service/twin-backfill/backfill-shape.js.map +0 -1
  131. package/dist-server/service/twin-backfill/index.js.map +0 -1
  132. package/dist-server/service/twin-backfill/twin-backfill-resolver.js.map +0 -1
  133. package/dist-server/service/twin-control/index.js.map +0 -1
  134. package/dist-server/service/twin-control/twin-control-mutation.js.map +0 -1
  135. package/dist-server/service/twin-event/index.js.map +0 -1
  136. package/dist-server/service/twin-event/journal-count.js.map +0 -1
  137. package/dist-server/service/twin-event/twin-event-keys.js.map +0 -1
  138. package/dist-server/service/twin-event/twin-event-type.js.map +0 -1
  139. package/dist-server/service/twin-event/twin-event.js.map +0 -1
  140. package/dist-server/service/twin-forecast/forecast-metrics.js.map +0 -1
  141. package/dist-server/service/twin-forecast/forecast-tuning.js.map +0 -1
  142. package/dist-server/service/twin-forecast/gap-analytics.js.map +0 -1
  143. package/dist-server/service/twin-forecast/index.js.map +0 -1
  144. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +0 -1
  145. package/dist-server/service/twin-ingest-window/index.js.map +0 -1
  146. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +0 -1
  147. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +0 -1
  148. package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +0 -1
  149. package/dist-server/service/twin-instance/index.js.map +0 -1
  150. package/dist-server/service/twin-instance/twin-instance.js.map +0 -1
  151. package/dist-server/service/twin-journal/event-type-split-shape.js.map +0 -1
  152. package/dist-server/service/twin-journal/event-type-split.js.map +0 -1
  153. package/dist-server/service/twin-journal/index.js.map +0 -1
  154. package/dist-server/service/twin-journal/journal-order.js.map +0 -1
  155. package/dist-server/service/twin-journal/twin-journal-query.js.map +0 -1
  156. package/dist-server/service/twin-lifecycle/domain-catalog.js.map +0 -1
  157. package/dist-server/service/twin-lifecycle/index.js.map +0 -1
  158. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +0 -1
  159. package/dist-server/service/twin-metrics/index.js.map +0 -1
  160. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +0 -1
  161. package/dist-server/service/twin-model/axis-journal-evidence.js.map +0 -1
  162. package/dist-server/service/twin-model/choose-recipe.js.map +0 -1
  163. package/dist-server/service/twin-model/epcis-coverage.js.map +0 -1
  164. package/dist-server/service/twin-model/external-resolver.js.map +0 -1
  165. package/dist-server/service/twin-model/iec61850-coverage.js.map +0 -1
  166. package/dist-server/service/twin-model/index.js.map +0 -1
  167. package/dist-server/service/twin-model/isa95-coverage.js.map +0 -1
  168. package/dist-server/service/twin-model/item-ref.js.map +0 -1
  169. package/dist-server/service/twin-model/name-index.js.map +0 -1
  170. package/dist-server/service/twin-model/project-structure.js.map +0 -1
  171. package/dist-server/service/twin-model/standard-coverage.js.map +0 -1
  172. package/dist-server/service/twin-model/status-tally.js.map +0 -1
  173. package/dist-server/service/twin-model/twin-equipment.js.map +0 -1
  174. package/dist-server/service/twin-model/twin-lineage-query.js.map +0 -1
  175. package/dist-server/service/twin-model/twin-location.js.map +0 -1
  176. package/dist-server/service/twin-model/twin-model-item-query.js.map +0 -1
  177. package/dist-server/service/twin-model/twin-model-mutation.js.map +0 -1
  178. package/dist-server/service/twin-model/twin-model-query.js.map +0 -1
  179. package/dist-server/service/twin-model/twin-model-tree-query.js.map +0 -1
  180. package/dist-server/service/twin-model/twin-operation.js.map +0 -1
  181. package/dist-server/service/twin-readiness/index.js.map +0 -1
  182. package/dist-server/service/twin-readiness/twin-readiness-query.js.map +0 -1
  183. package/dist-server/service/twin-space/area-resolver.js.map +0 -1
  184. package/dist-server/service/twin-space/index.js.map +0 -1
  185. package/dist-server/service/twin-space/move-space.js.map +0 -1
  186. package/dist-server/service/twin-space/representation-role.js.map +0 -1
  187. package/dist-server/service/twin-space/space-integrity.js.map +0 -1
  188. package/dist-server/service/twin-space/twin-area.js.map +0 -1
  189. package/dist-server/service/twin-space/twin-space-area.js.map +0 -1
  190. package/dist-server/service/twin-space/twin-space-representation.js.map +0 -1
  191. package/dist-server/service/twin-space/twin-space-resolver.js.map +0 -1
  192. package/dist-server/service/twin-space/twin-space.js.map +0 -1
  193. package/dist-server/service/twin-state/index.js.map +0 -1
  194. package/dist-server/service/twin-state/twin-state-subscription.js.map +0 -1
  195. package/dist-server/service/twin-structure/index.js.map +0 -1
  196. package/dist-server/service/twin-structure/twin-structure.js.map +0 -1
  197. package/dist-server/service/twin-subject/event-subjects.js.map +0 -1
  198. package/dist-server/service/twin-subject/index.js.map +0 -1
  199. package/dist-server/service/twin-subject/item-resolver.js.map +0 -1
  200. package/dist-server/service/twin-subject/subject-query-shape.js.map +0 -1
  201. package/dist-server/service/twin-subject/twin-subject-backfill.js.map +0 -1
  202. package/dist-server/service/twin-subject/twin-subject-event.js.map +0 -1
  203. package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +0 -1
  204. package/dist-server/service/twin-subject/twin-subject-query.js.map +0 -1
  205. package/dist-server/service/twin-subject/twin-subject-writer.js.map +0 -1
  206. package/dist-server/service/twin-target/index.js.map +0 -1
  207. package/dist-server/service/twin-target/twin-target-resolver.js.map +0 -1
  208. package/dist-server/service/twin-target/twin-target.js.map +0 -1
  209. package/dist-shared/axis-read.js.map +0 -1
  210. package/dist-shared/entity-delta.js.map +0 -1
  211. package/dist-shared/kpi-broadcast.js.map +0 -1
  212. package/dist-shared/touched-items.js.map +0 -1
  213. package/dist-shared/twin-level.js.map +0 -1
  214. package/server/engine/attention-digest.ts +0 -102
  215. package/server/engine/canonical-ingest.ts +0 -511
  216. package/server/engine/checkpoint-fold.ts +0 -12
  217. package/server/engine/command-routing.ts +0 -67
  218. package/server/engine/declared-stimulus.ts +0 -66
  219. package/server/engine/energy-topology.ts +0 -189
  220. package/server/engine/event-time.ts +0 -96
  221. package/server/engine/index.ts +0 -51
  222. package/server/engine/ingest-dedupe.ts +0 -24
  223. package/server/engine/ingest-health.ts +0 -24
  224. package/server/engine/integration-coverage.ts +0 -147
  225. package/server/engine/integration-probes.ts +0 -144
  226. package/server/engine/integration-runner.ts +0 -95
  227. package/server/engine/integration-target-profile.ts +0 -103
  228. package/server/engine/kpi-baseline.ts +0 -202
  229. package/server/engine/kpi-fold.ts +0 -1516
  230. package/server/engine/kpi-query.ts +0 -1210
  231. package/server/engine/kpi-target.ts +0 -248
  232. package/server/engine/live-attentions.ts +0 -30
  233. package/server/engine/live-feed-registry.ts +0 -59
  234. package/server/engine/load-meter.ts +0 -393
  235. package/server/engine/local-declarations.ts +0 -779
  236. package/server/engine/log.ts +0 -72
  237. package/server/engine/loop-lag.ts +0 -120
  238. package/server/engine/measured-estimator.ts +0 -91
  239. package/server/engine/measured-yield.ts +0 -89
  240. package/server/engine/model-basis.ts +0 -162
  241. package/server/engine/model-gap.ts +0 -168
  242. package/server/engine/model-refusal.ts +0 -31
  243. package/server/engine/model-vocabulary.ts +0 -82
  244. package/server/engine/oee-accumulator.ts +0 -195
  245. package/server/engine/operation-basis.ts +0 -131
  246. package/server/engine/producer-guard.ts +0 -64
  247. package/server/engine/property-effects.ts +0 -216
  248. package/server/engine/read-time.ts +0 -77
  249. package/server/engine/restart-policy.ts +0 -55
  250. package/server/engine/runtime-key.ts +0 -58
  251. package/server/engine/spec-coverage.ts +0 -105
  252. package/server/engine/stage-path.ts +0 -172
  253. package/server/engine/state-axes.ts +0 -60
  254. package/server/engine/structure-diff.ts +0 -88
  255. package/server/engine/travel-estimator.ts +0 -138
  256. package/server/engine/twin-engine.ts +0 -4979
  257. package/server/engine/twin-state-channel.ts +0 -39
  258. package/server/engine/warm-start.ts +0 -265
  259. package/server/index.ts +0 -90
  260. package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +0 -43
  261. package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +0 -54
  262. package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +0 -53
  263. package/server/migrations/1786300000000-IndexEventTypeByTime.ts +0 -48
  264. package/server/migrations/1786400000000-IndexEventCreatedAt.ts +0 -38
  265. package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +0 -93
  266. package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +0 -66
  267. package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +0 -82
  268. package/server/migrations/1786800000000-CreateTwinReferenceReconciliations.ts +0 -39
  269. package/server/migrations/index.ts +0 -25
  270. package/server/routes.ts +0 -75
  271. package/server/service/actuation/actuation-advisor.ts +0 -131
  272. package/server/service/actuation/actuation-outcome.ts +0 -97
  273. package/server/service/actuation/actuation-rule-resolver.ts +0 -147
  274. package/server/service/actuation/actuation-rule.ts +0 -139
  275. package/server/service/actuation/approval-gateway.ts +0 -44
  276. package/server/service/actuation/catch-up-effects.ts +0 -152
  277. package/server/service/actuation/command-dispatcher.ts +0 -474
  278. package/server/service/actuation/command-store.ts +0 -236
  279. package/server/service/actuation/dispatch-after-approval.ts +0 -71
  280. package/server/service/actuation/effect-match.ts +0 -124
  281. package/server/service/actuation/index.ts +0 -27
  282. package/server/service/actuation/retry-plan.ts +0 -145
  283. package/server/service/actuation/rule-evaluate.ts +0 -352
  284. package/server/service/actuation/rule-loop.ts +0 -160
  285. package/server/service/actuation/rule-runner.ts +0 -216
  286. package/server/service/actuation/rule-wiring.ts +0 -84
  287. package/server/service/actuation/settle-effects.ts +0 -115
  288. package/server/service/actuation/sweep-dispatch.ts +0 -179
  289. package/server/service/actuation/twin-command-resolver.ts +0 -387
  290. package/server/service/actuation/twin-command.ts +0 -232
  291. package/server/service/actuation/twin-now.ts +0 -97
  292. package/server/service/index.ts +0 -100
  293. package/server/service/reference/actuation-routing.ts +0 -192
  294. package/server/service/reference/actuation-target.ts +0 -163
  295. package/server/service/reference/actuation-verification.ts +0 -85
  296. package/server/service/reference/attention-lane.ts +0 -21
  297. package/server/service/reference/connection-portability-resolver.ts +0 -171
  298. package/server/service/reference/connection-portability.ts +0 -329
  299. package/server/service/reference/control-routing.ts +0 -62
  300. package/server/service/reference/discovery-result.ts +0 -95
  301. package/server/service/reference/fill-cadence.ts +0 -29
  302. package/server/service/reference/fill-dedupe.ts +0 -66
  303. package/server/service/reference/fill-loop.ts +0 -153
  304. package/server/service/reference/fill-span.ts +0 -31
  305. package/server/service/reference/hook-contract.ts +0 -364
  306. package/server/service/reference/hook-rejected.ts +0 -53
  307. package/server/service/reference/hook-store.ts +0 -28
  308. package/server/service/reference/index.ts +0 -18
  309. package/server/service/reference/ingest-space.ts +0 -104
  310. package/server/service/reference/knob-defaults.ts +0 -59
  311. package/server/service/reference/live-cadence.ts +0 -129
  312. package/server/service/reference/live-feed-lease.ts +0 -56
  313. package/server/service/reference/live-ingest.ts +0 -94
  314. package/server/service/reference/reference-adapter.ts +0 -985
  315. package/server/service/reference/reference-assessment.ts +0 -250
  316. package/server/service/reference/reference-fill-run.ts +0 -179
  317. package/server/service/reference/reference-fill.ts +0 -223
  318. package/server/service/reference/reference-hook.ts +0 -479
  319. package/server/service/reference/reference-link-groups.ts +0 -21
  320. package/server/service/reference/reference-links.ts +0 -77
  321. package/server/service/reference/reference-live.ts +0 -420
  322. package/server/service/reference/reference-master.ts +0 -999
  323. package/server/service/reference/reference-probe.ts +0 -264
  324. package/server/service/reference/reference-progress-channel.ts +0 -26
  325. package/server/service/reference/reference-progress-subscription.ts +0 -78
  326. package/server/service/reference/reference-progress.ts +0 -95
  327. package/server/service/reference/reference-reconciliation-query.ts +0 -28
  328. package/server/service/reference/reference-reconciliation-writer.ts +0 -38
  329. package/server/service/reference/reference-reconciliation.ts +0 -55
  330. package/server/service/reference/reference-registry.ts +0 -17
  331. package/server/service/reference/reference-resolver.ts +0 -969
  332. package/server/service/reference/template-registry.ts +0 -85
  333. package/server/service/reference/twin-reference-reconciliation.ts +0 -27
  334. package/server/service/reference/twin-reference.ts +0 -190
  335. package/server/service/twin-attention/index.ts +0 -3
  336. package/server/service/twin-attention/twin-attention-query.ts +0 -70
  337. package/server/service/twin-audit/command-audit.ts +0 -114
  338. package/server/service/twin-audit/index.ts +0 -5
  339. package/server/service/twin-audit/twin-audit-event.ts +0 -158
  340. package/server/service/twin-audit/twin-audit-query.ts +0 -72
  341. package/server/service/twin-backfill/backfill-period-facts.ts +0 -168
  342. package/server/service/twin-backfill/backfill-shape.ts +0 -86
  343. package/server/service/twin-backfill/index.ts +0 -3
  344. package/server/service/twin-backfill/twin-backfill-resolver.ts +0 -35
  345. package/server/service/twin-control/index.ts +0 -3
  346. package/server/service/twin-control/twin-control-mutation.ts +0 -150
  347. package/server/service/twin-event/index.ts +0 -3
  348. package/server/service/twin-event/journal-count.ts +0 -53
  349. package/server/service/twin-event/twin-event-keys.ts +0 -215
  350. package/server/service/twin-event/twin-event-type.ts +0 -68
  351. package/server/service/twin-event/twin-event.ts +0 -250
  352. package/server/service/twin-forecast/forecast-metrics.ts +0 -106
  353. package/server/service/twin-forecast/forecast-tuning.ts +0 -40
  354. package/server/service/twin-forecast/gap-analytics.ts +0 -139
  355. package/server/service/twin-forecast/index.ts +0 -3
  356. package/server/service/twin-forecast/twin-forecast-query.ts +0 -486
  357. package/server/service/twin-ingest-window/index.ts +0 -7
  358. package/server/service/twin-ingest-window/twin-ingest-window-query.ts +0 -125
  359. package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +0 -57
  360. package/server/service/twin-ingest-window/twin-ingest-window.ts +0 -113
  361. package/server/service/twin-instance/index.ts +0 -3
  362. package/server/service/twin-instance/twin-instance.ts +0 -199
  363. package/server/service/twin-journal/event-type-split-shape.ts +0 -112
  364. package/server/service/twin-journal/event-type-split.ts +0 -144
  365. package/server/service/twin-journal/index.ts +0 -3
  366. package/server/service/twin-journal/journal-order.ts +0 -20
  367. package/server/service/twin-journal/twin-journal-query.ts +0 -615
  368. package/server/service/twin-lifecycle/domain-catalog.ts +0 -51
  369. package/server/service/twin-lifecycle/index.ts +0 -3
  370. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +0 -285
  371. package/server/service/twin-metrics/index.ts +0 -3
  372. package/server/service/twin-metrics/twin-metrics-query.ts +0 -172
  373. package/server/service/twin-model/axis-journal-evidence.ts +0 -57
  374. package/server/service/twin-model/choose-recipe.ts +0 -31
  375. package/server/service/twin-model/epcis-coverage.ts +0 -251
  376. package/server/service/twin-model/external-resolver.ts +0 -173
  377. package/server/service/twin-model/iec61850-coverage.ts +0 -111
  378. package/server/service/twin-model/index.ts +0 -25
  379. package/server/service/twin-model/isa95-coverage.ts +0 -320
  380. package/server/service/twin-model/item-ref.ts +0 -80
  381. package/server/service/twin-model/name-index.ts +0 -94
  382. package/server/service/twin-model/project-structure.ts +0 -213
  383. package/server/service/twin-model/standard-coverage.ts +0 -35
  384. package/server/service/twin-model/status-tally.ts +0 -37
  385. package/server/service/twin-model/twin-equipment.ts +0 -191
  386. package/server/service/twin-model/twin-lineage-query.ts +0 -327
  387. package/server/service/twin-model/twin-location.ts +0 -147
  388. package/server/service/twin-model/twin-model-item-query.ts +0 -1029
  389. package/server/service/twin-model/twin-model-mutation.ts +0 -503
  390. package/server/service/twin-model/twin-model-query.ts +0 -792
  391. package/server/service/twin-model/twin-model-tree-query.ts +0 -211
  392. package/server/service/twin-model/twin-operation.ts +0 -157
  393. package/server/service/twin-readiness/index.ts +0 -3
  394. package/server/service/twin-readiness/twin-readiness-query.ts +0 -96
  395. package/server/service/twin-space/area-resolver.ts +0 -75
  396. package/server/service/twin-space/index.ts +0 -8
  397. package/server/service/twin-space/move-space.ts +0 -262
  398. package/server/service/twin-space/representation-role.ts +0 -15
  399. package/server/service/twin-space/space-integrity.ts +0 -293
  400. package/server/service/twin-space/twin-area.ts +0 -63
  401. package/server/service/twin-space/twin-space-area.ts +0 -66
  402. package/server/service/twin-space/twin-space-representation.ts +0 -99
  403. package/server/service/twin-space/twin-space-resolver.ts +0 -582
  404. package/server/service/twin-space/twin-space.ts +0 -148
  405. package/server/service/twin-state/index.ts +0 -3
  406. package/server/service/twin-state/twin-state-subscription.ts +0 -62
  407. package/server/service/twin-structure/index.ts +0 -3
  408. package/server/service/twin-structure/twin-structure.ts +0 -96
  409. package/server/service/twin-subject/event-subjects.ts +0 -162
  410. package/server/service/twin-subject/index.ts +0 -10
  411. package/server/service/twin-subject/item-resolver.ts +0 -92
  412. package/server/service/twin-subject/subject-query-shape.ts +0 -84
  413. package/server/service/twin-subject/twin-subject-backfill.ts +0 -196
  414. package/server/service/twin-subject/twin-subject-event.ts +0 -101
  415. package/server/service/twin-subject/twin-subject-fast-path.ts +0 -346
  416. package/server/service/twin-subject/twin-subject-query.ts +0 -210
  417. package/server/service/twin-subject/twin-subject-writer.ts +0 -189
  418. package/server/service/twin-target/index.ts +0 -5
  419. package/server/service/twin-target/twin-target-resolver.ts +0 -142
  420. package/server/service/twin-target/twin-target.ts +0 -97
  421. package/server/types/global.d.ts +0 -22
  422. package/shared/axis-read.ts +0 -28
  423. package/shared/entity-delta.ts +0 -335
  424. package/shared/kpi-broadcast.ts +0 -13
  425. package/shared/touched-items.ts +0 -73
  426. package/shared/twin-level.ts +0 -48
  427. package/test/ack-shape-alignment.test.ts +0 -97
  428. package/test/actuation-advisor.test.ts +0 -55
  429. package/test/actuation-approval-door.test.ts +0 -411
  430. package/test/actuation-dispatch.test.ts +0 -209
  431. package/test/actuation-effect.test.ts +0 -162
  432. package/test/actuation-outcome.test.ts +0 -152
  433. package/test/actuation-rule-runner.test.ts +0 -281
  434. package/test/actuation-rule.test.ts +0 -266
  435. package/test/actuation-seam.test.ts +0 -255
  436. package/test/actuation-settle.test.ts +0 -164
  437. package/test/actuation-target.test.ts +0 -145
  438. package/test/actuation-verification-state.test.ts +0 -139
  439. package/test/adopt-structure-live.test.ts +0 -133
  440. package/test/aggregate-not-findone.test.ts +0 -112
  441. package/test/area-resolver-db.test.ts +0 -110
  442. package/test/attention-digest.test.ts +0 -161
  443. package/test/axis-declaration-passthrough-db.test.ts +0 -152
  444. package/test/axis-journal-evidence.test.ts +0 -71
  445. package/test/axis-read.test.ts +0 -188
  446. package/test/backfill-shape.test.ts +0 -89
  447. package/test/boot-resume.test.ts +0 -287
  448. package/test/broadcast-cost-baseline.test.ts +0 -201
  449. package/test/broadcast-period.test.ts +0 -58
  450. package/test/broadcast-queue-overflow.test.ts +0 -244
  451. package/test/canonical-ingest-vocabularies.test.ts +0 -451
  452. package/test/canonical-quantity-door.test.ts +0 -61
  453. package/test/capability-mapping.test.ts +0 -89
  454. package/test/checkpoint-refuses-empty.test.ts +0 -103
  455. package/test/choose-recipe.test.ts +0 -117
  456. package/test/column-type-portability.test.ts +0 -122
  457. package/test/command-routing.test.ts +0 -61
  458. package/test/command-store-writes-columns.test.ts +0 -126
  459. package/test/connection-portability-doors.test.ts +0 -87
  460. package/test/connector-capability-declaration.test.ts +0 -195
  461. package/test/contract-layer-guard.test.ts +0 -48
  462. package/test/control-capability.test.ts +0 -98
  463. package/test/cursor-stall-not-read-failure.test.ts +0 -126
  464. package/test/declaration-reaches-model.test.ts +0 -226
  465. package/test/declared-location-types.test.ts +0 -89
  466. package/test/declared-stimulus.test.ts +0 -88
  467. package/test/dedupe-transformation.test.ts +0 -112
  468. package/test/discovery-result.test.ts +0 -75
  469. package/test/dispatch-after-approval-source.test.ts +0 -81
  470. package/test/duration-estimators.test.ts +0 -144
  471. package/test/energy-topology.test.ts +0 -113
  472. package/test/entity-delta.test.ts +0 -352
  473. package/test/equipment-identity-reaches.test.ts +0 -57
  474. package/test/event-subjects.test.ts +0 -148
  475. package/test/event-time-column.test.ts +0 -67
  476. package/test/event-type-split.test.ts +0 -178
  477. package/test/external-resolver.test.ts +0 -177
  478. package/test/fact-scope-wiring.test.ts +0 -96
  479. package/test/fill-dedupe.test.ts +0 -59
  480. package/test/fill-loop.test.ts +0 -35
  481. package/test/first-envelope.test.ts +0 -153
  482. package/test/fold-gap-speaks.test.ts +0 -53
  483. package/test/fold-shift-dst.test.ts +0 -110
  484. package/test/forecast-metrics.test.ts +0 -157
  485. package/test/forecast-tuning.test.ts +0 -42
  486. package/test/gap-analytics.test.ts +0 -113
  487. package/test/generated-not-counted.test.ts +0 -99
  488. package/test/guard-roots.ts +0 -76
  489. package/test/home-in-area.test.ts +0 -90
  490. package/test/hook-address.test.ts +0 -28
  491. package/test/hook-rejected-shape.test.ts +0 -86
  492. package/test/hook-response-sum.test.ts +0 -193
  493. package/test/hook-sequence.test.ts +0 -333
  494. package/test/ingest-bench.test.ts +0 -70
  495. package/test/ingest-dedupe.test.ts +0 -56
  496. package/test/ingest-expected-quiet.test.ts +0 -111
  497. package/test/ingest-health-engine.test.ts +0 -248
  498. package/test/ingest-health-wiring.test.ts +0 -120
  499. package/test/ingest-health.test.ts +0 -306
  500. package/test/ingest-history.test.ts +0 -247
  501. package/test/ingest-idempotent.test.ts +0 -211
  502. package/test/ingest-reconcile-four-ways.test.ts +0 -97
  503. package/test/ingest-rules-header.test.ts +0 -100
  504. package/test/ingest-running-guard.test.ts +0 -136
  505. package/test/ingest-space.test.ts +0 -78
  506. package/test/ingest-window-rolls-unobserved.test.ts +0 -72
  507. package/test/ingest-wiring-guard.test.ts +0 -197
  508. package/test/instance-cache-lifecycle.test.ts +0 -110
  509. package/test/intake-mapping-parity.test.ts +0 -175
  510. package/test/integration-probes.test.ts +0 -103
  511. package/test/integration-runner.test.ts +0 -95
  512. package/test/item-ref.test.ts +0 -78
  513. package/test/journal-order-axis.test.ts +0 -80
  514. package/test/journal-read-discipline.test.ts +0 -186
  515. package/test/journal-retention.test.ts +0 -275
  516. package/test/journal-sort-axis.test.ts +0 -142
  517. package/test/journal-write-door.test.ts +0 -110
  518. package/test/journal-write-trend.test.ts +0 -115
  519. package/test/kernel-kind-guard.test.ts +0 -98
  520. package/test/knob-defaults.test.ts +0 -72
  521. package/test/kpi-baseline-db.test.ts +0 -216
  522. package/test/kpi-baseline.test.ts +0 -196
  523. package/test/kpi-fold.test.ts +0 -1456
  524. package/test/kpi-query-bench.test.ts +0 -130
  525. package/test/lens-own-places.test.ts +0 -50
  526. package/test/lineage-survives-restart.test.ts +0 -234
  527. package/test/live-cadence.test.ts +0 -170
  528. package/test/live-cursor-wiring.test.ts +0 -87
  529. package/test/live-feed-lease.test.ts +0 -63
  530. package/test/live-feed-registry.test.ts +0 -75
  531. package/test/live-kernel-facts.test.ts +0 -161
  532. package/test/live-mirror-parity.test.ts +0 -286
  533. package/test/load-meter.test.ts +0 -328
  534. package/test/local-declarations.test.ts +0 -662
  535. package/test/log-stamp.test.ts +0 -59
  536. package/test/loop-lag.test.ts +0 -82
  537. package/test/master-to-twin.test.ts +0 -279
  538. package/test/measured-yield.test.ts +0 -90
  539. package/test/merge-streams.test.ts +0 -70
  540. package/test/mirror-resumes-from-checkpoint.test.ts +0 -192
  541. package/test/model-basis.test.ts +0 -141
  542. package/test/model-gap.test.ts +0 -153
  543. package/test/model-refusal.test.ts +0 -75
  544. package/test/model-vocabulary.test.ts +0 -114
  545. package/test/move-space.test.ts +0 -149
  546. package/test/mutation-gate.test.ts +0 -122
  547. package/test/oee-accumulator.test.ts +0 -204
  548. package/test/oee-site-calendar.test.ts +0 -146
  549. package/test/open-doors.test.ts +0 -197
  550. package/test/operation-basis.test.ts +0 -127
  551. package/test/operational-vocabulary.test.ts +0 -108
  552. package/test/operations-capability-db.test.ts +0 -165
  553. package/test/order-and-transaction-split.test.ts +0 -107
  554. package/test/order-fold-host.test.ts +0 -112
  555. package/test/producer-guard.test.ts +0 -66
  556. package/test/project-structure-db.test.ts +0 -226
  557. package/test/projection-reaches-screen.test.ts +0 -277
  558. package/test/projection-reads-declared.test.ts +0 -109
  559. package/test/property-effects.test.ts +0 -128
  560. package/test/provenance-promotion.test.ts +0 -99
  561. package/test/read-failure-ledger.test.ts +0 -106
  562. package/test/read-failure-visible.test.ts +0 -145
  563. package/test/read-time.test.ts +0 -118
  564. package/test/reference-fill.test.ts +0 -235
  565. package/test/reference-grounding.test.ts +0 -70
  566. package/test/reference-hook.test.ts +0 -177
  567. package/test/reference-links.test.ts +0 -56
  568. package/test/reference-reconciliation.test.ts +0 -39
  569. package/test/registry-key-guard.test.ts +0 -80
  570. package/test/rejection-carries-event-id.test.ts +0 -101
  571. package/test/rename-twin.test.ts +0 -89
  572. package/test/resolve-ts-siblings.mjs +0 -52
  573. package/test/restart-policy.test.ts +0 -111
  574. package/test/resync-origin-site.test.ts +0 -83
  575. package/test/retry-plan.test.ts +0 -139
  576. package/test/revision-axis.test.ts +0 -110
  577. package/test/runtime-key.test.ts +0 -66
  578. package/test/save-intake-collision.test.ts +0 -91
  579. package/test/scale-twin-bench.test.ts +0 -103
  580. package/test/secrets-at-rest.test.ts +0 -135
  581. package/test/snapshot-freshness.test.ts +0 -60
  582. package/test/source-outcome-audit.test.ts +0 -104
  583. package/test/space-integrity.test.ts +0 -223
  584. package/test/space-representation.test.ts +0 -66
  585. package/test/space-scope-includes-stopped.test.ts +0 -55
  586. package/test/spec-coverage.test.ts +0 -113
  587. package/test/stage-path.test.ts +0 -95
  588. package/test/standard-coverage.test.ts +0 -148
  589. package/test/state-axes.test.ts +0 -74
  590. package/test/status-tally.test.ts +0 -55
  591. package/test/streamline-e2e.test.ts +0 -76
  592. package/test/structure-revision-db.test.ts +0 -315
  593. package/test/subject-fast-path.test.ts +0 -148
  594. package/test/subject-read-model.test.ts +0 -175
  595. package/test/sweep-dispatch.test.ts +0 -191
  596. package/test/tenant-registry-db.test.ts +0 -149
  597. package/test/time-range.test.ts +0 -152
  598. package/test/touched-items.test.ts +0 -61
  599. package/test/twin-audit.test.ts +0 -83
  600. package/test/twin-event-keys.test.ts +0 -193
  601. package/test/twin-model-item-db.test.ts +0 -319
  602. package/test/twin-model-parent-relation-db.test.ts +0 -125
  603. package/test/twin-model-tree-db.test.ts +0 -209
  604. package/test/twin-origin-resync.test.ts +0 -133
  605. package/test/twin-state-channel.test.ts +0 -111
  606. package/test/vocabulary-guard.test.ts +0 -43
  607. package/test/warm-start-seam.test.ts +0 -162
  608. package/test/warm-start.test.ts +0 -297
  609. package/test/withheld-door.test.ts +0 -95
  610. package/test/yield-loop.test.ts +0 -199
  611. package/tsconfig.json +0 -15
  612. package/tsconfig.shared.json +0 -23
  613. package/tsconfig.shared.tsbuildinfo +0 -1
  614. package/tsconfig.tsbuildinfo +0 -1
@@ -1,164 +0,0 @@
1
- /*
2
- * **폐루프의 배선** — 관측이 들어올 때 나간 지시와 실제로 이어지는가.
3
- *
4
- * 판정은 `actuation-effect.test.ts` 가 지킨다. 여기서 보는 것은 **그 판정이 유입 경로에 서 있는가**다
5
- * — 봉투에서 오더 보고를 골라내는가, 저장소에 적히는가, 실패해도 관측 유입이 멈추지 않는가.
6
- *
7
- * 마지막 것이 특히 중요하다. 효과를 적다 실패해서 유입이 멈추면 **고치는 동안 트윈이 눈을 감는다.**
8
- * 효과는 다음 보고에 다시 이을 수 있고 관측은 다시 오지 않는다.
9
- */
10
- import { test } from 'node:test'
11
- import assert from 'node:assert/strict'
12
-
13
- import { OP_EVENT } from '@operato/ops-contract'
14
-
15
- import type { CommandStore, StoredCommand } from '../server/service/actuation/command-dispatcher.js'
16
- import { orderObservationsIn, settleEffects } from '../server/service/actuation/settle-effects.js'
17
-
18
- const DOMAIN = 'd-1'
19
- const AT = '2026-09-02T09:00:00.000Z'
20
-
21
- /**
22
- * 실측한 봉투 모양 그대로 — 훅과 라이브가 같은 것을 낸다.
23
- *
24
- * `data` 를 따로 뺀다. 처음에 `...over` 를 뒤에 두었더니 병합한 `data` 를 통째로 덮어써서 `orderId`
25
- * 가 사라졌고, **시험이 이을 것이 없는 봉투로 판정을 부르고 있었다.**
26
- */
27
- const orderEnv = ({ data, ...over }: Record<string, any> = {}) => ({
28
- eventId: `e-${Math.random()}`,
29
- eventType: OP_EVENT.order,
30
- eventTime: AT,
31
- tenantId: DOMAIN,
32
- ...over,
33
- data: { orderId: 'WO-20260902-005', kind: 'workorder', status: 'released', ...(data ?? {}) }
34
- })
35
-
36
- const otherEnv = () => ({ eventId: 'x', eventType: OP_EVENT.equipment, eventTime: AT, tenantId: DOMAIN, data: {} })
37
-
38
- function makeStore(seed: Partial<StoredCommand>[] = []) {
39
- const rows = seed.map(c => ({ id: 'cmd-1', instanceId: 'twin-a', type: 'production.order', state: 'acked', ...c }) as any)
40
- const written: any[] = []
41
- const store: CommandStore & { written: any[]; queries: string[][] } = {
42
- written,
43
- queries: [],
44
- load: async () => null,
45
- save: async () => {},
46
- create: async (_d, c) => c,
47
- byDispatchRef: async (_d, refs) => {
48
- store.queries.push([...refs])
49
- return new Map(rows.filter(r => r.dispatchRef && refs.includes(r.dispatchRef)).map(r => [r.dispatchRef, r]))
50
- },
51
- recordEffects: async (_d, updates) => void written.push(...updates)
52
- }
53
- return store
54
- }
55
-
56
- /* ── 봉투에서 골라낸다 ──────────────────────────────────────────────────────── */
57
-
58
- test('★ 오더 보고만 골라낸다 — 다른 어휘를 오더로 읽지 않는다', () => {
59
- const out = orderObservationsIn([orderEnv(), otherEnv(), orderEnv({ data: { orderId: 'WO-2' } })])
60
-
61
- assert.equal(out.length, 2)
62
- assert.deepEqual(out.map(o => o.orderId).sort(), ['WO-2', 'WO-20260902-005'])
63
- })
64
-
65
- test('★ 시각은 봉투의 것을 쓴다 — 우리가 처리한 시각이 아니다', () => {
66
- const out = orderObservationsIn([orderEnv({ eventTime: '2026-08-31T01:02:03.000Z' })])
67
-
68
- assert.equal(out[0]!.at, '2026-08-31T01:02:03.000Z')
69
- })
70
-
71
- test('식별자 없는 보고는 골라내지 않는다 — 이을 수 없는 것을 판정에 넘기지 않는다', () => {
72
- assert.deepEqual(orderObservationsIn([orderEnv({ data: { orderId: '' } })]), [])
73
- })
74
-
75
- test('봉투가 없어도 터지지 않는다 — 유입 경로에서 부른다', () => {
76
- assert.deepEqual(orderObservationsIn(undefined as any), [])
77
- assert.deepEqual(orderObservationsIn([null, undefined] as any), [])
78
- })
79
-
80
- /* ── 실제로 적힌다 ─────────────────────────────────────────────────────────── */
81
-
82
- test('★ 우리가 낸 지시의 보고가 저장소에 적힌다 — 이것이 폐루프가 닫히는 순간이다', async () => {
83
- const store = makeStore([{ id: 'cmd-1', dispatchRef: 'WO-20260902-005' }])
84
- const out = await settleEffects({ domainId: DOMAIN, envelopes: [orderEnv()], store })
85
-
86
- assert.equal(out.recorded, 1)
87
- assert.deepEqual(store.written, [{ commandId: 'cmd-1', status: 'released', at: AT, seen: 1 }])
88
- })
89
-
90
- test('★ 오더 보고가 없는 묶음은 저장소를 건드리지 않는다 — 유입은 초당 수천 건이 지난다', async () => {
91
- const store = makeStore([{ dispatchRef: 'WO-20260902-005' }])
92
- const out = await settleEffects({ domainId: DOMAIN, envelopes: [otherEnv(), otherEnv()], store })
93
-
94
- assert.deepEqual(store.queries, [], '오더가 없는데 저장소에 물었다')
95
- assert.equal(out.recorded, 0)
96
- })
97
-
98
- test('★ 찾아볼 식별자만 묶어서 한 번 묻는다', async () => {
99
- const store = makeStore([{ dispatchRef: 'WO-1' }])
100
- await settleEffects({
101
- domainId: DOMAIN,
102
- envelopes: [orderEnv({ data: { orderId: 'WO-1' } }), orderEnv({ data: { orderId: 'WO-1' } }), orderEnv({ data: { orderId: 'WO-2' } })],
103
- store
104
- })
105
-
106
- assert.equal(store.queries.length, 1, '보고마다 질의를 붙였다')
107
- assert.deepEqual(store.queries[0]!.sort(), ['WO-1', 'WO-2'])
108
- })
109
-
110
- test('우리가 내지 않은 오더만 온 묶음은 아무것도 적지 않는다', async () => {
111
- const store = makeStore([{ dispatchRef: 'WO-우리것' }])
112
- const out = await settleEffects({ domainId: DOMAIN, envelopes: [orderEnv({ data: { orderId: 'WO-남의것' } })], store })
113
-
114
- assert.deepEqual(store.written, [])
115
- assert.equal(out.unmatched, 1)
116
- })
117
-
118
- test('★ 이미 적힌 효과에서 이어 센다 — 저장소가 든 값을 판정에 넘긴다', async () => {
119
- const store = makeStore([
120
- { id: 'cmd-1', dispatchRef: 'WO-20260902-005', effect: { status: 'released', at: AT, seen: 2 } }
121
- ])
122
- await settleEffects({ domainId: DOMAIN, envelopes: [orderEnv({ data: { status: 'in-progress' } })], store })
123
-
124
- assert.equal(store.written[0]!.seen, 3)
125
- })
126
-
127
- /* ── 관측 유입을 멈추지 않는다 ─────────────────────────────────────────────── */
128
-
129
- test('★ 저장소가 터져도 던지지 않는다 — 고치는 동안 트윈이 눈을 감으면 안 된다', async () => {
130
- const store = makeStore([{ dispatchRef: 'WO-20260902-005' }])
131
- store.byDispatchRef = async () => {
132
- throw new Error('연결이 끊겼다')
133
- }
134
-
135
- const out = await settleEffects({ domainId: DOMAIN, envelopes: [orderEnv()], store })
136
- assert.deepEqual(out, { recorded: 0, unmatched: 0 })
137
- })
138
-
139
- test('★ 적다가 터져도 던지지 않는다', async () => {
140
- const store = makeStore([{ dispatchRef: 'WO-20260902-005' }])
141
- store.recordEffects = async () => {
142
- throw new Error('쓰다 실패했다')
143
- }
144
-
145
- const out = await settleEffects({ domainId: DOMAIN, envelopes: [orderEnv()], store })
146
- assert.deepEqual(out, { recorded: 0, unmatched: 0 })
147
- })
148
-
149
- test('★ 저장소에 이을 자리가 없으면 조용히 지나지 않는다 — 영원히 모르는 상태가 된다', async () => {
150
- const said: string[] = []
151
- const warn = console.warn
152
- console.warn = (...a: unknown[]) => void said.push(a.join(' '))
153
-
154
- try {
155
- const store = makeStore([{ dispatchRef: 'WO-20260902-005' }])
156
- delete (store as any).byDispatchRef
157
-
158
- const out = await settleEffects({ domainId: DOMAIN, envelopes: [orderEnv()], store })
159
- assert.equal(out.recorded, 0)
160
- assert.ok(said.join('\n').includes('byDispatchRef'), '무엇이 없어서인지 말하지 않았다')
161
- } finally {
162
- console.warn = warn
163
- }
164
- })
@@ -1,145 +0,0 @@
1
- /*
2
- * **승인된 조치를 어디로 보낼 수 있나** — 그 판정.
3
- *
4
- * 이 판정이 없어서 실제로 끊겨 있었다. 넘기는 리졸버가 어댑터를 찾지도 않고 「구현이 없습니다」를
5
- * 답했고, MES 커넥터는 그때 이미 `actuate` 를 다 만들어 두었다. 답이 그럴듯해서 설계 문서에도 다른
6
- * 레인에도 그대로 옮겼다.
7
- *
8
- * 그래서 여기서 지키는 것은 둘이다 — **보낼 수 있으면 보내는가**, 그리고 **못 보낼 때 무엇이 없어서
9
- * 인지 말하는가.** 뒤엣것이 없으면 사람은 커넥터를 다시 만들려 든다.
10
- */
11
- import { test } from 'node:test'
12
- import assert from 'node:assert/strict'
13
-
14
- import { actuationTarget, isActuationAllowed, type ActuationTargetInput } from '../server/service/reference/actuation-target.js'
15
-
16
- const input = (over: Partial<ActuationTargetInput> = {}): ActuationTargetInput => ({
17
- instanceId: 'twin-a',
18
- twinExists: true,
19
- siteId: 'plant-a',
20
- ref: { source: 'twin-a', adapterType: 'operato-plant' },
21
- adapterRegistered: true,
22
- capabilities: ['live', 'actuate'],
23
- declaresActuate: true,
24
- hasActuateImpl: true,
25
- ...over
26
- })
27
-
28
- /** 거절 코드를 꺼낸다 — 통과했으면 시험을 세운다(캐스팅으로 덮지 않는다). */
29
- function refusalOf(t: ReturnType<typeof actuationTarget>): string {
30
- assert.equal(isActuationAllowed(t), false, '거절해야 하는데 통과했다')
31
- return (t as any).code
32
- }
33
-
34
- /* ── 보낼 수 있으면 어디로까지 답한다 ───────────────────────────────────────── */
35
-
36
- test('★ 선언과 구현이 다 있으면 보낼 수 있다 — 어디로까지 답한다', () => {
37
- const t = actuationTarget(input())
38
-
39
- assert.equal(isActuationAllowed(t), true)
40
- assert.deepEqual(t, { ok: true, siteId: 'plant-a', adapterType: 'operato-plant', source: 'twin-a' })
41
- })
42
-
43
- test('사이트 이름의 앞뒤 공백은 다듬는다 — 주소에 그대로 들어가는 값이다', () => {
44
- const t = actuationTarget(input({ siteId: ' plant-a ' }))
45
- assert.equal((t as any).siteId, 'plant-a')
46
- })
47
-
48
- /* ── 구현만 있고 선언이 없는 경우를 따로 말한다 ────────────────────────────── */
49
-
50
- test('★ 구현은 있는데 선언이 없으면 그렇게 말한다 — 커넥터를 다시 만들게 하지 않는다', () => {
51
- /*
52
- * 실제로 있던 상태다. `operato-plant` 가 `actuate` 를 만들어 두고 `capabilities: ['live','control']` 만
53
- * 선언했다. 「이 원본은 조치를 받지 않습니다」로 뭉개면 고칠 한 줄을 못 찾는다.
54
- */
55
- const t = actuationTarget(input({ capabilities: ['live', 'control'], declaresActuate: false, hasActuateImpl: true }))
56
-
57
- assert.equal(refusalOf(t), 'not-declared')
58
- assert.match((t as any).detail, /capabilities/, '무엇을 고쳐야 하는지 말하지 않는다')
59
- })
60
-
61
- test('★ 구현도 선언도 없으면 다른 코드로 말한다 — 고칠 것이 다르다', () => {
62
- const t = actuationTarget(input({ capabilities: ['live'], declaresActuate: false, hasActuateImpl: false }))
63
-
64
- assert.equal(refusalOf(t), 'not-supported')
65
- assert.match((t as any).detail, /관측만/)
66
- })
67
-
68
- test('★ 선언은 있는데 구현이 없으면 「관측만 냅니다」가 아니다 — 그 사람은 조치를 하겠다고 적었다', () => {
69
- /*
70
- * 만들다 만 커넥터다. 등록 검사는 이쪽을 **말하지 않는다** — 구현했는데 선언 안 한 반대 방향만 본다.
71
- * 그러니 이 자리가 말하지 않으면 아무도 말하지 않고, 사람은 자기가 적어 둔 선언을 믿고 조치가 되는
72
- * 줄로 읽는다.
73
- */
74
- const t = actuationTarget(input({ capabilities: ['live'], declaresActuate: true, hasActuateImpl: false }))
75
-
76
- assert.equal(refusalOf(t), 'not-implemented')
77
- assert.doesNotMatch((t as any).detail, /관측만/, '선언한 사람에게 「관측만 냅니다」라고 답했다')
78
- assert.match((t as any).detail, /actuate/, '무엇을 만들어야 하는지 말하지 않는다')
79
- })
80
-
81
- test('낼 수 있나는 능력 판정만 본다 — 선언·구현 두 값은 이유를 말하기 위한 것이다', () => {
82
- /*
83
- * `capabilitiesOf` 가 선언과 구현을 함께 보고 답한 값이 판정의 근거다. 여기서 두 값으로 다시
84
- * 판단하면 규칙이 두 벌이 되고, 한쪽만 고쳐지는 날이 온다.
85
- */
86
- const t = actuationTarget(input({ capabilities: ['actuate'], declaresActuate: false, hasActuateImpl: false }))
87
- assert.equal(isActuationAllowed(t), true, '능력 판정의 결과를 신뢰하지 않고 여기서 다시 판단했다')
88
- })
89
-
90
- /* ── 모르면 보내지 않는다 ───────────────────────────────────────────────────── */
91
-
92
- test('★ 어느 사이트에서 왔는지 모르면 보내지 않는다 — 첫 번째 사이트로 보내지 않는다', () => {
93
- /*
94
- * 원본 하나가 여러 사이트를 낸다. 모르는 채로 아무 데나 보내면 **잘못된 공장이 실제로 만든다.**
95
- * 구동(control)은 사이트를 몰라도 넘기지만 이쪽은 다르다.
96
- */
97
- assert.equal(refusalOf(actuationTarget(input({ siteId: undefined }))), 'no-site')
98
- assert.equal(refusalOf(actuationTarget(input({ siteId: ' ' }))), 'no-site', '공백을 사이트 이름으로 읽었다')
99
- })
100
-
101
- test('★ 원본이 없는 트윈에는 보내지 않는다 — 시뮬레이션으로만 세운 트윈이다', () => {
102
- assert.equal(refusalOf(actuationTarget(input({ ref: undefined }))), 'no-source')
103
- })
104
-
105
- test('★ 거절 문장이 어느 트윈인지 말한다 — 「모르는 트윈입니다」만으로는 찾을 수 없다', () => {
106
- for (const over of [{ twinExists: false, ref: undefined }, { ref: undefined }, { siteId: undefined }]) {
107
- const t = actuationTarget(input(over)) as any
108
- assert.match(t.detail, /twin-a/, `${t.code} 가 어느 트윈인지 말하지 않는다`)
109
- }
110
- })
111
-
112
- test('모르는 트윈은 원본을 묻기 전에 거절한다', () => {
113
- assert.equal(refusalOf(actuationTarget(input({ twinExists: false, ref: undefined }))), 'unknown-twin')
114
- })
115
-
116
- test('등록되지 않은 커넥터는 능력을 묻기 전에 거절한다 — 물을 데가 없다', () => {
117
- const t = actuationTarget(input({ adapterRegistered: false, capabilities: [], hasActuateImpl: false }))
118
-
119
- assert.equal(refusalOf(t), 'no-adapter')
120
- assert.match((t as any).detail, /operato-plant/, '어느 커넥터인지 말하지 않으면 찾을 수 없다')
121
- })
122
-
123
- /* ── 거절은 전부 코드를 갖는다 ──────────────────────────────────────────────── */
124
-
125
- test('★ 모든 거절에 코드와 문장이 함께 있다 — 화면이 다음 할 일을 가를 수 있게', () => {
126
- const cases: Partial<ActuationTargetInput>[] = [
127
- { twinExists: false },
128
- { ref: undefined },
129
- { adapterRegistered: false, capabilities: [], declaresActuate: false, hasActuateImpl: false },
130
- { capabilities: ['live', 'control'], declaresActuate: false, hasActuateImpl: true },
131
- { capabilities: ['live'], declaresActuate: true, hasActuateImpl: false },
132
- { capabilities: ['live'], declaresActuate: false, hasActuateImpl: false },
133
- { siteId: undefined }
134
- ]
135
-
136
- const codes = cases.map(over => {
137
- const t = actuationTarget(input(over)) as any
138
- assert.equal(t.ok, false)
139
- assert.ok(t.code, '거절에 코드가 없다')
140
- assert.ok(t.detail?.length > 10, '거절에 사람이 읽을 문장이 없다')
141
- return t.code
142
- })
143
-
144
- assert.equal(new Set(codes).size, codes.length, '다른 원인이 같은 코드로 답했다 — 화면이 구별할 수 없다')
145
- })
@@ -1,139 +0,0 @@
1
- /*
2
- * ★ **한 번 넘겨 봤나** — 설정이 맞는 것과 저쪽이 받는 것은 다르다 (ADR-0046 ②).
3
- *
4
- * 주소도 비밀값도 다 적혀 있는데 저쪽 프로세스가 그 값을 잃은 일이 있었다(§`actuationReadiness`).
5
- * 그것은 넘겨 봐야만 알고, 그래서 「아직 안 해 봤다」와 「해 봤고 됐다」와 「해 봤고 안 됐다」가
6
- * 서로 다른 사실이다. 이 시험은 그 셋이 안 뭉개지는지 본다.
7
- *
8
- * ── 저장되는 것은 코드다 ────────────────────────────────────────────────────
9
- * `lastError` 가 사람 문장을 저장해 두고 화면이 그것을 그대로 뿌렸다. 번역도 집계도 안 되고,
10
- * 커넥터가 문장을 고치는 날 옛 행과 새 행이 다른 말을 한다. 그래서 사유는 코드로만 앉는다.
11
- */
12
- import { test } from 'node:test'
13
- import assert from 'node:assert/strict'
14
- import { readFileSync } from 'node:fs'
15
-
16
- import { actuationAddressed, actuationOutcomePatch, actuationResetPatch } from '../server/service/reference/actuation-verification.js'
17
-
18
- const AT = '2026-09-16T04:05:06.000Z'
19
-
20
- test('받아들여지면 verified 로 서고 그 시각이 남는다', () => {
21
- const patch = actuationOutcomePatch({ ok: true, ref: 'JO-1' }, AT)
22
-
23
- assert.equal(patch.actuationState, 'verified')
24
- assert.equal(patch.actuationVerifiedAt, AT)
25
- })
26
-
27
- test('★ 받아들여지면 지난 거절을 지운다 — 「됐는데 실패 사유가 있다」를 그리지 않게', () => {
28
- assert.equal(actuationOutcomePatch({ ok: true }, AT).actuationFailure, null)
29
- })
30
-
31
- test('★ 거절되면 사유가 코드로 앉는다 — 문장이 아니라', () => {
32
- const patch = actuationOutcomePatch(
33
- { ok: false, error: '저쪽이 503 을 답했습니다', errorCode: 'peer-unavailable', errorParams: { status: 503 } },
34
- AT
35
- )
36
-
37
- assert.equal(patch.actuationState, 'failed')
38
- assert.deepEqual(patch.actuationFailure, { code: 'peer-unavailable', at: AT, params: { status: 503 } })
39
-
40
- /* 사람 문장은 어디에도 안 실린다 — 그것이 이 칸을 만든 이유다. */
41
- assert.ok(!JSON.stringify(patch).includes('503 을 답했습니다'))
42
- })
43
-
44
- test('★ 코드가 없으면 사유를 비운다 — 자리를 채우려고 문장을 옮기지 않는다', () => {
45
- const patch = actuationOutcomePatch({ ok: false, error: '무언가 잘못됐습니다' }, AT)
46
-
47
- assert.equal(patch.actuationState, 'failed', '코드가 없어도 실패는 실패다')
48
- assert.equal(patch.actuationFailure, null, '모르는 것을 적었다')
49
- })
50
-
51
- test('★ 거절은 성공 시각을 지우지 않는다 — 「한 번이라도 닿은 적 있나」가 남아야 한다', () => {
52
- const patch = actuationOutcomePatch({ ok: false, errorCode: 'peer-unavailable' }, AT)
53
-
54
- assert.ok(!('actuationVerifiedAt' in patch), '실패가 지난 성공의 시각을 덮었다')
55
- })
56
-
57
- test('★ params 가 없으면 그 칸을 만들지 않는다 — 빈 객체와 「없다」는 다르다', () => {
58
- const patch = actuationOutcomePatch({ ok: false, errorCode: 'not-declared' }, AT)
59
-
60
- assert.deepEqual(patch.actuationFailure, { code: 'not-declared', at: AT })
61
- })
62
-
63
- /*
64
- * 위 시험들은 **판단만** 본다. 판단이 옳아도 아무도 안 부르면 레퍼런스에는 아무것도 안 남는다 —
65
- * 순수 시험은 부르는 사람을 못 본다.
66
- *
67
- * 값으로 재려면 DB 가 붙어야 해서, 여기서는 원문을 읽는다. 다만 **어느 함수 안에서 부르는지까지**
68
- * 본다. 파일 전체에서 이름을 세면 **선언이 자기를 센다** — 실제로 호출을 지우고 돌려 봤는데 이
69
- * 시험이 초록이었다. 세는 것은 주장이지 그 이웃이 아니다.
70
- */
71
- const strip = (x: string) => x.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/[^\n]*/g, '')
72
- const src = strip(readFileSync(new URL('../server/service/reference/actuation-routing.ts', import.meta.url), 'utf8'))
73
- const bodyOf = (name: string) => {
74
- const at = src.indexOf(`function ${name}(`)
75
- assert.ok(at > 0, `${name} 이 없다`)
76
- const next = src.slice(at + 1).search(/\nasync function |\nexport (async )?function /)
77
- return next < 0 ? src.slice(at) : src.slice(at, at + 1 + next)
78
- }
79
-
80
- test('★ routeActuation 이 실제로 그것을 부른다 — 판단만 맞고 아무도 안 부르면 남는 것이 없다', () => {
81
- const route = bodyOf('routeActuation')
82
-
83
- assert.match(route, /recordActuationOutcome\(/, '조치 경로에서 그 기록이 불리지 않는다')
84
- /* 기록이 본업을 막지 않는다 — 실패해도 조치 결과는 그대로 돌아간다. */
85
- assert.match(route, /\.catch\(/, '기록이 실패하면 조치까지 함께 넘어진다')
86
- assert.match(route, /return result/, '조치 결과를 돌려주지 않는다')
87
- })
88
-
89
- test('★ 기록하는 자리가 판단을 쓰고 그 값을 저장한다 — 자기 판단을 다시 짓지 않는다', () => {
90
- const record = bodyOf('recordActuationOutcome')
91
-
92
- assert.match(record, /actuationOutcomePatch\(/, '판단을 부르지 않는다 — 두 벌이 된다')
93
- assert.match(record, /\.update\(/, '부른 결과를 저장하지 않는다')
94
- })
95
-
96
- test('★ 주소를 바꾸는 저장은 검증을 되돌린다 — 지난 왕복은 지난 주소의 이야기다', () => {
97
- /*
98
- * 2026-09-18 실측(ADR-0046 ② 를 코드에 대어 본 결과): 칸 셋도 왕복의 결과를 적는 자리도 섰는데,
99
- * `verified` 인 연결의 주소를 바꿔도 그대로 `verified` 였다. 화면은 다른 공장을 가리키는 연결을
100
- * 「확인됨」으로 그린다.
101
- */
102
- const before = { intakeEndpoint: 'https://a.example/intake', intakeSiteId: 'line-a', intakeSecret: 's1' }
103
- const moved = actuationResetPatch(before, { ...before, intakeEndpoint: 'https://b.example/intake' })
104
- assert.deepEqual(moved, { actuationState: 'unverified', actuationVerifiedAt: null, actuationFailure: null })
105
- assert.ok(actuationResetPatch(before, { ...before, intakeSiteId: 'line-b' }), '받는 사이트가 바뀌었다')
106
- assert.ok(actuationResetPatch(before, { ...before, intakeSecret: 's2' }), '저쪽이 우리를 못 알아보면 그 왕복은 다시 성립하지 않는다')
107
- assert.ok(actuationResetPatch(undefined, before), '처음 적는 주소도 아직 왕복이 없다')
108
- })
109
-
110
- test('주소가 그대로면 검증도 그대로 — 이름만 고쳤다고 되돌리지 않는다', () => {
111
- const cfg = { intakeEndpoint: 'https://a.example/intake', intakeSiteId: 'line-a', intakeSecret: 's1' }
112
- assert.equal(actuationResetPatch(cfg, { ...cfg, label: '군산 1라인' }), null)
113
- /* 끝의 빗금은 같은 주소다 — 그것으로 되돌리면 저장할 때마다 초록이 사라진다. */
114
- assert.equal(actuationResetPatch(cfg, { ...cfg, intakeEndpoint: 'https://a.example/intake/' }), null)
115
- /* 가려진 비밀값은 저장 쪽이 병합해 옛 값 그대로 온다(그래서 여기까지 같은 값이 온다). */
116
- assert.equal(actuationResetPatch(cfg, { ...cfg }), null)
117
- })
118
-
119
- test('★ 보낼 주소가 적힌 연결에만 검증 상태를 말한다 — 읽기만 하는 연결에 할 일을 만들지 않는다', () => {
120
- assert.equal(actuationAddressed({ intakeEndpoint: 'https://a.example/intake', intakeSiteId: 'line-a' }), true)
121
- assert.equal(actuationAddressed({ intakeEndpoint: 'https://a.example/intake', siteId: 'line-a' }), true, 'siteId 가 그 자리를 대신한다')
122
- assert.equal(actuationAddressed({ intakeSiteId: 'line-a' }), false, '주소가 없으면 아무 데도 안 간다')
123
- assert.equal(actuationAddressed({ intakeEndpoint: 'https://a.example/intake' }), false, '받는 사이트를 모르면 못 보낸다')
124
- assert.equal(actuationAddressed(undefined), false)
125
- })
126
-
127
- test('★ 읽기 문이 그 상태를 싣는다 — 저장돼 있어도 나르지 않으면 화면이 볼 길이 없다', () => {
128
- /*
129
- * 2026-09-18 실측: 칸 셋은 2026-09 부터 서 있었고 왕복의 결과도 적히는데, 목록도 상세도 그 값을
130
- * 싣지 않았다. 저장된 사실이 아무에게도 닿지 않는 상태였다.
131
- */
132
- const src = readFileSync(new URL('../server/service/reference/reference-resolver.ts', import.meta.url).pathname, 'utf-8')
133
- for (const door of ['async twinReferences(', 'async twinReference(']) {
134
- const at = src.indexOf(door)
135
- assert.ok(at > 0, `${door} 를 못 찾았다 — 읽는 쪽이 깨졌다`)
136
- const body = src.slice(at, at + 3000)
137
- assert.ok(/actuationState/.test(body), `${door} 가 검증 상태를 싣지 않는다`)
138
- }
139
- })
@@ -1,133 +0,0 @@
1
- /*
2
- * ★ 돌고 있는 미러에 새 구조를 넣는다 — **미러는 멈출 수 없다.**
3
- *
4
- * 미러가 비추는 현실은 24시간 돈다. 설비 한 대가 늘었다고 트윈을 멈췄다 세우면 그 사이의
5
- * 사실을 잃고, 라이브에서 유실은 곧 거짓이다. 그래서 미러는 **돌면서** 갈아탄다.
6
- *
7
- * 갈아타기가 옳으려면 **세 층이 함께** 움직여야 한다. 하나라도 빠지면 알리지 않고 어긋난다:
8
- * ① 리비전 — 이후의 이벤트가 새 번호를 달고 다닌다(재생이 마디를 나눌 수 있게)
9
- * ② 저장 model·구조 행 — 조회가 새 구조를 본다
10
- * ③ 커널 — 지금 계산에 들어가는 이벤트가 새 구조 위에서 계산된다
11
- *
12
- * 커널 단위 거동(무엇을 지키고 무엇을 버리나)은 커널 쪽 `adopt-structure.test.ts` 가 지킨다.
13
- * 여기서 지키는 것은 **호스트 배선** — 세 층이 같은 인제스트에서 함께 움직이는가.
14
- *
15
- * 실 DataSource 로 돈다. 부분 적용은 정의상 "여러 표에 걸쳐 무엇이 남았나" 이므로.
16
- */
17
- import { test, before, after } from 'node:test'
18
- import assert from 'node:assert/strict'
19
- import { createRequire } from 'node:module'
20
- import type { DataSource } from 'typeorm'
21
-
22
- const req = createRequire(import.meta.url)
23
- const { NamingStrategy, addDataSource, entities: shellEntities, Domain } = req('@things-factory/shell')
24
- const { entities: authEntities } = req('@things-factory/auth-base')
25
- const { entities: twinEntities } = req('../dist-server/service/index.js')
26
- const { TwinEngine } = req('../dist-server/engine/index.js')
27
- const { TwinInstance } = req('../dist-server/service/twin-instance/twin-instance.js')
28
- const { TwinStructure } = req('../dist-server/service/twin-structure/twin-structure.js')
29
- const { TwinLocation } = req('../dist-server/service/twin-model/twin-location.js')
30
- const { TwinEquipment } = req('../dist-server/service/twin-model/twin-equipment.js')
31
- const { DataSource: TypeOrmDataSource } = req('typeorm')
32
-
33
- let ds: DataSource
34
- let domainId: string
35
-
36
- const MIRROR = 'mirror-probe'
37
- const SIM = 'sim-probe'
38
-
39
- const master = (source: string, bins: number, forklifts: number): any => ({
40
- source,
41
- system: 'wms',
42
- siteName: '미러 창고',
43
- space: { width: 60, depth: 30, unit: 'm' },
44
- locations: [
45
- { id: 'dock-recv', type: 'dock', role: 'location', name: '입고 도크', capacity: 100 },
46
- ...Array.from({ length: bins }, (_, i) => ({ id: `bin-${i + 1}`, type: 'storage', role: 'location', name: `빈${i + 1}`, capacity: 20 }))
47
- ],
48
- equipment: Array.from({ length: forklifts }, (_, i) => ({ id: `fk-${i + 1}`, kind: 'forklift', homeLocationId: 'dock-recv' }))
49
- })
50
-
51
- before(async () => {
52
- ds = new TypeOrmDataSource({
53
- type: 'sqlite',
54
- database: ':memory:',
55
- synchronize: true,
56
- dropSchema: true,
57
- namingStrategy: new NamingStrategy(),
58
- entities: [...shellEntities, ...authEntities, ...twinEntities],
59
- logging: false
60
- })
61
- await ds.initialize()
62
- addDataSource('default', ds)
63
- const d = await ds.getRepository(Domain).save({ name: 'adopt-test', subdomain: 'adopt-test' } as any)
64
- domainId = d.id
65
-
66
- await TwinEngine.ingestMaster(domainId, master(MIRROR, 3, 2), 'reset')
67
- await TwinEngine.ingestMaster(domainId, master(SIM, 3, 2), 'reset')
68
- })
69
-
70
- after(async () => {
71
- for (const id of [MIRROR, SIM]) await TwinEngine.stop(domainId, id).catch(() => {})
72
- await ds?.destroy()
73
- })
74
-
75
- test('돌고 있는 미러는 멈추지 않고 갈아탄다 — 세 층이 함께 움직인다', async () => {
76
- /* 미러 기동은 선언 기반 부팅이 가른다 — `startFromRegistry` 는 시뮬 경로다(같은 함수가 아니다). */
77
- const rt = await TwinEngine.bootDeclared(domainId, MIRROR, 'resync')
78
- assert.equal(rt.mode, 'live', '미러로 떠야 이 검사가 뜻이 있다')
79
-
80
- const res = await TwinEngine.ingestMaster(domainId, master(MIRROR, 7, 2), 'reset')
81
-
82
- /* ① 리비전 — 이후 이벤트가 달고 다닐 번호가 올라간다 */
83
- const revs = await ds.getRepository(TwinStructure).find({ where: { instanceId: MIRROR }, order: { rev: 'ASC' } })
84
- assert.deepEqual(revs.map((r: any) => r.rev), [1, 2], '구조가 달라졌으니 새 리비전이 남는다')
85
-
86
- /* ② 저장 model·구조 행 — 조회가 새 구조를 본다 */
87
- const inst = await ds.getRepository(TwinInstance).findOne({ where: { instanceId: MIRROR } })
88
- assert.equal(inst.model.locations.length, 8, '저장 model 가 새 구조다(도크 1 + 빈 7)')
89
- assert.equal(await ds.getRepository(TwinLocation).countBy({ instance: { id: inst.id } } as any), 8, '구조 행도 함께 다시 그려진다')
90
-
91
- /* ③ 커널 — 멈추지 않은 채로 새 구조를 들고 있다 */
92
- assert.equal(TwinEngine.instances[`${domainId}:${MIRROR}`]?.mode, 'live', '갈아타기가 미러를 멈추지 않는다')
93
- const snap = TwinEngine.snapshot(domainId, MIRROR)
94
- assert.equal(snap.locations.filter((n: any) => n.type === 'storage').length, 7, '커널도 새 자리를 들고 있다')
95
-
96
- /* 무엇이 달라졌는지 **말한다** — 멈췄다 세우는 마디가 없으므로 말하지 않으면 알리지 않고 지나간다 */
97
- const adopted = res.warnings.find((w: any) => w.code === 'structure-adopted')
98
- assert.ok(adopted, '갈아타기는 말없이 성공하지 않는다')
99
- assert.equal(adopted.params.locationsAdded, 4, '자리 4개가 늘었다(빈 3→7)')
100
- assert.equal(adopted.params.rev, 2)
101
- })
102
-
103
- test('사라진 설비를 수로 알린다 — 자리가 수천인 현장에서 직접 세어 보게 하지 않는다', async () => {
104
- const res = await TwinEngine.ingestMaster(domainId, master(MIRROR, 7, 1), 'reset') // 지게차 2 → 1
105
- const adopted = res.warnings.find((w: any) => w.code === 'structure-adopted')
106
- assert.equal(adopted.params.equipmentDropped, 1)
107
-
108
- const inst = await ds.getRepository(TwinInstance).findOne({ where: { instanceId: MIRROR } })
109
- assert.equal(await ds.getRepository(TwinEquipment).countBy({ instance: { id: inst.id } } as any), 1, '표에서도 사라진다')
110
- assert.equal(TwinEngine.snapshot(domainId, MIRROR).equipment.length, 1, '커널에서도 사라진다')
111
- })
112
-
113
- test('돌고 있는 시뮬레이션은 여전히 거절한다 — 조건이 바뀐 실험은 다른 실험이다', async () => {
114
- await TwinEngine.bootDeclared(domainId, SIM, 'reset')
115
- const before = (await ds.getRepository(TwinStructure).find({ where: { instanceId: SIM } })).length
116
-
117
- await assert.rejects(() => TwinEngine.ingestMaster(domainId, master(SIM, 9, 2), 'reset'), /is running/)
118
-
119
- assert.equal(
120
- (await ds.getRepository(TwinStructure).find({ where: { instanceId: SIM } })).length,
121
- before,
122
- '거절된 인제스트는 흔적을 남기지 않는다'
123
- )
124
- })
125
-
126
- test('멈춘 미러는 구조를 전환하지 않는다 — 정지한 대상을 전환하려 하지 않는다', async () => {
127
- await TwinEngine.stop(domainId, MIRROR)
128
- await assert.rejects(
129
- () => TwinEngine.adoptStructure(domainId, MIRROR, { locations: [], equipment: [] } as any),
130
- /is not running/,
131
- '멈춘 트윈은 프로비저닝으로 세우는 것이지 갈아타는 것이 아니다'
132
- )
133
- })