@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,192 +0,0 @@
1
- /*
2
- * ★ **재기동이 저널을 처음부터 다시 계산하지 않는다** — 미러가 저장된 재개점에서 이어 선다.
3
- *
4
- * ── 무엇이 오래 잘못돼 있었나 (2026-08-24 실측) ─────────────────────────────
5
- * 재개점을 **읽는** 쪽은 다 있었다: `recover` 는 `fold` 가 있으면 꼬리만 계산하고, 없으면 저널을 0부터
6
- * 계산한다. 그런데 **쓰는 쪽이 없었다** — `persistSnapshot` 은 `{revision, state, structureRev}` 만
7
- * 적었다. 실측으로 저장된 스냅샷 34건 전부 `fold` 가 비어 있었고, 저널은 2,960만 줄이었다.
8
- *
9
- * 그래서 두 가지가 함께 일어났다.
10
- *
11
- * ① 켤 때마다 처음부터 계산했다 — 규모 기준(엔티티 10만·품목 100만)에서 느린 것이 아니라 못 하는 것이다
12
- * ② 미러는 되찾은 상태를 **버렸다**(`startLive`). 「다음 계측이 정정한다」는 전제였는데, 원본이 커서
13
- * 증분으로 말하는 현장에서는 그 정정이 오지 않는다 — 미러가 영구히 빈 채로 남고 화면은 들어온 것이 없었다
14
- *
15
- * ── 왜 커널 시험만으로 충분하지 않나 ────────────────────────────────────────
16
- * 커널은 「재개점 + 꼬리 == 0부터 계산하기」를 증명한다(`observed-checkpoint.test.ts`). 그것이 참이어도
17
- * 호스트가 재개점을 **적지 않거나 되세우지 않으면** 아무 일도 일어나지 않는다 — 이 저장소가 실제로
18
- * 넉 달 동안 그 상태였다. 그래서 여기서 DB 를 물고 실제로 걷는다.
19
- *
20
- * ── 결정적인 단정 ───────────────────────────────────────────────────────────
21
- * 재기동 전에 **저널을 지운다.** 그래도 상태가 돌아오면 그것은 저널을 계산해 온 것이 **아니다** —
22
- * 저장된 재개점에서 온 것이다. 그리고 그 상황은 가정이 아니라 설계된 거동이다: 보존 정책이 체크포인트
23
- * 리비전 이하의 행을 지운다(「그 앞은 스냅샷이 대신한다」).
24
- */
25
- import { test, before, after } from 'node:test'
26
- import assert from 'node:assert/strict'
27
- import { createRequire } from 'node:module'
28
- import type { DataSource } from 'typeorm'
29
-
30
- const req = createRequire(import.meta.url)
31
- const { NamingStrategy, addDataSource, entities: shellEntities, Domain } = req('@things-factory/shell')
32
- const { entities: authEntities } = req('@things-factory/auth-base')
33
- const { entities: twinEntities } = req('../dist-server/service/index.js')
34
- /* 체크포인트는 `cache-service` 표에 앉는다 — 그 엔티티를 빼면 저장이 알리지 않고 실패한다(스냅샷도 씨앗도). */
35
- const { entities: cacheEntities } = req('@things-factory/cache-service/dist-server/service/index.js')
36
- const { TwinEngine } = req('../dist-server/engine/index.js')
37
- const { TwinEvent } = req('../dist-server/service/twin-event/twin-event.js')
38
- const { DataSource: TypeOrmDataSource } = req('typeorm')
39
-
40
- let ds: DataSource
41
- let domainId: string
42
-
43
- const INSTANCE = 'resume-probe'
44
-
45
- /** 미러 하나 — 원본이 사실을 말해 주는 트윈이므로 시나리오도 레시피도 필요 없다. */
46
- const master = (): any => ({
47
- source: INSTANCE,
48
- system: 'wms',
49
- siteName: '재개점 창고',
50
- origin: { kind: 'reference' }, // 현실 출처 선언 — 이것이 미러로 뜨는 근거다
51
- space: { width: 40, depth: 20, unit: 'm' },
52
- locations: [
53
- { id: 'dock', type: 'dock', role: 'location', capacity: 100 },
54
- { id: 'bin-1', type: 'storage', role: 'location', capacity: 100 }
55
- ],
56
- equipment: [{ id: 'fk-1', kind: 'forklift', homeLocationId: 'dock' }]
57
- })
58
-
59
- /** 원본이 말한 사실 — 오더와 작업. 미러는 이것을 계산해 상태를 만든다. */
60
- function facts(n: number): any[] {
61
- const out: any[] = []
62
- for (let i = 1; i <= n; i++) {
63
- out.push({
64
- eventId: `o-${i}`,
65
- eventType: 'order.status',
66
- eventTime: '2026-08-24T01:00:00.000Z',
67
- tenantId: domainId,
68
- data: { orderId: `WO-${i}`, kind: 'workorder', status: 'in-progress', requested: 10, fulfilled: 3 }
69
- })
70
- out.push({
71
- eventId: `t-${i}`,
72
- eventType: 'task.status',
73
- eventTime: '2026-08-24T01:00:01.000Z',
74
- tenantId: domainId,
75
- data: {
76
- taskId: `TK-${i}`,
77
- kind: 'putaway',
78
- status: 'in-progress',
79
- orderId: `WO-${i}`,
80
- fromNode: 'dock',
81
- toNode: 'bin-1',
82
- intent: 'transport',
83
- durationMs: 60000,
84
- remainingMs: 30000
85
- }
86
- })
87
- }
88
- return out
89
- }
90
-
91
- const observed = (s: any): number => (s?.items?.length ?? 0) + (s?.orders?.length ?? 0) + (s?.tasks?.length ?? 0)
92
-
93
- before(async () => {
94
- ds = new TypeOrmDataSource({
95
- type: 'sqlite',
96
- database: ':memory:',
97
- synchronize: true,
98
- dropSchema: true,
99
- namingStrategy: new NamingStrategy(),
100
- entities: [...shellEntities, ...authEntities, ...twinEntities, ...cacheEntities],
101
- logging: false
102
- })
103
- await ds.initialize()
104
- addDataSource('default', ds)
105
- const d = await ds.getRepository(Domain).save({ name: 'resume-test', subdomain: 'resume-test' } as any)
106
- domainId = d.id
107
- await TwinEngine.ingestMaster(domainId, master(), 'reset')
108
- })
109
-
110
- after(async () => {
111
- await TwinEngine.stop(domainId, INSTANCE).catch(() => {})
112
- await ds?.destroy()
113
- })
114
-
115
- test('체크포인트가 **이어 계산할 씨앗을 함께 적는다** — 이 줄이 없어서 넉 달 동안 처음부터 계산했다', async () => {
116
- const rt = await TwinEngine.bootDeclared(domainId, INSTANCE, 'resync')
117
- assert.equal(rt.mode, 'live', '미러로 떠야 이 검사가 뜻이 있다')
118
-
119
- const applied = TwinEngine.ingestLive(domainId, INSTANCE, facts(5))
120
- assert.equal(applied, 10, '원본이 말한 사실이 커널에 들어갔다')
121
- const before = TwinEngine.snapshot(domainId, INSTANCE)
122
- assert.ok(observed(before) > 0, `상태에 사실이 있어야 이 검사가 뜻이 있다 (실제 ${observed(before)})`)
123
-
124
- await TwinEngine.persistSnapshot(domainId, INSTANCE)
125
- const stored = await TwinEngine.loadSnapshot(domainId, INSTANCE)
126
- assert.ok(stored, '스냅샷이 저장됐다')
127
- assert.ok(stored.fold?.reducer, '★ 재개점이 함께 적혀야 한다 — 없으면 다음 기동이 저널을 0부터 계산한다')
128
- assert.ok(stored.fold?.oee, '가동 누적기도 함께 — 상태만 되돌리면 가동률이 부팅 이후로만 잡힌다')
129
- /* 씨앗이 실제로 사실을 들었는지 — 빈 껍데기를 적어 두고 초록이 되지 않게. */
130
- assert.ok((stored.fold.reducer as any).orders?.length, '씨앗에 오더가 담겨 있다')
131
- assert.ok((stored.fold.reducer as any).tasks?.length, '씨앗에 작업이 담겨 있다')
132
- })
133
-
134
- test('★ 저널을 지워도 미러가 상태를 들고 다시 선다 — 그러므로 저널을 계산한 것이 아니다', async () => {
135
- /*
136
- * 이 단정이 이 축의 전부다. 저널이 없는데 상태가 돌아오면 그 상태는 **저장된 재개점**에서 온 것이다.
137
- * 그리고 이 상황은 가정이 아니다 — 보존 정책이 체크포인트 리비전 이하의 행을 실제로 지운다.
138
- */
139
- const before = observed(TwinEngine.snapshot(domainId, INSTANCE))
140
- assert.ok(before > 0, '멈추기 전에 상태가 있어야 이 검사가 뜻이 있다')
141
-
142
- await TwinEngine.stop(domainId, INSTANCE)
143
- /* 이 인스턴스의 저널만 — 정확한 소유 표식으로 지운다. */
144
- await ds.getRepository(TwinEvent).delete({ domain: { id: domainId } as any, instanceId: INSTANCE } as any)
145
- assert.equal(
146
- await ds.getRepository(TwinEvent).countBy({ domain: { id: domainId } as any, instanceId: INSTANCE } as any),
147
- 0,
148
- '저널이 비었다 — 이제 계산할 것이 없다'
149
- )
150
-
151
- await TwinEngine.bootDeclared(domainId, INSTANCE, 'resync')
152
- const after = TwinEngine.snapshot(domainId, INSTANCE)
153
- assert.equal(observed(after), before, '★ 사실이 그대로 돌아왔다 — 저널 없이')
154
- assert.equal(after.orders.length, 5, '오더 다섯이 그대로다')
155
- assert.equal(after.tasks.length, 5, '작업 다섯이 그대로다')
156
- })
157
-
158
- test('되세운 뒤 들어온 사실이 앞의 것을 덮지 않는다 — 더해진다', async () => {
159
- /*
160
- * 미러는 첫 봉투가 올 때 리듀서를 만든다. 되돌리기가 그보다 먼저 서지 않으면 첫 봉투가 **빈 리듀서**를
161
- * 만들고 되세운 것을 덮는다 — 오류 없이 상태가 사라진다.
162
- */
163
- const before = observed(TwinEngine.snapshot(domainId, INSTANCE))
164
- TwinEngine.ingestLive(domainId, INSTANCE, [
165
- {
166
- eventId: 'o-new',
167
- eventType: 'order.status',
168
- eventTime: '2026-08-24T02:00:00.000Z',
169
- tenantId: domainId,
170
- data: { orderId: 'WO-NEW', kind: 'workorder', status: 'in-progress', requested: 1, fulfilled: 0 }
171
- } as any
172
- ])
173
- const after = TwinEngine.snapshot(domainId, INSTANCE)
174
- assert.equal(observed(after), before + 1, '앞의 것이 남고 새 것이 더해진다')
175
- assert.ok(after.orders.some((o: any) => o.id === 'WO-1'), '되세운 오더가 남아 있다')
176
- assert.ok(after.orders.some((o: any) => o.id === 'WO-NEW'), '새 오더도 있다')
177
- })
178
-
179
- test('씨앗이 없으면 지어내지 않는다 — 전과 같이 빈 채로 시작한다', async () => {
180
- /*
181
- * 처음 뜨는 트윈에는 씨앗이 없다. 여기서 무엇이든 심으면 없던 재고가 생긴다 — 그것은 이 작업이
182
- * 고치려던 것보다 나쁘다.
183
- */
184
- const FRESH = 'resume-probe-fresh'
185
- await TwinEngine.ingestMaster(domainId, { ...master(), source: FRESH }, 'reset')
186
- try {
187
- await TwinEngine.bootDeclared(domainId, FRESH, 'resync')
188
- assert.equal(observed(TwinEngine.snapshot(domainId, FRESH)), 0, '아무것도 듣지 못했으므로 비어 있다')
189
- } finally {
190
- await TwinEngine.stop(domainId, FRESH).catch(() => {})
191
- }
192
- })
@@ -1,141 +0,0 @@
1
- /*
2
- * 모델 근거 비교 — **배운 모델에만 보정을 적용하기 위한 관문.**
3
- *
4
- * 배경: 예측 출력 보정(P3.2)은 "그때 모델이 이만큼 치우쳐 있다" 를 배운다. 소요시간 추정기(실측·거리)
5
- * 와 공정 명세가 들어오면서 모델 자체가 바뀔 수 있게 됐고, 그러면 옛 편향을 그대로 밀어 주는 **이중
6
- * 보정**이 생긴다. 근거가 달라졌으면 적용하지 않는다(그리고 그 사실을 응답에 싣는다).
7
- *
8
- * 비교를 **상대 허용오차**로 하는 이유: 양자화 지문은 버킷 경계에 걸린 값이 1초 드리프트로도 달라져
9
- * "작은 드리프트로 학습을 무효화하지 않는다" 는 목적을 경계에서 못 지킨다. 비율은 어디서든 같다.
10
- */
11
- import { test } from 'node:test'
12
- import assert from 'node:assert/strict'
13
-
14
- import { BASIS_TOLERANCE, describeModelBasis, modelBasisChanged, toleranceOf } from '../server/engine/model-basis.ts'
15
-
16
- test('같은 근거면 바뀌지 않았다 — 키 순서에 흔들리지 않는다', () => {
17
- assert.equal(
18
- modelBasisChanged({ measured: { pick: 22_000, putaway: 47_000 } }, { measured: { putaway: 47_000, pick: 22_000 } }),
19
- false
20
- )
21
- })
22
-
23
- test('작은 드리프트는 같은 모델 — 경계에서도 성립한다(버킷이 아니라 비율)', () => {
24
- /* 47.0 → 47.9 (약 1.9%): 5초 버킷이면 45↔50 으로 갈렸을 값이다. */
25
- assert.equal(modelBasisChanged({ measured: { putaway: 47_000 } }, { measured: { putaway: 47_900 } }), false)
26
- /* 허용오차 경계 바로 아래·위 */
27
- assert.equal(modelBasisChanged({ measured: { p: 100_000 } }, { measured: { p: 105_000 } }), false, '5%')
28
- assert.equal(modelBasisChanged({ measured: { p: 100_000 } }, { measured: { p: 130_000 } }), true, '30%')
29
- })
30
-
31
- test('실측이 실제로 달라지면 다른 모델 — 30초 작업이 47초가 되면 옛 보정은 무효', () => {
32
- assert.equal(modelBasisChanged({ measured: { putaway: 30_000 } }, { measured: { putaway: 47_000 } }), true)
33
- })
34
-
35
- test('새로 배운 종류·사라진 종류는 다른 모델 — 값이 없다가 생긴 것도 변화다', () => {
36
- assert.equal(modelBasisChanged({ measured: { pick: 20_000 } }, { measured: { pick: 20_000, putaway: 47_000 } }), true)
37
- assert.equal(modelBasisChanged({ measured: { pick: 20_000, putaway: 47_000 } }, { measured: { pick: 20_000 } }), true)
38
- })
39
-
40
- test('속도가 바뀌면 다른 모델 — 이동시간 모델이 바뀐 것이다', () => {
41
- assert.equal(modelBasisChanged({ speeds: { forklift: 2 } }, { speeds: { forklift: 4 } }), true)
42
- assert.equal(modelBasisChanged({ speeds: { forklift: 2 } }, { speeds: { forklift: 2.05 } }), false)
43
- })
44
-
45
- test('선언 명세가 바뀌면 다른 모델 — 표기 원문을 그대로 비교한다', () => {
46
- assert.equal(
47
- modelBasisChanged({ declared: [{ key: 'cut', duration: 'PT25M' }] }, { declared: [{ key: 'cut', duration: 'PT30M' }] }),
48
- true
49
- )
50
- assert.equal(
51
- modelBasisChanged({ declared: [{ key: 'cut', duration: 'PT25M' }] }, { declared: [{ key: 'cut', duration: 'PT25M' }] }),
52
- false
53
- )
54
- })
55
-
56
- test('소요 없는 선언은 모델을 바꾸지 않는다', () => {
57
- assert.equal(modelBasisChanged({ declared: [{ key: 'cut' }] }, { declared: [] }), false)
58
- })
59
-
60
- test('뜻 없는 값은 근거가 아니다 — 0·음수·NaN 은 무시한다', () => {
61
- assert.equal(modelBasisChanged({ measured: { pick: 0 } }, {}), false)
62
- assert.equal(modelBasisChanged({ measured: { pick: NaN } }, { speeds: { f: -1 } }), false)
63
- })
64
-
65
- test('한쪽 근거를 모르면 판정하지 않는다 — 모르는 것을 근거로 학습을 끊지 않는다', () => {
66
- assert.equal(modelBasisChanged(undefined, { measured: { pick: 20_000 } }), false)
67
- assert.equal(modelBasisChanged({ measured: { pick: 20_000 } }, undefined), false)
68
- })
69
-
70
- test('세 재료가 섞이지 않는다 — 같은 이름이 다른 재료에 있으면 다른 모델', () => {
71
- assert.equal(modelBasisChanged({ measured: { x: 10_000 } }, { speeds: { x: 10_000 } }), true)
72
- })
73
-
74
- test('허용오차는 조절 가능하고 기본값이 명시돼 있다', () => {
75
- assert.equal(BASIS_TOLERANCE, 0.1)
76
- assert.equal(modelBasisChanged({ measured: { p: 100 } }, { measured: { p: 130 } }, 0.5), false, '느슨하게 주면 같은 모델')
77
- })
78
-
79
- test('사람이 읽는 요약을 낸다 — 로그에서 왜 달라졌는지 눈으로 본다', () => {
80
- const d = describeModelBasis({ measured: { putaway: 47_000 }, speeds: { forklift: 2 }, declared: [{ key: 'cut', duration: 'PT25M' }] })
81
- assert.match(d, /measured\(putaway=47s\)/)
82
- assert.match(d, /speed\(forklift=2m\/s\)/)
83
- assert.match(d, /declared\(cut=PT25M\)/)
84
- assert.equal(describeModelBasis({}), 'kernel defaults only')
85
- assert.equal(describeModelBasis(undefined), 'unknown')
86
- })
87
-
88
- /*
89
- * ★ 허용오차는 **그 공정이 선언한 변동폭에서 나온다.**
90
- *
91
- * 단일 10% 잣대는 두 방향으로 틀렸다. 우리 트레일러 템플릿의 용접은 변동폭을 `PT55M~PT1H35M`
92
- * (선언 소요 `PT1H10M` 기준 −21%~+36%)로 스스로 선언한다 — 10% 관문은 그 공정의 **정상 변동조차**
93
- * "다른 모델" 로 판정해 보정을 끊는다. 반대로 1% 변동도 치명적인 공정에는 10% 가 너무 느슨하다.
94
- *
95
- * 도메인 설정을 새로 만들지 않는다: 얼마나 흔들리는 것이 정상인지는 **현장이 이미 선언했다.**
96
- */
97
- const weld = (durationMs: number) => ({
98
- measured: { weld: durationMs },
99
- declared: [{ key: 'weld', duration: 'PT1H10M', variability: { distribution: 'triangular', min: 'PT55M', max: 'PT1H35M', mode: 'PT1H5M' } }]
100
- })
101
-
102
- test('선언된 변동폭 안의 흔들림은 같은 모델이다 — 10% 잣대는 정상 변동을 끊었다', () => {
103
- const base = 70 * 60_000 // PT1H10M
104
- /* 반폭 = (95분 − 55분)/2 / 70분 ≈ 28.6%. 20% 흔들림은 그 안이다 — 예전 잣대(10%)로는 끊겼다. */
105
- assert.equal(modelBasisChanged(weld(base), weld(base * 1.2)), false, '정상 변동으로 학습이 무효화되면 안 된다')
106
- /* 변동폭이 실제로 허용오차로 읽히는지 — 반폭 ≈ 28.6%. 이 값이 안 나오면 위 단언이 우연히 통과한다. */
107
- const tol = toleranceOf(weld(base).declared).weld
108
- assert.ok(tol > 0.28 && tol < 0.29, `선언에서 읽은 허용오차가 ${tol} 다`)
109
- })
110
-
111
- test('선언된 변동폭을 넘으면 다른 모델이다 — 넓혔다고 아무 변화나 삼키지 않는다', () => {
112
- const base = 70 * 60_000
113
- assert.equal(modelBasisChanged(weld(base), weld(base * 1.6)), true, '60% 변화는 정상 변동이 아니다')
114
- })
115
-
116
- test('정밀 공정은 더 좁게 판정한다 — 1% 변동이 치명적인 현장이 있다', () => {
117
- const precise = (ms: number) => ({
118
- measured: { grind: ms },
119
- declared: [{ key: 'grind', duration: 'PT10M', variability: { distribution: 'uniform', min: 'PT9M54S', max: 'PT10M6S' } }]
120
- })
121
- const base = 10 * 60_000
122
- /* 반폭 = 6초/10분 = 1%. 5% 흔들림은 이 공정에서 다른 모델이다 — 단일 10% 잣대는 삼켰다. */
123
- assert.equal(modelBasisChanged(precise(base), precise(base * 1.05)), true, '느슨한 잣대가 정밀 공정의 변화를 삼켰다')
124
- assert.equal(modelBasisChanged(precise(base), precise(base * 1.005)), false, '선언한 변동폭 안은 같은 모델이다')
125
- })
126
-
127
- test('선언이 침묵하면 기본값으로 떨어진다 — 없는 것을 지어내지 않는다', () => {
128
- const quiet = (ms: number) => ({ measured: { pack: ms }, declared: [{ key: 'pack', duration: 'PT5M' }] })
129
- const base = 5 * 60_000
130
- assert.equal(modelBasisChanged(quiet(base), quiet(base * 1.05)), false, '기본 10% 안')
131
- assert.equal(modelBasisChanged(quiet(base), quiet(base * 1.3)), true, '기본 10% 밖')
132
- })
133
-
134
- test('변동폭이 바뀌면 다른 모델이다 — 판정의 잣대가 알리지 않고 바뀌지 않게', () => {
135
- const a = weld(70 * 60_000)
136
- const b = {
137
- measured: { weld: 70 * 60_000 },
138
- declared: [{ key: 'weld', duration: 'PT1H10M', variability: { distribution: 'triangular', min: 'PT30M', max: 'PT3H', mode: 'PT1H5M' } }]
139
- }
140
- assert.equal(modelBasisChanged(a, b), true, '변동폭 선언이 바뀌었는데 같은 모델이라고 하면 잣대가 오류 없이 바뀐다')
141
- })
@@ -1,153 +0,0 @@
1
- /*
2
- * ★ 「원본이 말한 적 없는 것」을 세는 규율.
3
- *
4
- * ── 왜 이것이 필요한가 (2026-08-20 실측) ────────────────────────────────────
5
- * 동기화 건강 기능을 만들 때 제가 전제를 이렇게 적었다: *「커넥터의 매핑이 한 글자 틀리면 트윈은
6
- * 빈 공장이 된다」*. 사용자가 그 전제를 검증하게 해서 재 봤더니, 유입 문은 참조 오류를 **거부하지
7
- * 않았다**:
8
- *
9
- * 모르는 로케이션 「오타-99」 → 통과
10
- * 모르는 bizStep 「PUTAWAY_X17」 → 통과
11
- * 모르는 계량기 「MMXU-오타-99」 → 통과
12
- *
13
- * 즉 그 기능이 잡겠다고 내세운 대표 사례가 `mapping-blocked` 로는 **뜰 수 없었다.** 거부되는 것은
14
- * 형태 오류뿐이다(시각 형식·숫자 아닌 값·epc 없음).
15
- *
16
- * 거부하지 않는 것이 옳다 — 원천이 모델보다 먼저 새 로케이션을 말하는 것은 정상이고, 거부하면 그 선행
17
- * 계측을 잃는다. 커널은 흡수하고 **표시한다**(`origin: 'observed'`). 빠져 있던 것은 그 표시를
18
- * 「맞춰지고 있나」를 보는 사람에게 잇는 일이었다.
19
- *
20
- * ── 지키는 것 ───────────────────────────────────────────────────────────────
21
- * ① 마스터가 말한 것과 관측으로 알게 된 것을 섞지 않는다
22
- * ② 트윈이 안 돌면 `null` — 「없다」와 「세어 보지 못했다」는 다르다
23
- * ③ 알리지 않고 자르지 않는다 — 상한에서 밀려난 수를 함께 낸다
24
- * ④ 덮지 못하는 축을 밝힌다 — 계량기는 커널이 표시를 달지 않아 이 화면이 못 찾아 준다
25
- */
26
- import { test } from 'node:test'
27
- import assert from 'node:assert/strict'
28
-
29
- import { GAP_ID_LIMIT, modelGapOf } from '../server/engine/model-gap.ts'
30
-
31
- const loc = (id: string, origin: string) => ({ id, origin })
32
-
33
- test('마스터가 말한 로케이션은 갭이 아니다 — 선언된 것을 문제로 세지 않는다', () => {
34
- const g = modelGapOf({
35
- locations: [loc('dock-recv', 'master'), loc('bin-1', 'master')],
36
- equipment: [loc('fk-1', 'master')]
37
- })
38
-
39
- assert.equal(g!.total, 0)
40
- assert.deepEqual(g!.locations.ids, [])
41
- })
42
-
43
- test('관측으로만 알게 된 것을 축마다 센다 — 원천이 우리가 모르는 id 를 보내고 있다', () => {
44
- const g = modelGapOf({
45
- locations: [loc('dock-recv', 'master'), loc('오타-99', 'observed'), loc('A-77', 'observed')],
46
- equipment: [loc('fk-1', 'master'), loc('없는-지게차', 'observed')],
47
- persons: [loc('unknown-op', 'observed')]
48
- })
49
-
50
- assert.equal(g!.locations.count, 2)
51
- assert.equal(g!.locations.unknown, 0, '표시가 다 있으면 모름은 0')
52
- assert.deepEqual(g!.locations.ids, ['오타-99', 'A-77'], 'id 를 보여 준다 — 오타는 눈으로 찾는다')
53
- assert.equal(g!.equipment.count, 1)
54
- assert.equal(g!.persons.count, 1)
55
- assert.equal(g!.total, 4, '세 축의 합')
56
- })
57
-
58
- test('트윈이 안 돌면 「없음」이다 — 0 이 아니다', () => {
59
- /* 비교할 상대가 없다. 0 으로 답하면 「원천이 우리가 아는 것만 보낸다」는 없는 사실이 생긴다. */
60
- assert.equal(modelGapOf(null), null)
61
- assert.equal(modelGapOf(undefined), null)
62
- })
63
-
64
- test('돌지만 관측 갭이 없으면 0 이다 — 이건 「없음」과 다르다', () => {
65
- const g = modelGapOf({ locations: [] })
66
-
67
- assert.notEqual(g, null, '세어 봤다')
68
- assert.equal(g!.total, 0, '세어 보니 없었다')
69
- })
70
-
71
- test('id 를 알리지 않고 자르지 않는다 — 밀려난 수를 함께 낸다', () => {
72
- const many = Array.from({ length: GAP_ID_LIMIT + 7 }, (_, i) => loc(`ghost-${i}`, 'observed'))
73
- const g = modelGapOf({ locations: many })
74
-
75
- assert.equal(g!.locations.count, GAP_ID_LIMIT + 7, '전부 센다')
76
- assert.equal(g!.locations.ids.length, GAP_ID_LIMIT, '보이는 것은 상한까지')
77
- assert.equal(g!.locations.more, 7, '밀려난 수를 말한다')
78
- })
79
-
80
- test('커널이 담을 줄 모른 사건을 함께 낸다 — 참조 문제와 다른 사실이다', () => {
81
- const at = Date.parse('2026-08-20T01:02:03.000Z')
82
- const g = modelGapOf({
83
- unhandled: [
84
- { eventType: 'epcis.TransformationEvent', count: 12, lastAtMs: at },
85
- { eventType: 'aggregation-mixed-classes', count: 3 }
86
- ]
87
- })
88
-
89
- assert.equal(g!.unhandled.length, 2)
90
- assert.equal(g!.unhandled[0].lastAt, '2026-08-20T01:02:03.000Z', '언제까지 났는지 — 멈춘 종류는 고쳐진 것이다')
91
- assert.equal(g!.unhandled[1].lastAt, null, '시각이 없으면 지어내지 않는다')
92
- })
93
-
94
- test('모르는 설비의 에너지 보고는 「없음」과 0 을 가른다 — 경로가 `energy` 안이다', () => {
95
- /*
96
- * 이 값을 **루트에서 읽고 있었다**(2026-08-20에 잡음). 커널은 `EnergyState` 안에 담으므로 루트에서
97
- * 읽으면 영원히 `null` 이고, 오류 없이 「에너지 트윈이 아니다」로 읽힌다. 나만 읽는 필드를 잘못된
98
- * 경로에서 읽으면 이렇게 오류 없이 사라진다.
99
- *
100
- * 그리고 커널은 0 이면 그 칸을 만들지 않는다. 그래서 `energy` 자체가 있는지로 「세었고 0」과
101
- * 「에너지 트윈이 아님」을 가른다.
102
- */
103
- assert.equal(modelGapOf({})!.unknownEquipmentReports, null, '에너지 트윈이 아니면 이 수가 없다')
104
- assert.equal(modelGapOf({ energy: { points: [] } })!.unknownEquipmentReports, 0, '에너지 트윈이면 세었고 0 이다')
105
- assert.equal(modelGapOf({ energy: { unknownEquipment: 41 } })!.unknownEquipmentReports, 41)
106
- assert.equal(
107
- modelGapOf({ unknownEquipment: 41 } as any)!.unknownEquipmentReports,
108
- null,
109
- '루트에 있는 값을 집지 않는다 — 그 경로는 커널의 것이 아니다'
110
- )
111
- })
112
-
113
- test('계량기도 덮는다 — 이 축이 가장 무겁다', () => {
114
- /*
115
- * 모르는 `meterId` 는 알리지 않고 새 계량기가 되고 그 kW 가 그 현장의 수요·피크·요금 판정에 더해진다.
116
- * 로케이션 오타는 스키매틱이 비는 것으로 드러나지만, 이건 **그럴듯한 숫자**로 나온다.
117
- * 커널 0.7.39 가 `MeterPointState.origin` 을 내면서 덮을 수 있게 됐다.
118
- */
119
- const g = modelGapOf({
120
- energy: { points: [loc('main-incoming', 'master'), loc('MMXU-오타-99', 'observed')] }
121
- })
122
-
123
- assert.equal(g!.meters.count, 1)
124
- assert.deepEqual(g!.meters.ids, ['MMXU-오타-99'])
125
- assert.equal(g!.total, 1, '계량기도 합에 든다')
126
- assert.deepEqual(g!.notCovered, [], '덮지 못하는 축이 없다')
127
- })
128
-
129
- test('표시가 없는 항목은 「선언됨」이 아니라 「모름」으로 센다', () => {
130
- /*
131
- * 계량기의 `origin` 은 늦게 생긴 칸이라, 옛 스냅샷에서 이어받은 지점에는 없다(`undefined`).
132
- * 마스터로 세면 오타를 놓치고, 관측으로 세면 정상을 문제로 만든다. 둘 다 틀리다.
133
- */
134
- const g = modelGapOf({
135
- energy: { points: [{ id: 'carried-over' }, loc('main', 'master'), loc('ghost', 'observed')] }
136
- })
137
-
138
- assert.equal(g!.meters.unknown, 1, '표시 없는 것은 모름')
139
- assert.equal(g!.meters.count, 1, '관측 갭에 섞이지 않는다')
140
- assert.ok(!g!.meters.ids.includes('carried-over'), '모르는 것을 오타로 지목하지 않는다')
141
- })
142
-
143
- test('`origin` 은 「지금 모델에 있는가」의 답이다 — 채택되면 갭에서 빠진다', () => {
144
- /*
145
- * 커널이 표본마다 다시 맞춘다. 한 번 찍고 두면 나중에 선언된 계량기가 영원히 `observed` 로 남는다.
146
- * 그래서 채택 뒤 스냅샷에서는 같은 id 가 `master` 로 오고, 이 도출은 그것을 그대로 따른다.
147
- */
148
- const before = modelGapOf({ energy: { points: [loc('new-meter', 'observed')] } })
149
- const after = modelGapOf({ energy: { points: [loc('new-meter', 'master')] } })
150
-
151
- assert.equal(before!.meters.count, 1)
152
- assert.equal(after!.meters.count, 0, '모델에 들어오면 갭이 아니다')
153
- })
@@ -1,75 +0,0 @@
1
- /*
2
- * ★ A twin model the kernel refuses reaches the reader as a named refusal, not INTERNAL_SERVER_ERROR.
3
- *
4
- * 2026-10-10: `twinReplay(miratek)` failed with the MES kernel's English sentence "MES twin requires a
5
- * production declaration" in the shell's global notice. The kernel now names it
6
- * (`twin-model-no-production-spec`, with `params`); the engine turns a named kernel error into a shell
7
- * `Refusal` wherever it loads or replays a model, and the resolvers that reach those places speak it.
8
- */
9
- import { test } from 'node:test'
10
- import assert from 'node:assert/strict'
11
- import { readFileSync } from 'node:fs'
12
- import { Refusal, speakRefusal } from '@things-factory/shell'
13
- import { asModelRefusal, refusingModel } from '../server/engine/model-refusal.ts'
14
-
15
- /* The shape the kernel throws (`MesKernel.loadTwinModel`, twin-kernel 02f117f). */
16
- function kernelRefusal(): Error {
17
- return Object.assign(new Error('MES twin requires a production declaration (ProductionSpec): …'), {
18
- code: 'twin-model-no-production-spec',
19
- params: {}
20
- })
21
- }
22
-
23
- test('a named kernel error becomes a Refusal that says which twin', () => {
24
- const r = asModelRefusal(kernelRefusal(), 'miratek')
25
- assert.ok(r instanceof Refusal)
26
- assert.equal((r as Refusal).code, 'twin-model-no-production-spec')
27
- assert.deepEqual((r as Refusal).params, { instanceId: 'miratek' })
28
- assert.match((r as Refusal).message, /requires a production declaration/, 'the English sentence stays as the fallback')
29
- })
30
-
31
- test('an error without a name passes through untouched', () => {
32
- const plain = new Error('boom')
33
- assert.equal(asModelRefusal(plain, 'x'), plain)
34
- const codeOnly = Object.assign(new Error('x'), { code: 'ENOENT' })
35
- assert.equal(asModelRefusal(codeOnly, 'x'), codeOnly, 'a code without params is a system error, not a refusal')
36
- assert.throws(() => refusingModel('x', () => { throw plain }), e => e === plain)
37
- })
38
-
39
- test('spoken, it is a refusal in the reader language under error.<code>', () => {
40
- let askedKey = ''
41
- const t = (key: string, opts?: any) => ((askedKey = key), `${opts.instanceId}: no production declaration`)
42
- const spoken = speakRefusal(asModelRefusal(kernelRefusal(), 'miratek') as Refusal, { t })
43
- assert.equal(askedKey, 'error.twin-model-no-production-spec')
44
- assert.equal(spoken.message, 'miratek: no production declaration')
45
- assert.equal(spoken.extensions.code, 'BAD_USER_INPUT', 'not INTERNAL_SERVER_ERROR')
46
- assert.deepEqual(spoken.extensions.refusal, { code: 'twin-model-no-production-spec', params: { instanceId: 'miratek' } })
47
- })
48
-
49
- const ENGINE = readFileSync(new URL('../server/engine/twin-engine.ts', import.meta.url), 'utf8')
50
-
51
- test('every place the engine loads or replays a model goes through refusingModel', () => {
52
- const code = ENGINE.split('\n').filter(l => !/^\s*(\*|\/\/|\/\*)/.test(l))
53
- const roads = code.filter(l => /\.loadTwinModel\(|\breplay(From|WithCheckpoint|Segments)?\(/.test(l))
54
- assert.ok(roads.length >= 3, 'the engine still loads models somewhere')
55
- for (const l of roads) {
56
- /* a replay call that wraps onto the next line is inside a refusingModel opened on the line above */
57
- const i = code.indexOf(l)
58
- assert.ok(/refusingModel\(/.test(l) || /refusingModel\([^)]*\(\)\s*=>\s*$/.test(code[i - 1]), `not wrapped: ${l.trim()}`)
59
- }
60
- })
61
-
62
- test('the resolvers that reach those places speak refusals', () => {
63
- for (const f of [
64
- 'twin-journal/twin-journal-query.ts',
65
- 'twin-model/twin-model-query.ts',
66
- 'twin-model/twin-model-item-query.ts',
67
- 'twin-lifecycle/twin-lifecycle-mutation.ts',
68
- 'twin-forecast/twin-forecast-query.ts'
69
- ]) {
70
- const src = readFileSync(new URL(`../server/service/${f}`, import.meta.url), 'utf8')
71
- assert.match(src, /@Resolver\(\)\n@UseMiddleware\(SpeakRefusals\)\nexport class/, f)
72
- }
73
- const ref = readFileSync(new URL('../server/service/reference/reference-resolver.ts', import.meta.url), 'utf8')
74
- assert.match(ref, /e instanceof Refusal \? refusalKey\(e\.code\)/, 'the import result speaks the same key')
75
- })