@things-factory/headless-twin 10.1.277 → 10.1.279

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,104 +0,0 @@
1
- /*
2
- * **허락과 일어남 사이를 같은 행에 닫는다** — ADR-0029 §1 결정 C (2026-08-19).
3
- *
4
- * ── 무엇이 열려 있었나 ──────────────────────────────────────────────────────
5
- * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다: 어댑터가 오류 없이 실패하면 원장에는 승인만 남는다.
6
- * 그리고 구동 문(`controlTwinSource`)은 감사를 **아예 남기지 않았다** — 자극을 바꾸고 배속을 올리는 것은
7
- * 그 트윈의 사실을 바꾸는 행위인데, 나중에 「무엇이 이 공장을 흔들었나」에 답할 수 없었다.
8
- *
9
- * ── 세 값을 구별한다 ────────────────────────────────────────────────────────
10
- * · 칸이 **없음** — 원본에 묻지 않았다(커널이 받은 명령).
11
- * · `unknown` — 물었는데 답이 없다. **성공으로 적지 않는다.**
12
- * · `applied`·`refused` — 원본이 답했다(둘 다 사실이다).
13
- *
14
- * 셋을 뭉개면 둘 중 하나가 된다: 일어난 일을 없던 일로 만들거나, 없던 일을 일어난 일로 만든다.
15
- */
16
- import { test } from 'node:test'
17
- import assert from 'node:assert/strict'
18
- import { readFileSync } from 'node:fs'
19
- import { fileURLToPath } from 'node:url'
20
-
21
- import { buildCommandAudit, sourceOutcomeOf } from '../server/service/twin-audit/command-audit.ts'
22
-
23
- const at = new Date('2026-08-19T05:00:00.000Z')
24
-
25
- test('묻지 않았으면 칸을 만들지 않는다 — 커널이 받은 명령이 그렇다', () => {
26
- const row = buildCommandAudit({ command: { type: 'order.hold', origin: 'user' }, ack: { accepted: true }, at })
27
- assert.equal('sourceOutcome' in row, false, '없음은 「모른다」가 아니라 「묻지 않았다」다')
28
- assert.equal('sourceCode' in row, false)
29
- })
30
-
31
- test('물었는데 답이 없으면 unknown — 성공으로 적지 않는다', () => {
32
- const row = buildCommandAudit({
33
- command: { type: 'source.stimulus', origin: 'user' },
34
- ack: { accepted: true },
35
- source: { answered: false },
36
- at
37
- })
38
- assert.equal(row.sourceOutcome, 'unknown')
39
- })
40
-
41
- test('답이 있으면 그대로 적는다 — 거절도 사실이다', () => {
42
- const applied = buildCommandAudit({ command: {}, ack: { accepted: true }, source: { answered: true, ok: true }, at })
43
- assert.equal(applied.sourceOutcome, 'applied')
44
- const refused = buildCommandAudit({
45
- command: {},
46
- ack: { accepted: true },
47
- source: { answered: true, ok: false, code: 'not-declared' },
48
- at
49
- })
50
- assert.equal(refused.sourceOutcome, 'refused')
51
- assert.equal(refused.sourceCode, 'not-declared', '원본이 준 사유를 그대로 적는다')
52
- })
53
-
54
- test('사유가 없으면 사유 칸도 없다 — 지어내지 않는다', () => {
55
- const row = buildCommandAudit({ command: {}, ack: { accepted: true }, source: { answered: true, ok: true }, at })
56
- assert.equal('sourceCode' in row, false)
57
- })
58
-
59
- test('판정 함수가 세 값만 낸다 — ok 가 참/거짓이 아니면 모른다', () => {
60
- assert.equal(sourceOutcomeOf({ answered: true, ok: true }), 'applied')
61
- assert.equal(sourceOutcomeOf({ answered: true, ok: false }), 'refused')
62
- assert.equal(sourceOutcomeOf({ answered: false }), 'unknown')
63
- assert.equal(sourceOutcomeOf({ answered: true }), 'unknown', '답했다고 하면서 값이 없으면 모르는 것이다')
64
- assert.equal(sourceOutcomeOf({ answered: true, ok: undefined as any }), 'unknown')
65
- })
66
-
67
- test('신원은 여전히 서버만 채운다 — 원본의 답이 그 규율을 흔들지 않는다', () => {
68
- const row = buildCommandAudit({
69
- command: { type: 'source.pause', origin: 'user', actorId: 'forged', actorEmail: 'forged@x' },
70
- ack: { accepted: true },
71
- source: { answered: true, ok: true },
72
- at,
73
- actor: { id: 'u1', email: 'real@x' }
74
- })
75
- assert.equal(row.actorId, 'u1')
76
- assert.equal(row.actorEmail, 'real@x')
77
- })
78
-
79
- /*
80
- * ── 구동 문이 실제로 남기는지 (소스로 지킨다) ───────────────────────────────
81
- * 순수 함수만 시험하면 「기록을 만들 수 있다」까지만 지킨다. 남기지 않으면 그 함수는 아무 일도 하지 않는다.
82
- */
83
- test('구동 문이 게이트 뒤에서 원본의 답까지 남긴다', () => {
84
- const src = readFileSync(fileURLToPath(new URL('../server/service/twin-control/twin-control-mutation.ts', import.meta.url)), 'utf-8')
85
- const code = src
86
- .split('\n')
87
- .filter(line => !/^\s*(\*|\/\/|\/\*)/.test(line))
88
- .join('\n')
89
- /* 게이트는 남는다(결정 C 의 절반). */
90
- const gates = code.match(/@privilege\(category: "twin", privilege: "mutation"/g) ?? []
91
- assert.ok(gates.length >= 2, `구동 문에도 게이트가 있어야 한다(발견 ${gates.length})`)
92
- /* 원본의 답을 같은 행에 닫는다. */
93
- assert.match(code, /source: \{ answered: typeof result\?\.ok === 'boolean', ok: result\?\.ok, code: result\?\.code \}/)
94
- assert.match(code, /type: `source\.\$\{action\}`/, '커맨드 채널과 같은 어휘로 적는다')
95
- /* 기록 실패를 삼키지 않는다. */
96
- assert.match(code, /source control audit not recorded/)
97
- })
98
-
99
- test('엔티티가 그 두 칸을 든다 — 비어 있음이 뜻을 갖는다', () => {
100
- const src = readFileSync(fileURLToPath(new URL('../server/service/twin-audit/twin-audit-event.ts', import.meta.url)), 'utf-8')
101
- assert.match(src, /sourceOutcome\?: string/)
102
- assert.match(src, /sourceCode\?: string/)
103
- assert.match(src, /the source was not asked/, '비어 있음의 뜻을 필드 설명이 말한다')
104
- })
@@ -1,223 +0,0 @@
1
- /*
2
- * 공간 ↔ 트윈 ↔ 가시화 정합성 — 어긋난 모양마다 하나씩 세운다.
3
- *
4
- * 검사가 **무는지** 확인하는 것이 이 파일의 일이다: 정합한 입력에서는 아무것도 내지 않고, 어긋난
5
- * 입력에서는 그 자리를 코드와 id 로 지목해야 한다. 지목하지 못하면 사람이 어디를 볼지 알 수 없다.
6
- */
7
- import { test } from 'node:test'
8
- import assert from 'node:assert/strict'
9
-
10
- import { checkSpaceIntegrity, sortFindings, type SpaceIntegrityInput } from '../server/service/twin-space/space-integrity.ts'
11
-
12
- /** 정합한 한 현장 — 트윈 하나(창고), 지도 표현 하나, 구역 하나, 폴리곤이 그 구역과 로케이션을 가리킨다. */
13
- const SOUND: SpaceIntegrityInput = {
14
- spaces: [{ spaceId: 'rosarito-site', primaryRepresentationId: 'rep-map' }],
15
- instances: [
16
- {
17
- instanceId: 'wms-a',
18
- spaceId: 'rosarito-site',
19
- modelSpaceId: 'rosarito-site',
20
- locationIds: ['rack-1', 'dock-1'],
21
- equipmentIds: ['fork-1'],
22
- areaRefs: ['bldg-1']
23
- }
24
- ],
25
- representations: [
26
- {
27
- id: 'rep-map',
28
- spaceId: 'rosarito-site',
29
- type: 'map',
30
- polygons: [
31
- { id: 'p1', groupId: 'bldg-1' },
32
- { id: 'p2', targetKind: 'location', targetId: 'rack-1' },
33
- { id: 'p3', targetKind: 'equipment', targetId: 'fork-1' }
34
- ]
35
- }
36
- ],
37
- areasBySpace: { 'rosarito-site': ['bldg-1'] },
38
- boardIds: []
39
- }
40
-
41
- test('정합하면 아무것도 내지 않는다 — 멀쩡한 현장을 시끄럽게 만들지 않는다', () => {
42
- assert.deepEqual(checkSpaceIntegrity(SOUND), [])
43
- })
44
-
45
- test('없는 현장을 가리키는 트윈을 잡는다 — 무대가 사라진 트윈', () => {
46
- const f = checkSpaceIntegrity({
47
- ...SOUND,
48
- instances: [{ ...SOUND.instances[0], spaceId: 'gone-site', modelSpaceId: 'gone-site' }]
49
- })
50
- const hit = f.find(x => x.code === 'twin-space-missing')
51
- assert.ok(hit)
52
- assert.equal(hit.severity, 'broken')
53
- assert.equal(hit.instanceId, 'wms-a')
54
- assert.equal(hit.spaceId, 'gone-site')
55
- })
56
-
57
- test('레지스트리와 model 의 현장이 다르면 잡는다 — 어느 쪽이 사실인지 알 수 없다', () => {
58
- const f = checkSpaceIntegrity({
59
- ...SOUND,
60
- instances: [{ ...SOUND.instances[0], modelSpaceId: 'other-site' }]
61
- })
62
- const hit = f.find(x => x.code === 'twin-space-mismatch')
63
- assert.ok(hit)
64
- assert.equal(hit.severity, 'broken')
65
- assert.equal(hit.params?.registry, 'rosarito-site')
66
- assert.equal(hit.params?.model, 'other-site')
67
- })
68
-
69
- test('현장 없는 트윈은 경고로 낸다 — 뗀 결과일 수 있어 고장은 아니다', () => {
70
- const f = checkSpaceIntegrity({
71
- ...SOUND,
72
- instances: [{ ...SOUND.instances[0], spaceId: undefined, modelSpaceId: undefined }]
73
- })
74
- const hit = f.find(x => x.code === 'twin-without-space')
75
- assert.ok(hit)
76
- assert.equal(hit.severity, 'warn')
77
- })
78
-
79
- test('로케이션이 이 현장에 없는 구역에 소속되어 있으면 잡는다', () => {
80
- const f = checkSpaceIntegrity({
81
- ...SOUND,
82
- instances: [{ ...SOUND.instances[0], areaRefs: ['bldg-1', 'floor-9', 'floor-9'] }]
83
- })
84
- const hit = f.find(x => x.code === 'location-area-missing')
85
- assert.ok(hit)
86
- assert.equal(hit.params?.count, 1, '중복은 한 번만 센다')
87
- assert.equal(hit.params?.areas, 'floor-9')
88
- })
89
-
90
- test('폴리곤이 없는 구역을 가리키면 잡는다 — 그 도형은 아무것도 보여 주지 않는다', () => {
91
- const f = checkSpaceIntegrity({
92
- ...SOUND,
93
- representations: [{ ...SOUND.representations[0], polygons: [{ id: 'p1', groupId: 'ghost-area' }] }]
94
- })
95
- const hit = f.find(x => x.code === 'polygon-area-missing')
96
- assert.ok(hit)
97
- assert.equal(hit.severity, 'broken')
98
- assert.equal(hit.representationId, 'rep-map')
99
- assert.equal(hit.params?.areaId, 'ghost-area')
100
- })
101
-
102
- test('폴리곤이 이 현장의 어느 트윈에도 없는 로케이션을 가리키면 잡는다 — 트윈을 옮긴 뒤 남는 모양', () => {
103
- const f = checkSpaceIntegrity({
104
- ...SOUND,
105
- instances: [{ ...SOUND.instances[0], spaceId: 'other-site', modelSpaceId: 'other-site' }],
106
- spaces: [...SOUND.spaces, { spaceId: 'other-site' }]
107
- })
108
- const hits = f.filter(x => x.code === 'polygon-target-missing')
109
- assert.equal(hits.length, 2, '로케이션과 설비 둘 다 끊긴다')
110
- assert.equal(hits[0].severity, 'broken')
111
- assert.equal(hits.find(h => h.params?.kind === 'equipment')?.params?.targetId, 'fork-1')
112
- })
113
-
114
- test('설비 바인딩을 로케이션 목록으로 판정하지 않는다 — 종류를 섞으면 거짓 경보가 난다', () => {
115
- const f = checkSpaceIntegrity({
116
- ...SOUND,
117
- representations: [
118
- { ...SOUND.representations[0], polygons: [{ id: 'p3', targetKind: 'equipment', targetId: 'rack-1' }] }
119
- ]
120
- })
121
- assert.ok(f.find(x => x.code === 'polygon-target-missing'), '로케이션 id 를 설비로 가리키면 끊긴 것이다')
122
- })
123
-
124
- test('대표 표현이 이 현장의 것이 아니면 잡는다', () => {
125
- const f = checkSpaceIntegrity({
126
- ...SOUND,
127
- spaces: [{ spaceId: 'rosarito-site', primaryRepresentationId: 'rep-elsewhere' }]
128
- })
129
- const hit = f.find(x => x.code === 'primary-representation-missing')
130
- assert.ok(hit)
131
- assert.equal(hit.severity, 'broken')
132
- })
133
-
134
- test('보드 표현이 보드를 가리키지 않으면 잡는다', () => {
135
- const f = checkSpaceIntegrity({
136
- ...SOUND,
137
- representations: [{ id: 'rep-board', spaceId: 'rosarito-site', type: 'board', boardId: null, polygons: [] }],
138
- spaces: [{ spaceId: 'rosarito-site', primaryRepresentationId: 'rep-board' }]
139
- })
140
- const hit = f.find(x => x.code === 'board-representation-unbound')
141
- assert.ok(hit)
142
- assert.equal(hit.params?.boardId, '—')
143
- })
144
-
145
- test('없는 보드를 가리키는 보드 표현도 잡는다', () => {
146
- const f = checkSpaceIntegrity({
147
- ...SOUND,
148
- representations: [{ id: 'rep-board', spaceId: 'rosarito-site', type: 'board', boardId: 'gone', polygons: [] }],
149
- spaces: [{ spaceId: 'rosarito-site', primaryRepresentationId: 'rep-board' }],
150
- boardIds: ['other-board']
151
- })
152
- assert.ok(f.find(x => x.code === 'board-representation-unbound'))
153
- })
154
-
155
- test('트윈이 사는데 표현이 없으면 경고한다 — 볼 화면이 없다', () => {
156
- const f = checkSpaceIntegrity({ ...SOUND, representations: [], spaces: [{ spaceId: 'rosarito-site' }] })
157
- const hit = f.find(x => x.code === 'space-without-representation')
158
- assert.ok(hit)
159
- assert.equal(hit.params?.twins, 1)
160
- })
161
-
162
- test('트윈이 없는 빈 현장은 정상이다 — 만들어 두고 아직 안 쓴 현장', () => {
163
- const f = checkSpaceIntegrity({
164
- spaces: [{ spaceId: 'empty-site' }],
165
- instances: [],
166
- representations: [],
167
- areasBySpace: {},
168
- boardIds: []
169
- })
170
- assert.deepEqual(f, [])
171
- })
172
-
173
- test('벤치 사본은 검사 대상이 아니다 — 잠깐 살고 지워지는 사본', () => {
174
- const f = checkSpaceIntegrity({
175
- ...SOUND,
176
- instances: [
177
- ...SOUND.instances,
178
- { instanceId: 'bench-1', spaceId: 'nowhere-site', modelSpaceId: 'else', purpose: 'bench' }
179
- ]
180
- })
181
- assert.deepEqual(f, [], '사본의 어긋남은 세지 않는다')
182
- })
183
-
184
- test('심각한 것이 먼저 온다 — 사람이 무엇부터 볼지 정하지 않아도 되게', () => {
185
- const f = sortFindings([
186
- { code: 'twin-without-space', severity: 'warn', message: 'w' },
187
- { code: 'twin-space-missing', severity: 'broken', message: 'b' }
188
- ])
189
- assert.equal(f[0].severity, 'broken')
190
- })
191
-
192
- /*
193
- * ── 어휘가 맞지 않는 트윈 (2026-08-14, EMS 를 붙이며) ────────────────────────
194
- *
195
- * 커널은 모르는 `eventType` 을 버리고 종류별로 센다(`state.unhandled`). 그 수가 0이 아니면 저널은
196
- * 들어오는데 상태가 채워지지 않는 것이고, 화면에는 「정상인데 빈」 트윈으로 보인다.
197
- *
198
- * 이 검사가 지키는 것은 **모른다와 없다의 구별**이다: 정지한 트윈은 확인한 바가 없으므로 세지 않는다.
199
- */
200
- test('담을 줄 모르는 어휘가 들어오는 트윈을 잡는다 — 리비전만 오르는 빈 트윈', () => {
201
- const f = checkSpaceIntegrity({
202
- ...SOUND,
203
- instances: [{ ...SOUND.instances[0], unhandled: [{ eventType: 'energy.measured', count: 96 }, { eventType: 'energy.peak', count: 4 }] }]
204
- })
205
- const hit = f.find(x => x.code === 'twin-unhandled-vocabulary')!
206
- assert.ok(hit, '이것을 놓치면 사용자는 커넥터가 잘못 붙은 것을 알 수 없다')
207
- assert.equal(hit.severity, 'warn')
208
- assert.equal(hit.instanceId, 'wms-a', '어느 트윈인지 지목해야 한다')
209
- assert.equal(hit.params?.events, 100, '건수를 합쳐 낸다')
210
- assert.equal(hit.params?.kinds, 2)
211
- assert.match(String(hit.params?.types), /energy\.measured/, '많은 것부터 이름을 낸다')
212
- })
213
-
214
- test('정지한 트윈은 세지 않는다 — 확인하지 않은 것을 정합으로도 결함으로도 세지 않는다', () => {
215
- /* `unhandled` 가 undefined 인 것은 「없다」가 아니라 「모른다」다(런타임이 없으면 알 수 없다). */
216
- const f = checkSpaceIntegrity(SOUND)
217
- assert.equal(f.find(x => x.code === 'twin-unhandled-vocabulary'), undefined)
218
- })
219
-
220
- test('빈 배열은 결함이 아니다 — 받은 것이 없으면 들어온 것이 없다', () => {
221
- const f = checkSpaceIntegrity({ ...SOUND, instances: [{ ...SOUND.instances[0], unhandled: [] }] })
222
- assert.equal(f.find(x => x.code === 'twin-unhandled-vocabulary'), undefined)
223
- })
@@ -1,66 +0,0 @@
1
- /*
2
- * ★ 표현을 묶고 가른다 — 목록에 나올 것과 다른 표현에서 열리는 것.
3
- *
4
- * ── 왜 (2026-08-27 · 사용자 지시, UX 레인 요청) ─────────────────────────────
5
- * 「각 표현이 많아지게 되면 관리가 어려우니, 그루핑과 정렬 기능도 필요하다.」
6
- * 「표현 인덱스에 포함될 표현과 팝업 같은 파생 표현이 구분될 수 있어야 한다.」
7
- *
8
- * 칸 둘을 더한다.
9
- *
10
- * group 자유 문자열. 묶는 축이 현장마다 다르다(건물별·용도별·층별)
11
- * role index(기본) · derived. 닫힌 목록이다
12
- */
13
- import { test } from 'node:test'
14
- import assert from 'node:assert/strict'
15
- import { readFileSync } from 'node:fs'
16
- import { join } from 'node:path'
17
- import { REPRESENTATION_ROLES } from '../server/service/twin-space/representation-role.js'
18
-
19
- const dir = (...p: string[]) => join(import.meta.dirname, '..', 'server', 'service', 'twin-space', ...p)
20
- const entity = readFileSync(dir('twin-space-representation.ts'), 'utf8')
21
- const resolver = readFileSync(dir('twin-space-resolver.ts'), 'utf8')
22
-
23
- test('★ 묶는 이름은 자유 문자열이다 — 묶는 축이 현장마다 다르다', () => {
24
- assert.match(entity, /group\?: string/, 'group 칸이 있어야 한다')
25
- /* 고정 목록으로 두면 현장마다 맞지 않는다 — 값을 검사하지 않는다. */
26
- assert.doesNotMatch(resolver, /GROUPS as readonly|REPRESENTATION_GROUPS/, '묶는 이름을 목록으로 닫지 않는다')
27
- })
28
-
29
- test('★ 그룹 자체의 순서는 칸으로 두지 않는다 — 그 그룹의 최소 seq 가 그 순서다', () => {
30
- /* 칸을 두면 그룹 이름을 바꿀 때 두 곳을 맞춰야 하고, 어긋나면 목록 순서가 오류 없이 달라진다. */
31
- assert.doesNotMatch(entity, /groupSeq|groupOrder/, '그룹 순서 칸을 만들지 않는다')
32
- })
33
-
34
- test('★ role 은 닫힌 목록이고, 모르는 값은 저장하지 않는다', () => {
35
- assert.deepEqual([...REPRESENTATION_ROLES], ['index', 'derived'])
36
- /*
37
- * 모르는 값을 그냥 저장하면 화면이 그것을 어느 쪽으로도 그리지 못하고, 그 표현이 목록에서 알리지 않고
38
- * 사라진다. 저장하는 자리에서 거절한다.
39
- */
40
- assert.match(resolver, /REPRESENTATION_ROLES as readonly string\[\]\)\.includes\(role\)/, '닫힌 목록으로 검사한다')
41
- assert.match(resolver, /unknown representation role/, '거절 사유를 말한다')
42
- })
43
-
44
- test('★ 비어 있으면 index 다 — 흔한 쪽을 기본으로 둔다', () => {
45
- assert.match(entity, /role\?: string/, 'role 은 선택 칸이다')
46
- assert.match(entity, /default when absent/, '비어 있을 때의 뜻이 설명에 있어야 한다')
47
- /* 공백만 있는 값은 「없음」과 같다 — 그것을 값으로 저장하면 검사를 지나며 뜻이 없는 값이 남는다. */
48
- assert.match(resolver, /String\(rep\.role\)\.trim\(\) === ''/, '공백만 있는 값은 비운다')
49
- assert.match(resolver, /String\(rep\.group\)\.trim\(\) === ''/, '묶는 이름도 같다')
50
- })
51
-
52
- test('★ isPrimary 에 얹지 않는다 — 다른 질문에 답하는 칸이다', () => {
53
- /*
54
- * `isPrimary` 는 「현장 현황에 나올 하나」를 정한다. `role` 은 「목록에 나오나」를 정한다. 한 칸이
55
- * 두 질문에 답하면 한쪽을 고칠 때 다른 쪽이 오류 없이 바뀐다.
56
- */
57
- assert.match(entity, /isPrimary\?: boolean/, 'isPrimary 는 그대로 있어야 한다')
58
- assert.match(entity, /Kept separate from isPrimary/, '왜 따로 두는지 설명에 있어야 한다')
59
- })
60
-
61
- test('★ 조회가 두 값을 실어 보낸다 — 화면이 묶을 수 있어야 한다', () => {
62
- assert.match(resolver, /group: rep\.group, role: rep\.role/, '표현 목록에 두 값을 싣는다')
63
- assert.match(resolver, /order: \{ group: 'ASC', seq: 'ASC' \}/, '묶은 이름 다음에 순서로 정렬한다')
64
- /* 빈 값이 앞에 오는지 뒤에 오는지는 드라이버마다 다르다 — 그 순서에 기대지 않는다. */
65
- assert.match(resolver, /드라이버마다\s*\n?\s*\*?\s*다르므로/, '그 순서에 기대지 않는다는 것을 적어 둔다')
66
- })
@@ -1,55 +0,0 @@
1
- /*
2
- * ★ 현장으로 물으면 멈춘 트윈의 기록도 나온다 — 저널은 기록이고, 지금 도는지는 다른 축이다.
3
- *
4
- * ── 무엇이 났나 (2026-08-28 실측) ───────────────────────────────────────────
5
- * 대상 해소에 `running` 조건이 있었다. 그래서 현장으로 물으면 멈춘 트윈이 대상에서 빠지고, 화면은
6
- * 「기록이 없습니다」라고 말했다 — 저널에는 있는데.
7
- *
8
- * twinEventList(instanceId: "ems-plant-1") 1,792건
9
- * twinEventList(spaceId: "ems-plant-1-site") 0건 ← 같은 트윈 · 같은 도메인
10
- *
11
- * 규모로 보면 예외가 아니라 기본값이었다: 등록된 트윈 30개 중 도는 것 2개, 멈춘 것 28개.
12
- *
13
- * ── 왜 지웠나 ──────────────────────────────────────────────────────────────
14
- * 옛 주석이 대는 이유(「벤치 사본은 사용자가 보는 현장이 아니다」)는 벤치 제외만 설명한다. `running` 에는
15
- * 근거가 적혀 있지 않았다. 그리고 바로 다음 줄이 반대 원칙을 적어 두었다 — 「정지·비등록이어도 저널은
16
- * 남아 있을 수 있다」. 그 원칙이 현장 경로에만 적용되지 않고 있었다.
17
- */
18
- import { test } from 'node:test'
19
- import assert from 'node:assert/strict'
20
- import { readFileSync } from 'node:fs'
21
- import { join } from 'node:path'
22
-
23
- const KPI = join(import.meta.dirname, '..', 'server', 'engine', 'kpi-query.ts')
24
- const src = readFileSync(KPI, 'utf8')
25
-
26
- /** 대상을 고르는 그 한 줄만 떼어 본다. */
27
- const targetLine = (() => {
28
- const from = src.indexOf('async function resolveTargets')
29
- const body = src.slice(from, from + 1200)
30
- const m = /: list\.filter\(\(x: any\) => [^\n]+\)/.exec(body)
31
- return m?.[0] ?? ''
32
- })()
33
-
34
- test('★ 현장 경로가 「지금 도는가」로 걸러내지 않는다', () => {
35
- assert.ok(targetLine, '대상을 고르는 줄을 찾아야 한다')
36
- assert.doesNotMatch(targetLine, /running/, '멈춘 트윈을 현장에서 빼면 화면이 거짓 「없다」를 낸다')
37
- })
38
-
39
- test('벤치 사본은 계속 뺀다 — 그 제외에는 근거가 있다', () => {
40
- /* 부하 시험용 사본은 사용자가 보는 현장이 아니다. 이 제외는 지우지 않는다. */
41
- assert.match(targetLine, /purpose !== 'bench'/)
42
- })
43
-
44
- test('현장과 트윈 두 경로가 같은 원칙을 쓴다 — 저널은 기록이다', () => {
45
- /* 트윈을 지정한 경로는 처음부터 「정지·비등록이어도 저널은 남아 있을 수 있다」였다. */
46
- assert.match(src, /정지·비등록\)? ?지정된 트윈은 그대로 조회한다|정지·비등록/)
47
- /* 왜 지웠는지가 코드에 남아 있어야 한다 — 다음 사람이 성능을 이유로 되넣지 않게. */
48
- assert.match(src, /「지금 도는가」로 걸러내지 않는다/)
49
- assert.match(src, /1,792건/, '무엇을 재서 알았는지 적혀 있어야 한다')
50
- })
51
-
52
- test('★ 「지금 도는 것만」이 필요하면 이름 있는 축으로 받는다 — 여기 숨기지 않는다', () => {
53
- /* 한 칸에 두 물음을 담으면 어느 화면이 무엇을 보는지 아무도 모른다. */
54
- assert.match(src, /\*\*이름 있는 축\*\*으로 받는다/)
55
- })
@@ -1,113 +0,0 @@
1
- /*
2
- * 시뮬 명세 자격 판정 — **"이 예측으로 무엇을 말할 수 있나" 를 숫자로 가른다.**
3
- *
4
- * 배경: 공정 소요가 커널 상수였을 때와 현장 명세로 굴렸을 때가 응답에서 똑같이 "p50 168" 로 보였다.
5
- * 그 둘을 구별하지 못하면 상대 비교용 숫자가 절대 예측처럼 읽힌다.
6
- */
7
- import { test } from 'node:test'
8
- import assert from 'node:assert/strict'
9
-
10
- import { classifySpecCoverage, readSpecCoverage } from '../server/engine/spec-coverage.ts'
11
-
12
- test('전부 기본값이면 상대 비교만 — 절대 시각을 주장할 근거가 없다', () => {
13
- const r = classifySpecCoverage({
14
- operations: [
15
- { kind: 'putaway', duration: 'default' },
16
- { kind: 'pick', duration: 'default' }
17
- ]
18
- })
19
- assert.equal(r!.qualification, 'relative')
20
- assert.equal(r!.declaredDurations, 0)
21
- assert.equal(r!.defaultDurations, 2)
22
- })
23
-
24
- test('전부 선언되면 절대 예측 시도 가능 — 단 정확도는 별개(이름이 capable 이다)', () => {
25
- const r = classifySpecCoverage({
26
- operations: [
27
- { kind: 'cut', duration: 'declared', variability: 'triangular', parameters: ['yield'] },
28
- { kind: 'weld', duration: 'declared', variability: 'uniform' }
29
- ]
30
- })
31
- assert.equal(r!.qualification, 'absolute-capable')
32
- assert.equal(r!.varyingDurations, 2)
33
- })
34
-
35
- test('섞이면 partial — 한쪽만 계산하지된 사실을 감추지 않는다', () => {
36
- const r = classifySpecCoverage({
37
- operations: [
38
- { kind: 'cut', duration: 'declared' },
39
- { kind: 'paint', duration: 'default' }
40
- ]
41
- })
42
- assert.equal(r!.qualification, 'partial')
43
- assert.equal(r!.declaredDurations, 1)
44
- assert.equal(r!.defaultDurations, 1)
45
- })
46
-
47
- test('변동 없는 선언은 varying 0 — 고정값이면 대기·병목이 과소평가된다는 신호', () => {
48
- const r = classifySpecCoverage({ operations: [{ kind: 'cut', duration: 'declared' }] })
49
- assert.equal(r!.varyingDurations, 0)
50
- const c = classifySpecCoverage({ operations: [{ kind: 'cut', duration: 'declared', variability: 'constant' }] })
51
- assert.equal(c!.varyingDurations, 0, 'constant 는 변동이 아니다')
52
- })
53
-
54
- test('관측된 작업이 없으면 판정하지 않는다 — 모름을 relative 로 단정하지 않는다', () => {
55
- assert.equal(classifySpecCoverage({ operations: [] }), undefined)
56
- assert.equal(classifySpecCoverage({} as any), undefined)
57
- })
58
-
59
- test('커널이 보고 API 를 갖지 않으면 undefined — "전부 기본값" 이라 단정하지 않는다', () => {
60
- assert.equal(readSpecCoverage({}), undefined)
61
- assert.equal(readSpecCoverage(undefined), undefined)
62
- })
63
-
64
- test('커널 보고가 오류를 내어도 예측을 깨지 않는다', () => {
65
- assert.equal(readSpecCoverage({ specCoverage: () => { throw new Error('boom') } }), undefined)
66
- })
67
-
68
- test('커널 보고를 그대로 분류한다 — 카운트를 다시 세지 않고 준 값을 존중', () => {
69
- const r = readSpecCoverage({
70
- specCoverage: () => ({
71
- operations: [{ kind: 'cut', duration: 'declared', parameters: ['yield'] }],
72
- declaredDurations: 1,
73
- defaultDurations: 0
74
- })
75
- })
76
- assert.equal(r!.qualification, 'absolute-capable')
77
- assert.deepEqual(r!.operations[0].parameters, ['yield'])
78
- })
79
-
80
- /* ── 실측이 들어오면 자격이 한 칸 올라간다 ─────────────────────────────── */
81
-
82
- test('전부 이력에서 온 소요면 calibrated — 선언은 사람이 적은 값, 이것은 일어난 값', () => {
83
- const r = classifySpecCoverage({
84
- operations: [
85
- { kind: 'putaway', duration: 'measured' },
86
- { kind: 'pick', duration: 'measured' }
87
- ]
88
- })
89
- assert.equal(r!.qualification, 'calibrated')
90
- assert.equal(r!.measuredDurations, 2)
91
- })
92
-
93
- test('실측과 선언이 섞이면 absolute-capable — 상수가 없으면 시각을 말할 수 있다', () => {
94
- const r = classifySpecCoverage({
95
- operations: [
96
- { kind: 'putaway', duration: 'measured' },
97
- { kind: 'cut', duration: 'declared' }
98
- ]
99
- })
100
- assert.equal(r!.qualification, 'absolute-capable')
101
- })
102
-
103
- test('상수가 하나라도 섞이면 partial — 실측이 있어도 감추지 않는다', () => {
104
- const r = classifySpecCoverage({
105
- operations: [
106
- { kind: 'putaway', duration: 'measured' },
107
- { kind: 'pick', duration: 'default' }
108
- ]
109
- })
110
- assert.equal(r!.qualification, 'partial')
111
- assert.equal(r!.measuredDurations, 1)
112
- assert.equal(r!.defaultDurations, 1)
113
- })
@@ -1,95 +0,0 @@
1
- /*
2
- * ★ 단계 판정 — **체크리스트가 아니라 증거로 센다.**
3
- *
4
- * 이 테스트가 지키는 것:
5
- * ① **「모른다」는 달성이 아니다.** 계측되지 않은 신호(`null`)를 0 으로 대체하면 「반출 0건」과
6
- * 「반출을 세지 않았다」가 같아진다. 배선하지 않은 계측으로 단계를 주장할 길을 남기지 않는다.
7
- * ② **반출을 세었는데 없으면 라이브가 아니다.** 되풀어 읽는 스냅샷은 원리적으로 반출을 못 낸다 —
8
- * 이 판별식이 폴링을 「실시간」이라 부르는 것을 막는다.
9
- * ③ **선언이 비면 예측이 아니다.** 커널 기본값 위에 선 숫자도 화면에서는 예측처럼 보인다.
10
- * ④ **앞을 건너뛸 수 없다.** 뒤 단계는 자기 조건을 따지지 않고 `prerequisite` 으로 막는다.
11
- */
12
- import { test } from 'node:test'
13
- import assert from 'node:assert/strict'
14
-
15
- import { assessStagePath, forbiddenClaims, type StageEvidence } from '../server/engine/stage-path.ts'
16
-
17
- /** 전부 달성한 증거 — 각 시험은 여기서 한 축만 무너뜨린다(무엇이 판정을 바꿨는지 분명해진다). */
18
- const full = (): StageEvidence => ({
19
- locationCount: 12,
20
- itemCount: 340,
21
- masterWarnings: 3,
22
- liveIngestTotal: 1200,
23
- removalsObserved: 17,
24
- forecastRan: true,
25
- specCoverage: { declared: 6, total: 8 },
26
- actuateCapability: true,
27
- correlatedEffectObserved: 2
28
- })
29
-
30
- test('전부 증거가 있으면 폐루프까지 도달하고 금지 표현이 없다', () => {
31
- const p = assessStagePath(full())
32
- assert.deepEqual(p.stages.map(s => s.achieved), [true, true, true, true])
33
- assert.equal(p.reached, 'closed-loop')
34
- assert.equal(p.next, null)
35
- assert.deepEqual(forbiddenClaims(p), [])
36
- })
37
-
38
- test('못 옮긴 값을 세지 않았으면 구조도 달성이 아니다 — 0 이라고 우기지 않는다', () => {
39
- const p = assessStagePath({ ...full(), masterWarnings: null })
40
- const s1 = p.stages[0]
41
- assert.equal(s1.achieved, false)
42
- assert.deepEqual(s1.unmeasured, ['master-warnings'])
43
- assert.deepEqual(s1.blockedBy, [], '자리와 물품은 있으므로 막힌 것이 아니라 모르는 것이다')
44
- assert.equal(p.reached, null, '첫 칸을 못 밟았으면 서 있는 칸이 없다')
45
- })
46
-
47
- test('못 옮긴 값이 3건이어도 구조는 달성이다 — 요구는 「없다」가 아니라 「말할 수 있다」', () => {
48
- assert.equal(assessStagePath({ ...full(), masterWarnings: 3 }).stages[0].achieved, true)
49
- assert.equal(assessStagePath({ ...full(), masterWarnings: 0 }).stages[0].achieved, true)
50
- })
51
-
52
- test('반출을 세었는데 0 이면 라이브가 아니다 — 스냅샷 되풀어 읽기의 징표', () => {
53
- const p = assessStagePath({ ...full(), removalsObserved: 0 })
54
- assert.equal(p.stages[1].achieved, false)
55
- assert.deepEqual(p.stages[1].blockedBy, ['no-removal-observed'])
56
- assert.equal(p.reached, 'structure')
57
- assert.ok(forbiddenClaims(p).includes('claim.realtime'), '실시간이라고 말할 수 없다')
58
- })
59
-
60
- test('반출이 계측되지 않으면 「없다」가 아니라 「모른다」로 막힌다', () => {
61
- const p = assessStagePath({ ...full(), removalsObserved: null })
62
- assert.deepEqual(p.stages[1].unmeasured, ['removals'])
63
- assert.deepEqual(p.stages[1].blockedBy, [], '인제스트는 있으므로 막힌 것이 아니다')
64
- })
65
-
66
- test('선언이 비면 예측이 아니다 — 기본값 위에 선 숫자도 숫자로 보인다', () => {
67
- const p = assessStagePath({ ...full(), specCoverage: { declared: 0, total: 8 } })
68
- assert.equal(p.stages[2].achieved, false)
69
- assert.deepEqual(p.stages[2].blockedBy, ['declarations-empty'])
70
- assert.equal(p.reached, 'live')
71
- assert.ok(forbiddenClaims(p).includes('claim.prediction'))
72
- })
73
-
74
- test('접수만으로는 폐루프가 아니다 — 효과가 관측으로 돌아와야 닫힌다', () => {
75
- const p = assessStagePath({ ...full(), correlatedEffectObserved: 0 })
76
- assert.deepEqual(p.stages[3].blockedBy, ['effect-not-observed'])
77
- assert.equal(p.reached, 'forecast')
78
- })
79
-
80
- test('앞이 막히면 뒤는 자기 조건을 따지지 않는다 — 순서를 건너뛸 수 없다', () => {
81
- const p = assessStagePath({ ...full(), locationCount: 0, itemCount: 0 })
82
- assert.deepEqual(p.stages[0].blockedBy, ['no-locations', 'no-items'])
83
- for (const later of p.stages.slice(1)) assert.deepEqual(later.blockedBy, ['prerequisite'])
84
- assert.deepEqual(p.next, { stage: 'structure', blockedBy: ['no-locations', 'no-items'], unmeasured: [] })
85
- })
86
-
87
- test('다음 걸음은 목록이 아니라 하나다', () => {
88
- const p = assessStagePath({ ...full(), removalsObserved: 0, specCoverage: null, actuateCapability: false })
89
- assert.equal(p.next?.stage, 'live', '뒤쪽 결손을 함께 들이밀지 않는다')
90
- })
91
-
92
- test('비직렬 수량 물품만 있어도 구조는 달성이다 — 식품·화학은 개수로 오지 않는다', () => {
93
- /* itemCount 는 「자리에 놓인 물품 수」이고, 비직렬 수량 물품(subLot)도 한 줄로 센다. */
94
- assert.equal(assessStagePath({ ...full(), itemCount: 1 }).stages[0].achieved, true)
95
- })