@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,297 +0,0 @@
1
- /*
2
- * ★ 웜스타트 판정 검증 — 재기동하는 커널에 직전 관측 상태를 심을지.
3
- *
4
- * 이 판정은 **양쪽으로 오류 없이 틀린 값을 낸다**: 심어야 할 때 안 심으면 있는 재고가 0 으로 보이고
5
- * (2026-07-31 hatiolab-wms — 저널에 입고 540·출고 94 인데 재고 화면이 비어 있었다),
6
- * 벤치에 심으면 용량 측정이 오염된다. 둘 다 화면에는 아무 이상이 없어 보인다.
7
- */
8
- import { test } from 'node:test'
9
- import assert from 'node:assert/strict'
10
- import { readFileSync } from 'node:fs'
11
- import { fileURLToPath } from 'node:url'
12
-
13
- import { planLiveContinuity, planWarmStart, unwrapState } from '../server/engine/warm-start.ts'
14
-
15
- const STATE = {
16
- locations: [{ id: 'dock-recv' }, { id: 'rack-1' }],
17
- items: [{ epc: 'a' }, { epc: 'b' }, { epc: 'c' }],
18
- equipment: [{ id: 'fork-1' }],
19
- orders: [{ id: 'SO-1', kind: 'outbound', status: 'created', progress: 0.5 }],
20
- tasks: [{ id: 't1' }]
21
- }
22
-
23
- test('상태가 있으면 심는다 — 재고·노드·무버', () => {
24
- const plan = planWarmStart(STATE, undefined, true)
25
- assert.equal(plan.action, 'hydrate')
26
- if (plan.action !== 'hydrate') return
27
- assert.equal(plan.itemCount, 3)
28
- assert.equal(plan.equipmentCount, 1)
29
- assert.deepEqual(plan.seed.locations, STATE.locations)
30
- })
31
-
32
- test('원값 없는 오더는 심지 않는다 — 남은 수량을 알 수 없어 지어내야 하기 때문', () => {
33
- /* STATE 의 오더는 progress 만 들고 있다 — 커널 판정(requested !== undefined)과 같은 기준으로 뺀다. */
34
- const plan = planWarmStart(STATE, undefined, true)
35
- assert.equal(plan.action, 'hydrate')
36
- if (plan.action !== 'hydrate') return
37
- assert.equal(plan.seed.orders, undefined)
38
- assert.equal(plan.orderCount, 0)
39
- assert.equal(plan.ordersWithoutDemand, 1)
40
- })
41
-
42
- test('뺀 오더의 수를 센다 — "주문이 없다" 와 "주문을 못 심었다" 가 같아지면 안 된다', () => {
43
- /*
44
- * 이 숫자가 로그의 근거다. 세지 않고 알리지 않고 빼면, 재기동 후 빈 주문 목록을 보고
45
- * 사용자는 "원래 없었다" 로 읽는다. 실제로 그 화면이 오래 남아 있었다.
46
- */
47
- const mixed = {
48
- ...STATE,
49
- orders: [
50
- { id: 'SO-1', kind: 'outbound', status: 'created', progress: 0.5 },
51
- { id: 'SO-2', kind: 'outbound', status: 'created', requested: 100, fulfilled: 40 },
52
- { id: 'SO-3', kind: 'outbound', status: 'created', requested: 30 }
53
- ]
54
- }
55
- const plan = planWarmStart(mixed, undefined, true)
56
- assert.equal(plan.action, 'hydrate')
57
- if (plan.action !== 'hydrate') return
58
- assert.equal(plan.orderCount, 2)
59
- assert.equal(plan.ordersWithoutDemand, 1)
60
- assert.deepEqual((plan.seed.orders as any[]).map(o => o.id), ['SO-2', 'SO-3'])
61
- })
62
-
63
- test('진행 중 주문을 심는다 — 재기동하면 주문이 사라졌던 결함의 회귀 방지', () => {
64
- /*
65
- * 예전에는 씨앗이 자리·물품·설비 셋만 넘겨, 재고는 맞는데 주문 목록이 비었다. 원값이 있는
66
- * 오더는 반드시 씨앗에 실려야 한다 — 이 단언이 그 결함으로 되돌아가는 것을 막는다.
67
- */
68
- const plan = planWarmStart(
69
- { ...STATE, orders: [{ id: 'SO-9', kind: 'outbound', status: 'created', requested: 50, fulfilled: 10, lines: [{ gtin: 'g1', requested: 50 }] }] },
70
- undefined,
71
- true
72
- )
73
- assert.equal(plan.action, 'hydrate')
74
- if (plan.action !== 'hydrate') return
75
- assert.equal(plan.orderCount, 1)
76
- assert.equal(plan.ordersWithoutDemand, 0)
77
- assert.equal((plan.seed.orders as any[])[0].requested, 50)
78
- assert.equal((plan.seed.orders as any[])[0].fulfilled, 10)
79
- })
80
-
81
- test('작업·사람·자산도 함께 심는다 — 커널이 심을 수 있는 축을 호스트가 버리지 않는다', () => {
82
- const plan = planWarmStart(
83
- { ...STATE, persons: [{ id: 'p1' }, { id: 'p2' }], assets: [{ id: 'pallet-1' }] },
84
- undefined,
85
- true
86
- )
87
- assert.equal(plan.action, 'hydrate')
88
- if (plan.action !== 'hydrate') return
89
- assert.equal(plan.taskCount, 1)
90
- assert.equal(plan.personCount, 2)
91
- assert.equal(plan.assetCount, 1)
92
- assert.deepEqual(plan.seed.tasks, STATE.tasks)
93
- assert.equal((plan.seed.persons as any[]).length, 2)
94
- })
95
-
96
- test('없는 축은 씨앗에 키를 만들지 않는다 — 빈 배열로 커널 판정을 흐리지 않는다', () => {
97
- const plan = planWarmStart({ locations: [{ id: 'n1' }], items: [], equipment: [] }, undefined, true)
98
- assert.equal(plan.action, 'hydrate')
99
- if (plan.action !== 'hydrate') return
100
- assert.deepEqual(Object.keys(plan.seed).sort(), ['equipment', 'items', 'locations'])
101
- })
102
-
103
- test('오더만 있어도 심는다 — 구조가 모델에서 오는 경우가 있다', () => {
104
- const plan = planWarmStart({ orders: [{ id: 'SO-1', requested: 10 }] } as any, undefined, true)
105
- assert.equal(plan.action, 'hydrate')
106
- if (plan.action !== 'hydrate') return
107
- assert.equal(plan.orderCount, 1)
108
- })
109
-
110
- test('벤치 트윈에는 심지 않는다 — 새 시작에서 용량을 재는 것이 목적이다', () => {
111
- const plan = planWarmStart(STATE, 'bench', true)
112
- assert.deepEqual(plan, { action: 'skip', reason: 'bench' })
113
- })
114
-
115
- test('벤치 판정은 상태 유무보다 먼저다 — 상태가 없어도 이유는 bench 여야 한다', () => {
116
- /* 이유가 뒤바뀌면 로그가 "심을 게 없었다" 로 남아, 벤치를 의도적으로 비웠다는 사실이 사라진다. */
117
- assert.deepEqual(planWarmStart(null, 'bench', true), { action: 'skip', reason: 'bench' })
118
- })
119
-
120
- test('심을 상태가 없으면 알리지 않고 넘어간다 — 처음 만든 트윈의 정상 경로다', () => {
121
- assert.deepEqual(planWarmStart(null, undefined, true), { action: 'skip', reason: 'no-state' })
122
- assert.deepEqual(planWarmStart(undefined, undefined, true), { action: 'skip', reason: 'no-state' })
123
- assert.deepEqual(planWarmStart({ locations: [], items: [], equipment: [] }, undefined, true), { action: 'skip', reason: 'no-state' })
124
- })
125
-
126
- test('노드만 있어도 심는다 — 구조 배치가 복원되면 화면이 살아난다', () => {
127
- const plan = planWarmStart({ locations: [{ id: 'n1' }], items: [], equipment: [] }, undefined, true)
128
- assert.equal(plan.action, 'hydrate')
129
- if (plan.action !== 'hydrate') return
130
- assert.equal(plan.itemCount, 0)
131
- })
132
-
133
- test('커널이 주입을 지원하지 않으면 알린다 — 알리지 않고 빈 채로 뜨면 안 된다', () => {
134
- assert.deepEqual(planWarmStart(STATE, undefined, false), { action: 'skip', reason: 'unsupported' })
135
- })
136
-
137
- test('심을 게 없으면 미지원이어도 경고할 일이 아니다', () => {
138
- /* 미지원 경고가 매 기동마다 뜨면 진짜 경고가 묻힌다. */
139
- assert.deepEqual(planWarmStart(null, undefined, false), { action: 'skip', reason: 'no-state' })
140
- })
141
-
142
- test('빠진 배열은 빈 배열로 다뤄지되 없는 것을 지어내지 않는다', () => {
143
- const plan = planWarmStart({ items: [{ epc: 'a' }] } as any, undefined, true)
144
- assert.equal(plan.action, 'hydrate')
145
- if (plan.action !== 'hydrate') return
146
- assert.deepEqual(plan.seed.locations, [])
147
- assert.deepEqual(plan.seed.equipment, [])
148
- assert.equal(plan.itemCount, 1)
149
- })
150
-
151
- test('확인해 둔 주목 신호를 이어받는다 — 재기동하면 다시 빨개지던 것', () => {
152
- /*
153
- * 확인 처리는 상태에서 파생되지 않는 유일한 축이다. 씨앗에서 빠지면 재기동 후 확인해 둔 신호가
154
- * 전부 다시 활성으로 뜬다 — 오류는 나지 않고, 사용자는 "또 터졌다" 로 읽는다.
155
- */
156
- const plan = planWarmStart({ ...STATE, acked: ['bottleneck:bin-1', 'breakdown:fk-1'] } as any, undefined, true)
157
- assert.equal(plan.action, 'hydrate')
158
- if (plan.action !== 'hydrate') return
159
- assert.deepEqual(plan.seed.acked, ['bottleneck:bin-1', 'breakdown:fk-1'])
160
- assert.equal(plan.ackedCount, 2)
161
- })
162
-
163
- test('확인 처리만 있어도 복원한다 — 신호를 확인해 둔 사실 자체가 이어받을 가치가 있다', () => {
164
- const plan = planWarmStart({ acked: ['bottleneck:bin-1'] } as any, undefined, true)
165
- assert.equal(plan.action, 'hydrate')
166
- if (plan.action !== 'hydrate') return
167
- assert.equal(plan.ackedCount, 1)
168
- })
169
-
170
- test('확인 처리가 문자열 목록이 아니면 없는 것으로 본다 — 지어내지 않는다', () => {
171
- const plan = planWarmStart({ ...STATE, acked: 'nope' } as any, undefined, true)
172
- assert.equal(plan.action, 'hydrate')
173
- if (plan.action !== 'hydrate') return
174
- assert.equal(plan.ackedCount, 0)
175
- assert.equal(plan.seed.acked, undefined)
176
- })
177
-
178
- /*
179
- * ── 겹포장 회귀 방지 (2026-08-05) ──────────────────────────────────────────
180
- * 체크포인트가 `{revision, state:{revision, state:{실제}}}` 로 저장돼, 꺼낸 값에 축이 하나도 없었다.
181
- * 판정은 "심을 것이 없다"(no-state)로 답하고 **알리지 않고** 넘어갔다 — 저널에 수천 건이 있고 캐시도
182
- * 최신인데 트윈이 빈 채로 떴다. 오류도 로그도 없어서 이 경로가 처음부터 죽어 있었다.
183
- */
184
- test('봉투로 감싸여 와도 벗겨서 심는다 — 체크포인트가 겹포장돼 복원이 죽었던 자리', () => {
185
- const enveloped = { revision: 2684, state: { revision: 2684, state: STATE } }
186
- const plan = planWarmStart(enveloped as any, undefined, true)
187
- assert.equal(plan.action, 'hydrate', '봉투를 받으면 심을 것이 없다고 답하면 안 된다')
188
- if (plan.action !== 'hydrate') return
189
- assert.equal(plan.itemCount, 3)
190
- assert.deepEqual(plan.seed.locations, STATE.locations)
191
- })
192
-
193
- test('한 겹 봉투도 벗긴다 — 저장 방식이 바뀌는 동안 두 모양이 함께 남는다', () => {
194
- const plan = planWarmStart({ revision: 1, state: STATE } as any, undefined, true)
195
- assert.equal(plan.action, 'hydrate')
196
- if (plan.action !== 'hydrate') return
197
- assert.equal(plan.itemCount, 3)
198
- })
199
-
200
- test('벗길 것이 없으면 그대로 쓴다 — 상태를 봉투로 착각하지 않는다', () => {
201
- const plan = planWarmStart(STATE, undefined, true)
202
- assert.equal(plan.action, 'hydrate')
203
- if (plan.action !== 'hydrate') return
204
- assert.equal(plan.itemCount, 3)
205
- })
206
-
207
- test('빈 봉투는 여전히 no-state — 벗겼는데도 아무 축이 없으면 심을 것이 없다', () => {
208
- assert.deepEqual(planWarmStart({ revision: 5, state: { revision: 5 } } as any, undefined, true), { action: 'skip', reason: 'no-state' })
209
- })
210
-
211
- test('unwrapState 는 상태를 먼저 알아본다 — state 라는 이름의 축이 있어도 벗기지 않는다', () => {
212
- const st = { items: [{ epc: 'a' }], state: 'whatever' }
213
- assert.equal(unwrapState(st as any), st, '축이 있으면 그것이 상태다')
214
- })
215
-
216
- /*
217
- * ── 「언제부터인가」도 씨앗에 실린다 (2026-08-18) ─────────────────────────────
218
- * 확인과 같은 성질이다 — 상태에서 파생되지 않으므로 넘기지 않으면 사라진다. 사라지면 세 시간째
219
- * 지속된 조건이 재기동 뒤 「0초째」가 되고, 화면은 사람을 잘못된 순서로 움직인다.
220
- */
221
- test('주목 신호 시작 시각이 씨앗에 실린다 — 재기동 뒤 지속 시간이 거짓이 되지 않게', () => {
222
- const since = [{ id: 'bottleneck:bin-1', since: '2026-08-18T01:00:00.000Z' }]
223
- const plan = planWarmStart({ ...STATE, attentionSince: since } as any, undefined, true)
224
- assert.equal(plan.action, 'hydrate')
225
- if (plan.action !== 'hydrate') return
226
- assert.deepEqual(plan.seed.attentionSince, since)
227
- assert.equal(plan.attentionSinceCount, 1)
228
- })
229
-
230
- test('시작 시각만 있어도 복원한다 — 그 사실 자체가 이어받을 가치가 있다', () => {
231
- const plan = planWarmStart({ attentionSince: [{ id: 'a', since: '2026-08-18T01:00:00.000Z' }] } as any, undefined, true)
232
- assert.equal(plan.action, 'hydrate')
233
- if (plan.action !== 'hydrate') return
234
- assert.equal(plan.attentionSinceCount, 1)
235
- })
236
-
237
- test('모양이 아닌 시작 시각은 없는 것으로 본다 — 지어낸 시각을 심지 않는다', () => {
238
- const plan = planWarmStart({ ...STATE, attentionSince: ['bottleneck:bin-1', { id: 'ok', since: 5 }, { since: '2026-08-18T01:00:00.000Z' }] } as any, undefined, true)
239
- assert.equal(plan.action, 'hydrate')
240
- if (plan.action !== 'hydrate') return
241
- assert.equal(plan.attentionSinceCount, 0)
242
- assert.equal(plan.seed.attentionSince, undefined)
243
- })
244
-
245
- /*
246
- * ── 미러 재기동의 연속성 (2026-08-18) ────────────────────────────────────────
247
- * 미러는 오랫동안 아무것도 이어받지 않았다 — 진실이 원천에 있으니 옳았지만, 원천이 **애초에 다시 말해
248
- * 주지 않는 축**까지 함께 버렸다. 그래서 재기동하면 오류 없이 값이 작아졌다.
249
- */
250
- test('미러는 되풀어 주지 않는 축만 이어받는다 — 관측 축은 원천에서 온다', () => {
251
- const plan = planLiveContinuity({
252
- ...STATE,
253
- acked: ['bottleneck:bin-1'],
254
- attentionSince: [{ id: 'bottleneck:bin-1', since: '2026-08-18T01:00:00.000Z' }],
255
- energy: { points: [{ id: 'm-1', kWhAtWindowStart: 1000, samplesInWindow: 3 }], closed: [], closedTotal: 0 }
256
- })
257
- assert.equal(plan.ackedCount, 1)
258
- assert.equal(plan.attentionSinceCount, 1)
259
- assert.equal(plan.energy, true)
260
- /* 관측 축은 **일부러** 넣지 않는다 — 심으면 부팅 전에 떠난 물건이 되살아난다. */
261
- assert.equal((plan.seed as any).locations, undefined)
262
- assert.equal((plan.seed as any).items, undefined)
263
- assert.equal((plan.seed as any).equipment, undefined)
264
- assert.equal((plan.seed as any).orders, undefined)
265
- })
266
-
267
- test('에너지가 없는 트윈은 에너지를 이어받지 않는다 — 없는 것을 있다고 하지 않는다', () => {
268
- const plan = planLiveContinuity({ ...STATE, acked: ['x'] })
269
- assert.equal(plan.energy, false)
270
- assert.equal((plan.seed as any).energy, undefined)
271
- })
272
-
273
- test('이어받을 것이 없으면 빈 씨앗이다 — 빈 주입으로 로그만 남기지 않는다', () => {
274
- const plan = planLiveContinuity(STATE)
275
- assert.deepEqual(plan.seed, {})
276
- assert.equal(plan.ackedCount + plan.attentionSinceCount, 0)
277
- assert.equal(plan.energy, false)
278
- })
279
-
280
- test('겹포장된 체크포인트도 벗겨 읽는다 — 한 번은 반드시 만난다', () => {
281
- const plan = planLiveContinuity({ revision: 42, state: { acked: ['a'], energy: { points: [] } } })
282
- assert.equal(plan.ackedCount, 1)
283
- assert.equal(plan.energy, true)
284
- })
285
-
286
- /* 배선이 사라지면 미러는 알리지 않고 예전으로 돌아간다 — 소스 모양으로 못 박는다(엔진은 DB 를 물고 있다). */
287
- test('미러 기동이 연속성 씨앗을 심는다 — 배선이 사라지지 않게', () => {
288
- const src = readFileSync(fileURLToPath(new URL('../server/engine/twin-engine.ts', import.meta.url)), 'utf-8')
289
- const at = src.indexOf('static startLive(')
290
- assert.ok(at > 0)
291
- const body = src.slice(at, src.indexOf('\n static ', at + 10))
292
- assert.match(body, /seedLiveContinuity\(domainId, id, kernel\)/, '미러가 연속성을 이어받아야 한다')
293
- assert.ok(
294
- body.indexOf('seedLiveContinuity') < body.indexOf('delete this.recovered[key]'),
295
- '캐시를 지우기 전에 심는다 — 순서가 뒤집히면 늘 빈손이다'
296
- )
297
- })
@@ -1,95 +0,0 @@
1
- /*
2
- * ★ **원본에 있는데 세우지 않은 것** — 그 사실이 스쳐 지나가지 않게.
3
- *
4
- * ── 무엇이 아무 신호도 내지 않았나 (2026-08-24) ────────────────────────────────────────────
5
- * 커넥터가 원본의 사실 일부를 **일부러 받지 않는 일이 정상이다**(입자가 안 맞는다 · 받으면 상태가
6
- * 거짓이 된다 · 커널 어휘로 옮길 수 없다). 그때 경고를 내는데, 그 경고의 유일한 소비처가 **프로비저닝
7
- * 마법사**였다 — 트윈을 만드는 동안만 뜨는 화면이다.
8
- *
9
- * 그래서 「지시되지 않은 생산계획 8건을 세우지 않았다」가 **한 번 스쳐 지나갈 뿐**이었고, 나중에
10
- * 사용자가 「원본보다 계획이 적다」를 물으면 답이 어디에도 없었다.
11
- *
12
- * 그 사실은 한 번의 사건이 아니라 **상태의 성질**이다 — 세우지 않은 것은 **지금도** 트윈에 없다.
13
- *
14
- * ── `unhandled` 의 형제다 ──────────────────────────────────────────────────
15
- * `unhandled` 리듀서가 **받았는데** 담을 자리를 몰랐다
16
- * 여기 커넥터가 **보지만 일부러 보내지 않았다** — 이유와 함께
17
- *
18
- * ── 그래서 문에서 조회까지 걷는다 ───────────────────────────────────────────
19
- * 오늘 「계약에 자리는 있고 그 자리로 가는 길이 없다」를 여섯 번 만났다. 장부만 검사하면 어댑터가
20
- * 부를 문이 없는 것을 못 잡는다 — 그것이 그 결함들이 살아남은 방식이다.
21
- */
22
- import { test } from 'node:test'
23
- import assert from 'node:assert/strict'
24
- import { readFileSync } from 'node:fs'
25
- import { createRequire } from 'node:module'
26
-
27
- const req = createRequire(import.meta.url)
28
- const { newIngestLedger, recordWithheld, ingestHealth } = req('../dist-server/engine/ingest-health.js')
29
-
30
- const REASON = '아직 지시되지 않은 생산계획을 세우지 않았다 — 커널의 created 는 「할당해도 되는 오더」를 뜻한다'
31
-
32
- test('★ 세우지 않은 것이 조회에 나온다 — 유입이 한 건도 없어도', () => {
33
- /*
34
- * 이 갈래가 중요하다: 원본이 말하는데 **전부** 안 받는 경우가 있고, 그때 유입은 0 이다.
35
- * 유입 있는 갈래에서만 내면 바로 그 상황에서 들어온 것이 없어진다.
36
- */
37
- const l = newIngestLedger()
38
- recordWithheld(l, REASON, 8, Date.parse('2026-08-24T11:19:16.000Z'))
39
- const view: any = ingestHealth(l)
40
- assert.equal(view.withheld?.length, 1)
41
- assert.equal(view.withheld[0].reason, REASON)
42
- assert.equal(view.withheld[0].count, 8)
43
- assert.equal(view.withheld[0].lastAt, '2026-08-24T11:19:16.000Z', '언제 그랬는지 함께 — 「지금도 그런가」를 사람이 판정한다')
44
- })
45
-
46
- test('주기마다 불러도 부풀지 않는다 — 누적이 아니라 **지금 세우지 않은 수**다', () => {
47
- /* 8건이 매 주기 다시 보고되면 8 이어야 한다. 더해서 800 이 되면 거짓이다. */
48
- const l = newIngestLedger()
49
- for (let i = 0; i < 100; i++) recordWithheld(l, REASON, 8, 1000 + i)
50
- assert.equal(l.withheld.length, 1)
51
- assert.equal(l.withheld[0].count, 8)
52
- assert.equal(l.withheld[0].lastAtMs, 1099, '마지막 시각으로 움직인다')
53
- })
54
-
55
- test('수가 달라지면 마지막 수로 덮는다 — 낡은 수가 남지 않게', () => {
56
- const l = newIngestLedger()
57
- recordWithheld(l, REASON, 8, 1000)
58
- recordWithheld(l, REASON, 3, 2000)
59
- assert.equal(l.withheld[0].count, 3)
60
- })
61
-
62
- test('이유가 여럿이면 각자 한 줄 — 다른 사실을 한 줄로 뭉치지 않는다', () => {
63
- const l = newIngestLedger()
64
- recordWithheld(l, REASON, 8, 1000)
65
- recordWithheld(l, '사람이 올린 문서라 자재와 이어지지 않는다', 46, 1000)
66
- assert.equal((ingestHealth(l) as any).withheld.length, 2)
67
- })
68
-
69
- test('말하지 않은 것은 만들지 않는다 — 빈 목록을 「세우지 않은 것이 있다」로 읽히게 하지 않는다', () => {
70
- const l = newIngestLedger()
71
- assert.equal((ingestHealth(l) as any).withheld, undefined, '키 자체가 없다')
72
- recordWithheld(l, REASON, 0, 1000)
73
- assert.equal(l.withheld, undefined, '0 은 적지 않는다')
74
- recordWithheld(l, '', 5, 1000)
75
- assert.equal(l.withheld, undefined, '이유 없는 것은 적지 않는다')
76
- })
77
-
78
- test('★ 어댑터가 부를 문이 있고, 그 문이 장부에 닿는다', () => {
79
- /*
80
- * 이 단정이 오늘 여섯 번 만난 부류를 막는다. 장부만 검사하면 **어댑터가 부를 통로가 없는 것**을
81
- * 못 잡고, 그러면 보내는 쪽에는 「알렸다」로 보이고 화면에는 「없다」로 보인다.
82
- */
83
- const adapter = readFileSync(new URL('../server/service/reference/reference-adapter.ts', import.meta.url), 'utf-8')
84
- assert.match(adapter, /onWithheld\?: \(info: \{ reason: string; count: number \}\) => void/, '계약에 통로가 있다')
85
-
86
- const live = readFileSync(new URL('../server/service/reference/reference-live.ts', import.meta.url), 'utf-8')
87
- const wired = live.slice(live.indexOf('onWithheld'), live.indexOf('onWithheld') + 260)
88
- assert.match(wired, /recordIngestWithheld/, '그 통로가 장부로 이어진다')
89
-
90
- const engine = readFileSync(new URL('../server/engine/twin-engine.ts', import.meta.url), 'utf-8')
91
- const fn = engine.slice(engine.indexOf('static recordIngestWithheld'))
92
- assert.match(fn.slice(0, 700), /recordWithheld\(ledger/, '엔진이 장부에 적는다')
93
- /* 실패로 적지 않는다 — 어댑터의 옳은 판단이고, 오류로 적으면 화면이 원본을 의심한다. */
94
- assert.doesNotMatch(fn.slice(0, 700), /lastError|status:/, '오류로 적지 않는다')
95
- })
@@ -1,199 +0,0 @@
1
- /*
2
- * **한 바퀴** — 커널이 라인을 돌리고, 그 이벤트를 계산해, 배운 수율이 다시 커널로 들어간다.
3
- *
4
- * ── 왜 이 시험이 필요했나 (2026-08-19) ─────────────────────────────────────
5
- * 층마다 시험이 있었다(커널 7 · 호스트 9). 그런데 **사슬이 이어졌는지**는 층 시험으로 알 수 없다 —
6
- * 이벤트 모양이 한 칸만 어긋나도 각 층은 통과하면서 전체는 알리지 않고 상수로 돈다.
7
- *
8
- * 실 앱에서 보려고 데모 MES 트윈으로 한 바퀴를 돌리려 했는데 두 번 막혔다: ① 데모의 자극(시나리오)은
9
- * **시드 때만 실려서** 트윈을 재기동하면 사라진다 ② 모델에서 읽은 값으로 자극을 재구성했지만 부품 도착이
10
- * 레시피 입력과 맞물리지 않아 라인이 돌지 않았다. 그 두 개는 **데모 데이터의 문제**이고, 우리가 증명해야
11
- * 하는 것(사슬)과는 다른 문제다.
12
- *
13
- * 그래서 여기서 **DB·서버 없이** 진짜 사슬을 돌린다: 커널(MES) → `task.status` 이벤트 → 호스트의 실제
14
- * 폴드(`foldKpi`) → 실제 추정기(`buildYieldEstimator`) → 커널 시임. 가짜 이벤트를 손으로 만들지 않는다 —
15
- * 커널이 낸 것을 그대로 처리한다.
16
- */
17
- import { test } from 'node:test'
18
- import assert from 'node:assert/strict'
19
- import { createRequire } from 'node:module'
20
-
21
- import { foldKpi } from '../server/engine/kpi-fold.ts'
22
- import { buildYieldEstimator } from '../server/engine/measured-yield.ts'
23
-
24
- /* 커널은 한 벌로 묶인 산출물로 들어온다(서브패스는 exports 로 막혀 있다 — property-effects 시험과 같은 이유). */
25
- const require = createRequire(import.meta.url)
26
- const { MesKernel } = require('@operato/twin-kernel')
27
- /* 이 시험이 쓰는 부품 품번을 여기서 선언합니다 — 커널이 생성한 값을 가져다 쓰지 않습니다(0.7.40 이
28
- 그 export 를 제거했습니다). 프리픽스는 GS1 이 예제로 지정한 952 대역입니다. */
29
- const MES_PART_GTINS = { partA: 'urn:epc:idpat:sgtin:9521321.011111.*', partB: 'urn:epc:idpat:sgtin:9521321.022222.*' } /* 선언(SPEC.binding)과 같은 값이어야 자극이 그 자재로 들어옵니다. */
30
-
31
- /** 보드·자극은 커널 시험(`mes.test.ts`)의 것과 같은 모양 — 여기서 공장을 지어내지 않는다. */
32
- function board() {
33
- return {
34
- locations: [
35
- { id: 'raw-store', type: 'raw-store', capacity: 500 },
36
- { id: 'cut-station', type: 'cut-station', capacity: 20 },
37
- { id: 'weld-station', type: 'weld-station', capacity: 20 },
38
- { id: 'paint-booth', type: 'paint-booth', capacity: 20 },
39
- { id: 'assembly-line', type: 'assembly-line', capacity: 20 },
40
- { id: 'fg-store', type: 'fg-store', capacity: 200 }
41
- ],
42
- equipment: [
43
- { id: 'cutter-1', kind: 'cutter', homeLocation: 'cut-station' },
44
- { id: 'welder-1', kind: 'welder', homeLocation: 'weld-station' },
45
- { id: 'painter-1', kind: 'painter', homeLocation: 'paint-booth' },
46
- { id: 'assembler-1', kind: 'assembler', homeLocation: 'assembly-line' }
47
- ]
48
- }
49
- }
50
-
51
- const partsInbound = {
52
- seed: 3,
53
- generators: [
54
- {
55
- kind: 'inbound-arrival',
56
- rate: { distribution: 'constant', meanPerHour: 720 },
57
- content: { skuMix: [{ gtin: MES_PART_GTINS.partA, weight: 1 }, { gtin: MES_PART_GTINS.partB, weight: 1 }], qtyPerLine: { min: 1, max: 1 } }
58
- }
59
- ]
60
- }
61
- const workOrders = {
62
- seed: 7,
63
- generators: [
64
- {
65
- kind: 'outbound-order',
66
- rate: { distribution: 'constant', meanPerHour: 360 },
67
- content: { skuMix: [{ gtin: MES_PART_GTINS.partA, weight: 1 }], qtyPerLine: { min: 1, max: 1 } }
68
- }
69
- ]
70
- }
71
-
72
-
73
- /**
74
- * 이 라인의 **생산 선언** — 커널이 더는 내장 데모 제품을 들지 않습니다(0.7.43).
75
- *
76
- * 무엇을 만드는가는 모델이 정합니다. 그래서 이 시험도 자기 자재·라우트·레시피를 선언하고, 자재는
77
- * 자기 보관 자리를, 현장은 작업지시의 문서 타입을 선언합니다. 프리픽스는 GS1 이 예제로 지정한 952
78
- * 대역입니다 — 실 배정 대역을 시험 데이터에 쓰지 않습니다.
79
- */
80
- const PREFIX = '9521321'
81
- const SPEC = {
82
- companyPrefix: PREFIX,
83
- binding: { partA: '011111', partB: '022222', unit: '033333' },
84
- identity: { documentTypes: { workorder: '403' } },
85
- definition: {
86
- materials: [
87
- { key: 'partA', label: '부품 A', locationType: 'raw-store' },
88
- { key: 'partB', label: '부품 B', locationType: 'raw-store' },
89
- { key: 'unit', label: '완성품', locationType: 'fg-store' }
90
- ],
91
- locationTypes: [
92
- { key: 'raw-store', label: '자재 보관' },
93
- { key: 'cut-station', label: '절단' },
94
- { key: 'weld-station', label: '용접' },
95
- { key: 'paint-booth', label: '도장' },
96
- { key: 'assembly-line', label: '조립' },
97
- { key: 'fg-store', label: '완제품 보관' }
98
- ],
99
- resourceTypes: [
100
- { key: 'cutter', label: '절단기' },
101
- { key: 'welder', label: '용접기' },
102
- { key: 'painter', label: '도장기' },
103
- { key: 'assembler', label: '조립기' }
104
- ],
105
- operations: [
106
- { key: 'cut', label: '절단', intent: 'process', locationType: 'cut-station', resourceType: 'cutter', duration: 'PT1M' },
107
- { key: 'weld', label: '용접', intent: 'process', locationType: 'weld-station', resourceType: 'welder', duration: 'PT1M' },
108
- { key: 'paint', label: '도장', intent: 'process', locationType: 'paint-booth', resourceType: 'painter', duration: 'PT1M' },
109
- { key: 'assembly', label: '조립', intent: 'process', locationType: 'assembly-line', resourceType: 'assembler', duration: 'PT1M' }
110
- ],
111
- routes: [{ key: 'line', label: '라인', steps: ['cut', 'weld', 'paint', 'assembly'] }],
112
- recipes: [
113
- {
114
- key: 'unit',
115
- label: '완성품',
116
- route: 'line',
117
- inputs: [{ material: 'partA', qty: 1 }, { material: 'partB', qty: 1 }],
118
- outputs: [{ material: 'unit', qty: 1 }]
119
- }
120
- ]
121
- }
122
- }
123
-
124
- /** 라인을 한 바퀴 돌린다 — 부품을 채우고 작업지시를 흘리고 배수한다. */
125
- function runLine(declaredYieldPct?: number): { events: any[]; kernel: any } {
126
- const k: any = new MesKernel('plantA', undefined, SPEC)
127
- const events: any[] = []
128
- k.onEvent((e: any) => events.push(e))
129
- k.loadTwinModel(board())
130
- /* 선언값을 넣어 두면 「실측이 선언을 이긴다」를 같은 라인에서 확인할 수 있다. */
131
- if (declaredYieldPct !== undefined) k.declareParameters({ assembly: { yield: String(declaredYieldPct / 100) } })
132
- k.scenario.load(partsInbound)
133
- k.scenario.start()
134
- for (let i = 0; i < 400; i++) k.tick(1000)
135
- k.scenario.pause()
136
- for (let i = 0; i < 30; i++) k.tick(1000)
137
- k.scenario.load(workOrders)
138
- k.scenario.start()
139
- for (let i = 0; i < 300; i++) k.tick(1000)
140
- k.scenario.pause()
141
- for (let i = 0; i < 4000; i++) k.tick(1000)
142
- return { events, kernel: k }
143
- }
144
-
145
- /** 커널 이벤트를 저널 줄 모양으로 — 호스트가 DB 에서 읽는 것과 같은 모양(payload 안에 data). */
146
- const asJournal = (events: any[]) =>
147
- events.filter(e => e.eventType === 'task.status').map(e => ({ eventType: 'task.status', eventTime: e.eventTime, payload: { data: e.data } }))
148
-
149
- const window = (rows: { eventTime: string }[]) => {
150
- const times = rows.map(r => Date.parse(r.eventTime)).filter(n => Number.isFinite(n))
151
- return { fromMs: Math.min(...times) - 1000, toMs: Math.max(...times) + 1000 }
152
- }
153
-
154
- test('한 바퀴: 커널이 판정을 내고 → 폴드가 종류별로 세고 → 추정기가 비율을 배운다', () => {
155
- const { events } = runLine()
156
- const rows = asJournal(events)
157
- assert.ok(rows.length > 50, `작업 전이가 충분히 나야 한다(관측 ${rows.length})`)
158
-
159
- /* 호스트의 **실제** 폴드로 처리한다 — 시험용 계산을 따로 만들지 않는다. */
160
- const kpi = foldKpi(rows as any, window(rows as any), { groupBy: 'taskKind' })
161
- const judged = (kpi.groups?.items ?? []).filter(g => g.quality)
162
- assert.ok(judged.length > 0, '품질이 세어진 종류가 있어야 한다')
163
- for (const g of judged) {
164
- assert.ok(g.quality!.good + g.quality!.scrap > 0)
165
- assert.ok(g.quality!.good + g.quality!.scrap <= g.tasks, '판정 수는 완료 수를 넘지 못한다')
166
- }
167
- /* 판정이 없는 종류도 있어야 한다 — 중간 스테이션은 품질을 가리지 않는다(분모에 섞이면 안 된다). */
168
- assert.ok((kpi.groups?.items ?? []).some(g => !g.quality), '판정하지 않는 공정이 있다')
169
-
170
- const learned = buildYieldEstimator(kpi.groups?.items, { minSamples: 5 })
171
- assert.ok(Object.keys(learned.learned).length > 0, '수율을 배워야 한다')
172
- for (const [kind, ratio] of Object.entries(learned.learned)) {
173
- assert.ok(ratio >= 0 && ratio <= 1, `${kind} 의 비율이 0..1 이어야 한다(관측 ${ratio})`)
174
- const s = learned.samples[kind]
175
- assert.equal(learned.learned[kind], s.good / (s.good + s.scrap), '비율은 판정 수에서 곧바로 나온다')
176
- }
177
- })
178
-
179
- test('배운 값이 커널로 되돌아가 선언값을 이긴다 — 사슬의 마지막 칸', () => {
180
- /* 선언 60% 로 라인을 돌린다(그 현장의 이력이 그렇게 남는다). */
181
- const { events } = runLine(60)
182
- const rows = asJournal(events)
183
- const kpi = foldKpi(rows as any, window(rows as any), { groupBy: 'taskKind' })
184
- const learned = buildYieldEstimator(kpi.groups?.items, { minSamples: 5 })
185
- const kinds = Object.keys(learned.learned)
186
- assert.ok(kinds.length > 0, '이력에서 배운 종류가 있어야 한다')
187
-
188
- /* 새 커널에 그 이력을 실으면 — 선언값(90%)이 아니라 이력값으로 답한다. */
189
- const k2: any = new MesKernel('plantA')
190
- k2.declareParameters(Object.fromEntries(kinds.map(kind => [kind, { yield: '0.9' }])))
191
- k2.yieldEstimator = learned.estimator
192
- for (const kind of kinds) {
193
- assert.equal(k2.yieldOf(kind), learned.learned[kind], `${kind}: 이력값이 이긴다`)
194
- assert.deepEqual(k2.specCoverage().operations.find((o: any) => o.kind === kind)?.parameterBasis, { yield: 'measured' })
195
- }
196
- /* 이력이 없는 종류는 그대로 선언값이다 — 배운 것만 이긴다(전부 덮지 않는다). */
197
- k2.declareParameters({ 'never-run': { yield: '0.5' } })
198
- assert.equal(k2.yieldOf('never-run'), 0.5)
199
- })
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "extends": "../tsconfig-base.json",
3
- "compilerOptions": {
4
- "outDir": "./dist-server",
5
- /* shared/ 는 별도 산출(dist-shared) — 여기 섞이면 dist-server/server/ 로 한 겹 밀린다. */
6
- "rootDir": "./server",
7
- "baseUrl": "./",
8
- "skipLibCheck": true,
9
- /* 시험은 소스를 그대로 불러오므로 지역 import 가 `.ts` 여야 하고, 산출물은 `.js` 여야 한다.
10
- 이 옵션이 컴파일 때 확장자를 바꿔 준다(twin-ai 가 이미 쓰는 관행 — 두 규칙을 함께 지킨다). */
11
- "rewriteRelativeImportExtensions": true
12
- },
13
- "include": ["./server/**/*"],
14
- "exclude": ["**/*.spec.ts"]
15
- }
@@ -1,23 +0,0 @@
1
- /*
2
- * 공유 어휘 빌드 — 서버와 **브라우저가 함께 보는** 순수 모듈.
3
- *
4
- * 왜 서버 빌드와 따로인가 (2026-08-07):
5
- * 이 파일들은 `server/engine/` 안에 있었고, 화면 코드가 `dist-server/engine/*.js` 를 깊이 참조했다.
6
- * 그런데 `build:server` 는 `rm -rf dist-server` 로 시작한다. tsc 가 다시 채우기 전 그 틈에 webpack 이
7
- * 컴파일하면 해석에 실패하고, 그 실패가 `bootstrap.js` 를 죽여 **앱 전체가 백지**가 된다. 콘솔에
8
- * 오류 한 줄 없이 화면만 빈다. 실제로 그렇게 한 번 멈췄다.
9
- *
10
- * 그래서 산출 자리를 서버와 분리한다. `dist-shared` 는 서버를 다시 빌드해도 지워지지 않는다.
11
- * (`build:shared` 도 일부러 clean 하지 않는다 — 지우는 순간이 곧 그 틈이다. 전체 정리는 `clean` 이 한다.)
12
- */
13
- {
14
- "extends": "../tsconfig-base.json",
15
- "compilerOptions": {
16
- "outDir": "./dist-shared",
17
- "rootDir": "./shared",
18
- "baseUrl": "./",
19
- "declaration": true,
20
- "skipLibCheck": true
21
- },
22
- "include": ["./shared/**/*"]
23
- }