@things-factory/headless-twin 10.1.278 → 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,101 +0,0 @@
1
- /*
2
- * A refusal has to name which envelope was refused.
3
- *
4
- * ── What this catches, and why the existing test did not (2026-09-08) ──────
5
- * `rejectedForCaller` pairs a refused record with its envelope by **object identity** — value
6
- * comparison would let two identically shaped records take each other's id. Its own test
7
- * hands the same object to both sides, so it passes and proves the pairing works.
8
- *
9
- * It does not prove anything about the real path, because in between
10
- * `ingestCanonicalRecords` builds `{ ...r, eventTime, sourceType }` — **a new object**. The
11
- * refusal then carries that copy, the copy is not in the identity map, and the response comes
12
- * back as `{ record, errors }` with no `eventId`:
13
- *
14
- * sent {"eventId":"probe-eventid-check-001","record":{"kind":"transformation"}}
15
- * back rejected: [{ record: {kind:"transformation", sourceType:"twin"}, errors:[…] }]
16
- *
17
- * The sending side cannot mark the row that was refused, so it cannot settle the batch and
18
- * its queue stops moving — measured on the plant side as 719 envelopes pending with nothing
19
- * lost and nothing advancing.
20
- *
21
- * So this test walks the seam the way a real envelope does: through the ingest that makes the
22
- * copy, then through the pairing. That is the step a pure test of either half cannot take.
23
- */
24
- import { test } from 'node:test'
25
- import assert from 'node:assert/strict'
26
-
27
- import { ingestCanonicalRecords } from '../server/engine/canonical-ingest.js'
28
- import { rejectedForCaller } from '../server/service/reference/hook-rejected.js'
29
-
30
- const AT = '2026-09-08T02:00:00.000Z'
31
-
32
- /** A transformation the kernel refuses — no inputs, no outputs, no bizStep. */
33
- const REFUSED = { kind: 'transformation' } as any
34
-
35
- test('a refusal names the envelope it came from, after ingest has copied the record', () => {
36
- /* The envelope as the hook holds it: the record object, and the id that identifies its row. */
37
- const items = [{ record: REFUSED, eventId: 'evt-refused-1' }]
38
-
39
- const result = ingestCanonicalRecords(
40
- items.map(i => i.record),
41
- 'test-domain',
42
- AT
43
- ) as any
44
-
45
- assert.equal(result.rejected.length, 1, 'the kernel refuses this record')
46
-
47
- const forCaller = rejectedForCaller(result.rejected, items)
48
-
49
- assert.deepEqual(
50
- forCaller.map((r: any) => r.eventId),
51
- ['evt-refused-1'],
52
- 'the refusal carries the envelope id — without it the sender cannot mark the row'
53
- )
54
- })
55
-
56
- test('two refused records of the same shape keep their own ids', () => {
57
- /*
58
- * This is why the pairing is by identity and not by value. Both records look the same, and
59
- * value comparison would hand the first id to both — the sender would mark one row twice
60
- * and leave the other pending forever.
61
- */
62
- const a = { kind: 'transformation' } as any
63
- const b = { kind: 'transformation' } as any
64
- const items = [
65
- { record: a, eventId: 'evt-a' },
66
- { record: b, eventId: 'evt-b' }
67
- ]
68
-
69
- const result = ingestCanonicalRecords(
70
- items.map(i => i.record),
71
- 'test-domain',
72
- AT
73
- ) as any
74
- const forCaller = rejectedForCaller(result.rejected, items)
75
-
76
- assert.deepEqual(
77
- forCaller.map((r: any) => r.eventId).sort(),
78
- ['evt-a', 'evt-b'],
79
- 'each refusal keeps its own id'
80
- )
81
- })
82
-
83
- test('an envelope with no id still says what was refused', () => {
84
- /*
85
- * A connector that does not number its envelopes gets the record back instead. An empty id
86
- * would be worse than none: the sender would look for a row, find nothing, and treat the
87
- * batch as understood.
88
- */
89
- const items = [{ record: REFUSED }]
90
-
91
- const result = ingestCanonicalRecords(
92
- items.map(i => i.record),
93
- 'test-domain',
94
- AT
95
- ) as any
96
- const forCaller = rejectedForCaller(result.rejected, items) as any[]
97
-
98
- assert.equal(forCaller.length, 1)
99
- assert.equal('eventId' in forCaller[0], false, 'no id is sent rather than an empty one')
100
- assert.ok('record' in forCaller[0], 'the record is sent so a person can see what was dropped')
101
- })
@@ -1,89 +0,0 @@
1
- /*
2
- * ★ 트윈이 첫날의 이름에 갇혀 있었다 — 바꿀 문이 없었다.
3
- *
4
- * 이름은 처음 세울 때 한 번 정해지고(`provision`) 다시 읽기는 건드리지 않는다. 그 자체는 안전하다 —
5
- * 사람이 붙인 이름을 연결이 덮어쓰면 안 된다. 그런데 그래서 첫날 이름에서 벗어날 길이 없었다.
6
- *
7
- * 실제로 그런 일이 났다(2026-08-25 · 태양광 발전소). 커넥터가 처음 아는 이름이 연결된 시스템의
8
- * 코드뿐이었다.
9
- *
10
- * 현장 이름 호현에너지
11
- * 트윈 이름 ES202307202202 ← 화면의 트윈 목록에 이렇게 보였다
12
- *
13
- * 뒤에 사람이 부르는 이름이 어디 있는지 알아내 커넥터를 고쳤는데, 트윈 이름은 그대로였다. 남은
14
- * 유일한 길이 트윈을 지우고 다시 세우는 것이었고, 그러면 그날 실제 발전소에서 받은 246건이
15
- * 사라진다 — **이름 하나 때문에 사실을 버리는 선택**이다.
16
- *
17
- * 연결된 시스템을 따라가는 트윈에서는 이름이 나중에 좋아진다. 커넥터가 나아질 때마다 나는 일이다.
18
- *
19
- * 이 테스트는 소스를 전수 조회해 규율을 지킨다(실제 뮤테이션은 DB 와 도메인 맥락이 필요하다).
20
- */
21
- import { test } from 'node:test'
22
- import assert from 'node:assert/strict'
23
- import { readFileSync } from 'node:fs'
24
- import { join } from 'node:path'
25
-
26
- const FILE = join(import.meta.dirname, '..', 'server', 'service', 'twin-lifecycle', 'twin-lifecycle-mutation.ts')
27
- const src = readFileSync(FILE, 'utf8')
28
- const body = (() => {
29
- const at = src.indexOf('async renameTwinInstance')
30
- assert.ok(at > 0, '이름을 바꾸는 문이 있어야 한다')
31
- /*
32
- * **주석을 걷고 본다.** 이 조각은 다음 문(`deleteTwinInstance`)의 머리 주석까지 품는데, 그 주석은
33
- * 삭제가 왜 `TwinEngine.remove` 를 부르는지 설명한다. 걷지 않으면 그 산문이 세어져, 이름 바꾸기가
34
- * 런타임을 건드린다고 읽힌다 — 실제로 그렇게 빨개졌다. 세는 것은 코드지 그 옆의 글이 아니다.
35
- */
36
- return src
37
- .slice(at, src.indexOf('async deleteTwinInstance'))
38
- .replace(/\/\*[\s\S]*?\*\//g, '')
39
- .replace(/\/\/[^\n]*/g, '')
40
- })()
41
-
42
- test('★ 이름을 바꾸는 문이 있다 — 없어서 지우고 다시 세우는 것이 유일한 길이었다', () => {
43
- assert.ok(/@Mutation/.test(src.slice(0, src.indexOf('async renameTwinInstance'))))
44
- assert.ok(/@Arg\('instanceId'\)/.test(body))
45
- assert.ok(/@Arg\('name'\)/.test(body))
46
- })
47
-
48
- test('★ 빈 이름은 받지 않는다 — 지우는 것과 바꾸는 것은 다른 일이다', () => {
49
- assert.ok(/\.trim\(\)/.test(body), '앞뒤 공백은 이름이 아니다')
50
- assert.ok(/if \(!next\) throw/.test(body), '빈 값이면 거절한다')
51
- /* 빈 이름을 받아 두면 그 트윈은 목록에서 식별자만 남는데, 그것을 「바꿨다」로 보고하면 거짓이다. */
52
- assert.ok(/left as it was/.test(body), '무엇도 바뀌지 않았다는 것을 말한다')
53
- })
54
-
55
- test('★ 남의 도메인 트윈은 바꾸지 못한다 — 테넌트 격리', () => {
56
- assert.ok(/where: \{ domain: \{ id: domainId \}, instanceId \}/.test(body), '도메인으로 좁혀 찾는다')
57
- assert.ok(/unknown twin/.test(body), '없으면 이유를 말한다')
58
- })
59
-
60
- test('바꾸지 않은 경우를 바꿨다고 말하지 않는다', () => {
61
- assert.ok(/changed: false/.test(body), '같은 이름이면 changed 를 false 로 낸다')
62
- assert.ok(/previous/.test(body), '무엇에서 무엇으로 바뀌었는지 함께 낸다')
63
- })
64
-
65
- test('바꾼 사람을 남긴다 — 이름은 사람이 하는 선언이다', () => {
66
- assert.ok(/updater: context\.state\.user/.test(body))
67
- })
68
-
69
- test('이름만 바꾼다 — 트윈을 멈추거나 다시 읽지 않는다', () => {
70
- /*
71
- * 도는 런타임은 식별자로 동작하고 이름을 쓰지 않는다. 정지·기동을 끼우면 그 사이의 사실이 어디로
72
- * 갔는지 설명해야 하는데, 이름 때문에 그 값을 치를 이유가 없다.
73
- */
74
- assert.ok(!/TwinEngine\.(stop|start|remove|resync)/.test(body), '런타임을 건드리지 않는다')
75
- assert.ok(!/adoptStructure|reprovision/.test(body), '구조를 다시 읽지 않는다')
76
- })
77
-
78
- test('연결된 시스템이 이름을 덮어쓰지는 않는다 — 다시 읽기는 그대로다', () => {
79
- /*
80
- * 「사람이 손대지 않았으면 따라간다」가 옳아 보이지만, 그러려면 「손댔다」는 표시를 새로 만들어야
81
- * 한다. 이름 하나 때문에 지기에 무거운 빚이므로 사람이 바꾸는 길만 낸다. 그 결정을 여기서 고정한다.
82
- *
83
- * 이름을 정하는 자리는 **처음 세울 때 하나**다. 그 수가 늘면 다시 읽기가 이름을 다시 정하기
84
- * 시작했다는 뜻이고, 그때는 이 결정을 다시 해야 한다.
85
- */
86
- const engine = readFileSync(join(import.meta.dirname, '..', 'server', 'engine', 'twin-engine.ts'), 'utf8')
87
- const places = engine.match(/name: master\.siteName/g) ?? []
88
- assert.equal(places.length, 1, `이름을 정하는 자리가 ${places.length}곳이다 — 처음 세울 때 하나여야 한다`)
89
- })
@@ -1,52 +0,0 @@
1
- /*
2
- * ★ 소스 시험이 형제 모듈을 부를 수 있게 한다 — **`operato-twin` 의 같은 규칙을 이 패키지에도 둔다** — **`.js` 로 적힌 상대 경로를 `.ts` 로 되짚는다.**
3
- *
4
- * ── 무엇이 서고 있었나 (2026-08-22) ─────────────────────────────────────────
5
- * 이 패키지의 `npm test` 는 `node --test test/*.test.ts` 로 **소스를 그대로 실행**한다. 그런데 서버
6
- * 소스는 tsc 로 빌드되는 코드이므로 상대 import 를 `'./x.js'` 로 적는다(그것이 빌드 산출물에서 맞는
7
- * 경로다). 타입만 지우는 실행은 그 `.js` 를 `.ts` 로 바꿔 주지 않는다.
8
- *
9
- * 그래서 **소스 모듈이 형제 모듈을 값으로 참조하는 순간** 그 모듈 그래프를 부르는 시험이 전부 선다.
10
- * 실측으로 하루에 네 종류가 이 벽에 걸렸다: `identity/namespace.js`(정체성 이름공간) ·
11
- * `engine/log.js`(로그 문) · `isa95-coverage.js`(적합성 판정) · `journal-count.js`(저널 세기). 늘 같은 오류다.
12
- *
13
- * Cannot find module '…/server/identity/namespace.js' imported from '…/templates/wms-unit-load.ts'
14
- *
15
- * ── 왜 이 방식인가 ──────────────────────────────────────────────────────────
16
- * 고르던 길이 둘 있었다.
17
- *
18
- * ① 그 시험들을 **빌드 산출물**(`dist-server`)로 돌린다 — 이 패키지에 전례가 있다. 그러나 시험마다
19
- * 그 배선을 적어야 하고, 걸리는 시험이 늘 때마다 같은 일을 다시 한다. 그리고 산출물이 낡으면
20
- * **고친 코드가 아닌 것이 돌면서 초록으로 보인다.**
21
- * ② 상수를 쓰는 파일 안으로 옮긴다 — 값 참조가 사라지지만 **정본이 흩어진다.** 그것이 이 상수를 한
22
- * 자리에 모은 이유와 정면으로 어긋난다.
23
- *
24
- * 둘 다 증상을 피하는 것이고, 원인은 **해석 규칙 하나**다. 그래서 규칙을 고친다: 상대 경로 `.js` 가
25
- * 없고 같은 이름의 `.ts` 가 있으면 그것을 쓴다. 한 자리에 두므로 걸리는 시험이 늘어도 할 일이 없다.
26
- *
27
- * ── 무엇을 하지 않는가 ─────────────────────────────────────────────────────
28
- * **패키지 이름(`@things-factory/…`)은 손대지 않는다.** 그것은 의존 패키지의 산출물을 가리키는
29
- * 것이고 실제로 `.js` 가 있다. 되짚는 것은 **상대 경로**뿐이고, 그것도 `.ts` 가 실제로 있을 때만이다 —
30
- * 없으면 원래 오류가 그대로 난다(없는 것을 지어내지 않는다).
31
- */
32
- import { registerHooks } from 'node:module'
33
- import { existsSync } from 'node:fs'
34
- import { fileURLToPath, pathToFileURL } from 'node:url'
35
-
36
- registerHooks({
37
- resolve(specifier, context, nextResolve) {
38
- /* 상대 경로의 `.js` 만 본다 — 패키지 이름과 그 밖의 확장자는 그대로 둔다. */
39
- if (!specifier.startsWith('.') || !specifier.endsWith('.js')) return nextResolve(specifier, context)
40
-
41
- try {
42
- return nextResolve(specifier, context)
43
- } catch (err) {
44
- /* 해석이 실패한 그때만 `.ts` 를 본다 — 성공하는 경로의 뜻을 바꾸지 않는다. */
45
- const parent = context?.parentURL
46
- if (!parent) throw err
47
- const asTs = new URL(specifier.slice(0, -3) + '.ts', parent)
48
- if (!existsSync(fileURLToPath(asTs))) throw err
49
- return { url: pathToFileURL(fileURLToPath(asTs)).href, shortCircuit: true, format: 'module-typescript' }
50
- }
51
- }
52
- })
@@ -1,111 +0,0 @@
1
- /*
2
- * **재기동 정책** — 개명(ADR-0029 §2)과 그 규율 둘.
3
- *
4
- * ── 무엇을 바꿨나 ───────────────────────────────────────────────────────────
5
- * `realityMode`(`mirror`·`sim-world`·`sim-experiment`) → `restartPolicy`(`resync`·`resume`·`reset`).
6
- * 「현실이 어디서 오나」는 ADR-0029 가 **원본의 종류**로 옮긴 물음이고, 코드가 이 축으로 실제로 가른 것은
7
- * **재기동 거동 하나**였다 — 그것은 원본의 성질이 아니라 트윈과 자기 과거의 관계다. 그래서 축은 남고
8
- * 이름이 바뀌었다.
9
- *
10
- * ── 지키는 규율 둘 (계획서 §6) ──────────────────────────────────────────────
11
- * ① **모르는 값은 오류를 낸다.** 예전에는 미선언이 알리지 않고 `sim-experiment`(=저널 초기화)로 떨어졌다 — 값이
12
- * 하나 어긋나는 순간 이력을 지우는 길이다. 기본값을 없앴다.
13
- * ② **옛 어휘를 번역하지 않는다.** 번역을 두면 옛 값이 살아남고 다시 저장된다. 저장된 값은 한 번
14
- * 옮기고(데이터 이관), 코드는 새 어휘만 안다 — 다만 무엇으로 옮겨야 하는지는 오류 문장이 말한다.
15
- */
16
- import { test } from 'node:test'
17
- import assert from 'node:assert/strict'
18
- import { readdirSync, readFileSync, statSync } from 'node:fs'
19
- import { fileURLToPath } from 'node:url'
20
- import { join } from 'node:path'
21
-
22
- import { readRestartPolicy, isRestartPolicy, RESTART_POLICIES } from '../server/engine/restart-policy.ts'
23
-
24
- test('셋뿐이다 — 그리고 그 셋을 읽는다', () => {
25
- assert.deepEqual([...RESTART_POLICIES], ['resync', 'resume', 'reset'])
26
- for (const p of RESTART_POLICIES) assert.equal(readRestartPolicy(p, 'test'), p)
27
- assert.equal(readRestartPolicy(' resume ', 'test'), 'resume', '공백은 다듬는다')
28
- })
29
-
30
- test('미선언은 오류를 낸다 — 기본값으로 메우면 저널이 지워지는 길이 열린다', () => {
31
- for (const raw of [undefined, null, '', ' ', 42, {}]) {
32
- assert.throws(() => readRestartPolicy(raw, 'twin "x"'), /twin "x": restart policy/)
33
- }
34
- /* 무엇을 해야 하는지 문장이 말한다 — 코드를 그대로 오류를 내지 않는다. */
35
- try {
36
- readRestartPolicy(undefined, 'twin "x"')
37
- assert.fail('오류를 내어야 한다')
38
- } catch (e: any) {
39
- assert.match(e.message, /resync \| resume \| reset/)
40
- assert.match(e.message, /no default/)
41
- }
42
- })
43
-
44
- test('옛 어휘도 오류를 낸다 — 다만 무엇으로 옮길지 말한다(번역해 주지 않는다)', () => {
45
- const cases: [string, string][] = [
46
- ['mirror', 'resync'],
47
- ['sim-world', 'resume'],
48
- ['sim-experiment', 'reset']
49
- ]
50
- for (const [old, next] of cases) {
51
- try {
52
- readRestartPolicy(old, 'twin "x"')
53
- assert.fail(`${old} 은 오류를 내어야 한다`)
54
- } catch (e: any) {
55
- assert.match(e.message, /old vocabulary/)
56
- assert.match(e.message, new RegExp(`"${next}"`), '옮길 값을 말한다')
57
- }
58
- }
59
- })
60
-
61
- test('묻는 자리도 있다 — 화면·검사는 오류를 내지 않고 판별한다', () => {
62
- assert.equal(isRestartPolicy('resume'), true)
63
- assert.equal(isRestartPolicy('sim-world'), false)
64
- assert.equal(isRestartPolicy(undefined), false)
65
- })
66
-
67
- /*
68
- * ── 옛 어휘가 코드로 되돌아오지 않게 (계획서 §6 의 검사) ────────────────────
69
- * ADR-0034 의 `local-declarations.test.ts` 가 `site*` 에 대해 하는 것과 같은 방식이다. 개명은 저장값·타입·
70
- * 화면에 걸쳐 있어서, 한 곳만 되돌아와도 그 자리가 알리지 않고 다르게 재기동한다.
71
- */
72
- const OLD_TOKENS = [/\brealityMode\b/, /\bRealityMode\b/, /'sim-world'/, /'sim-experiment'/, /DEFAULT_REALITY_MODE/]
73
-
74
- function sources(root: string): { file: string; src: string }[] {
75
- const base = fileURLToPath(new URL(root, import.meta.url))
76
- const out: { file: string; src: string }[] = []
77
- const walk = (dir: string) => {
78
- for (const name of readdirSync(dir)) {
79
- if (name === 'node_modules' || name.startsWith('dist')) continue
80
- const path = join(dir, name)
81
- if (statSync(path).isDirectory()) { walk(path); continue }
82
- if (name.endsWith('.ts')) out.push({ file: path.slice(base.length + 1), src: readFileSync(path, 'utf-8') })
83
- }
84
- }
85
- walk(base)
86
- return out
87
- }
88
-
89
- test('옛 어휘가 코드에 없다 — 이력을 설명하는 주석만 예외다', () => {
90
- const offenders: string[] = []
91
- for (const { file, src } of [...sources('../server'), ...sources('../test')]) {
92
- /* 이력 설명(「예전에는 …」)과 이관 안내(restart-policy.ts)는 남아야 한다 — 그것이 개명의 근거다. */
93
- if (file.endsWith('restart-policy.ts') || file.endsWith('restart-policy.test.ts')) continue
94
- for (const line of src.split('\n')) {
95
- const isComment = /^\s*(\*|\/\/|\/\*)/.test(line)
96
- if (isComment) continue
97
- if (OLD_TOKENS.some(re => re.test(line))) offenders.push(`${file}: ${line.trim().slice(0, 80)}`)
98
- }
99
- }
100
- assert.deepEqual(offenders, [], `옛 어휘가 코드로 돌아왔다:\n${offenders.join('\n')}`)
101
- })
102
-
103
- test('기본값 상수가 없다 — 미선언을 우리가 고르지 않는다', () => {
104
- const engine = readFileSync(fileURLToPath(new URL('../server/engine/twin-engine.ts', import.meta.url)), 'utf-8')
105
- const code = engine
106
- .split('\n')
107
- .filter(line => !/^\s*(\*|\/\/|\/\*)/.test(line))
108
- .join('\n')
109
- assert.equal(/DEFAULT_RESTART_POLICY/.test(code), false, '기본값 상수가 되살아나면 미선언이 다시 들어온 것이 없어진다')
110
- assert.match(code, /readRestartPolicy\(/, '읽는 자리는 엄격한 리더를 지난다')
111
- })
@@ -1,83 +0,0 @@
1
- /*
2
- * 다시 읽기가 **자기 사이트**를 찾는가 — 사이트가 여럿인 참조에서 온 트윈의 재동기.
3
- *
4
- * ── 무엇이 났나 (2026-08-18 실측) ───────────────────────────────────────────
5
- * `resyncTwin` 이 「reference "ems-gw-live" no longer reports this site」로 거절했다. 사이트는 멀쩡히
6
- * 있었다 — 코드가 **다른 것을 견주고** 있었다: `origin.source` 는 레퍼런스 등록 이름(그 참조의 사이트
7
- * 전부에 같다)이고 `master.source` 는 사이트별 인스턴스 id 다. 그래서 사이트가 여럿인 참조에서 온
8
- * 트윈은 전부 재동기가 불가했고, 오류 문장은 원인을 참조 쪽으로 잘못 가리켰다(내가 그 문장을 읽고
9
- * 커넥터를 의심했다).
10
- *
11
- * 고친 뒤의 규율: ① 가져올 때 사이트 정체를 남긴다 ② 다시 읽기는 그 사이트로 곧장 간다 ③ 기억이 없는
12
- * 옛 트윈은 마스터의 정체(=인스턴스 id)로 찾는다 ④ 어느 쪽도 못 찾으면 **첫 사이트로 때우지 않는다**.
13
- */
14
- import { test } from 'node:test'
15
- import assert from 'node:assert/strict'
16
- import { readFileSync } from 'node:fs'
17
- import { fileURLToPath } from 'node:url'
18
-
19
- import { pickOriginSite } from '../server/service/reference/reference-master.ts'
20
-
21
- const sites = [{ siteId: 'plant-1' }, { siteId: 'plant-2' }, { siteId: 'plant-3' }]
22
-
23
- test('기억해 둔 사이트로 곧장 간다', () => {
24
- const { site, reason } = pickOriginSite(sites, { siteId: 'plant-2' })
25
- assert.equal(site?.siteId, 'plant-2')
26
- assert.equal(reason, undefined)
27
- })
28
-
29
- test('기억이 없으면 그렇게 말한다 — 첫 사이트로 때우지 않는다', () => {
30
- const { site, reason } = pickOriginSite(sites, {})
31
- assert.equal(site, undefined)
32
- assert.equal(reason, 'no-remembered-site')
33
- })
34
-
35
- test('기억한 사이트가 사라졌으면 다른 사이트로 덮지 않는다', () => {
36
- const { site, reason } = pickOriginSite(sites, { siteId: 'plant-9' })
37
- assert.equal(site, undefined)
38
- assert.equal(reason, 'site-gone', '다른 현장의 구조를 이 트윈에 덮는 것은 오류 없이 틀린 공장이 된다')
39
- })
40
-
41
- test('빈 문자열은 기억이 아니다', () => {
42
- assert.equal(pickOriginSite(sites, { siteId: ' ' }).reason, 'no-remembered-site')
43
- })
44
-
45
- /* 배선이 사라지면 알리지 않고 예전으로 돌아간다 — 소스 모양으로 못 박는다(리졸버는 DB·어댑터를 물고 있다). */
46
- test('다시 읽기는 인스턴스 정체로 견주고, 가져오기는 사이트 정체를 남긴다', () => {
47
- const src = readFileSync(fileURLToPath(new URL('../server/service/reference/reference-resolver.ts', import.meta.url)), 'utf-8')
48
- /* 옛 비교식은 **설명문에 남아 있어야 한다**(왜 고쳤는지가 사라지면 되돌아간다) — 그래서 코드 줄만 본다. */
49
- const code = src
50
- .split('\n')
51
- .filter(line => !/^\s*(\*|\/\*|\/\/)/.test(line))
52
- .join('\n')
53
- assert.match(code, /pickOriginSite\(sites, origin\)/, '기억한 사이트로 곧장 가는 길이 있어야 한다')
54
- assert.match(code, /master\.source === instanceId/, '옛 트윈은 마스터의 정체로 찾는다(참조 이름이 아니다)')
55
- assert.equal(/master\.source === origin\.source/.test(code), false, '참조 이름과 인스턴스 id 를 견주지 않는다')
56
- /* 사이트 정체는 남아 있어야 한다 — 현장 기억(spaceId)이 함께 붙어도 그 사실은 변하지 않는다. */
57
- assert.match(code, /origin: \{ kind: 'reference', source, siteId: site\.siteId/, '가져올 때 사이트 정체를 남긴다')
58
- })
59
-
60
- /*
61
- * ── 다시 읽기가 **현장 소속**을 지킨다 (2026-08-18 실측) ─────────────────────
62
- * 한 현장에 합쳐 둔 EMS 트윈 여덟을 재동기했더니 각자 공간으로 흩어졌다 — 템플릿이 낸 기본 공간으로
63
- * 돌아갔기 때문이다. 들어온 것이 없다: 오류도 경고도 없고, 트윈은 멀쩡히 돌아간다. 그런데 그 순간 **그 현장의
64
- * 값(요금·통화)을 함께 잃는다** — 현장 겹은 소속으로 얹히기 때문이다.
65
- *
66
- * 원인은 origin 이 「어느 현장에 합쳤나」를 기억하지 않은 것이다(구조만 기억했다).
67
- */
68
- test('프로비저닝이 고른 현장을 origin 에 남기고, 다시 읽기가 그것을 따른다', () => {
69
- const src = readFileSync(fileURLToPath(new URL('../server/service/reference/reference-resolver.ts', import.meta.url)), 'utf-8')
70
- const code = src
71
- .split('\n')
72
- .filter(line => !/^\s*(\*|\/\*|\/\/)/.test(line))
73
- .join('\n')
74
- assert.match(code, /kind: 'template', templateId, params: effective, \.\.\.\(spaceId \? \{ spaceId \} : \{\}\)/, '템플릿 트윈이 현장을 기억한다')
75
- assert.match(code, /const keepSpace = origin\.spaceId \|\| inst\.spaceId/, '기억이 없으면 지금 있는 현장을 지킨다')
76
- /* 인자 사이에 재기동 정책이 끼었다(ADR-0029 §2) — 현장을 넘기는 인자는 그대로여야 한다. */
77
- assert.match(code, /keepSpace \? \{ spaceId: keepSpace \} : undefined/, '다시 읽기가 그 현장으로 넣는다')
78
- assert.match(
79
- code,
80
- /readRestartPolicy\(inst\.restartPolicy, `resync of twin/,
81
- '다시 읽기는 그 트윈의 정책을 그대로 지킨다(구조만 새로 그린다)'
82
- )
83
- })
@@ -1,139 +0,0 @@
1
- /*
2
- * ★ **다시 넘길 것인가, 언제인가** — 일꾼의 판단 전부.
3
- *
4
- * ── 왜 이 판단이 필요한가 (2026-09-04) ─────────────────────────────────────
5
- * 승인 직후에 한 번 보내는 것만 있었다. 그래서 **커밋과 발신 사이에 프로세스가 죽으면** 그
6
- * 조치는 `approved` 로 남고 스스로 나가지 않았다. 그리고 실패한 것을 다시 보내는 것은 사람이
7
- * 시켜야 했다.
8
- *
9
- * ── 실패가 다 같지 않다 (2026-09-02 실측) ──────────────────────────────────
10
- * 저쪽 인증 정보가 없어 503 이었던 것(고치면 됨)과 `ITEM-1` 이 400 이었던 것(고쳐도 이 조치로는
11
- * 안 됨)이 같은 모양이었다. 다 다시 하면 없는 자재를 끝없이 두드리고, 다 포기하면 저쪽을 고쳐
12
- * 놓고도 안 나간다.
13
- */
14
- import { test } from 'node:test'
15
- import assert from 'node:assert/strict'
16
-
17
- import {
18
- AFTER_FIX_PERIOD_MS,
19
- AGAIN_BACKOFF_MS,
20
- retryDecisionOf
21
- } from '../server/service/actuation/retry-plan.js'
22
-
23
- const NOW = 1_800_000_000_000
24
- const at = (over: Record<string, unknown> = {}) =>
25
- retryDecisionOf({ state: 'failed', dispatchable: true, nowMs: NOW, ...over } as any)
26
-
27
- /* ── 첫 시도 — 승인 직후 발신이 놓친 것을 줍는다 ─────────────────────────── */
28
-
29
- test('★ 승인됐는데 한 번도 안 나간 것은 바로 집는다 — 그 창이 이 일꾼의 존재 이유다', () => {
30
- const d = at({ state: 'approved', attempts: 0 })
31
-
32
- assert.equal(d.take, true)
33
- assert.equal(d.attempt, 1)
34
- })
35
-
36
- test('★ 첫 시도는 멱등을 묻지 않는다 — 한 번뿐이라 두 건이 설 수 없다', () => {
37
- assert.equal(at({ state: 'approved', attempts: 0, idempotent: false }).take, true)
38
- })
39
-
40
- test('★ 첫 시도는 어댑터의 답을 묻지 않는다 — 아직 아무 답도 하지 않았다', () => {
41
- assert.equal(at({ state: 'approved' }).take, true)
42
- })
43
-
44
- /* ── 재시도 — 모르면 넘기지 않는다 ──────────────────────────────────────── */
45
-
46
- test('★ 어댑터가 다시 될 일인지 말하지 않았으면 집지 않는다 — 「never」로 접지도 않는다', () => {
47
- /*
48
- * 모르는 것을 `never` 로 접으면 고칠 수 있는 것을 사람이 포기한다. 그래서 집지 않고 목록에
49
- * 「모름」으로 남긴다 — 사람이 보고 정한다.
50
- */
51
- const d = at({ attempts: 1, idempotent: true })
52
-
53
- assert.equal(d.take, false)
54
- assert.equal(d.skip, 'outlook-unknown')
55
- })
56
-
57
- test('★ 멱등을 선언하지 않은 커넥터는 재시도하지 않는다 — 현장에 지시가 두 건 서면 안 된다', () => {
58
- const d = at({ attempts: 1, retry: 'again' })
59
-
60
- assert.equal(d.take, false)
61
- assert.equal(d.skip, 'not-idempotent')
62
- })
63
-
64
- test('★ 영원히 안 될 것은 집지 않는다 — 사람이 새 조치를 내야 한다', () => {
65
- const d = at({ attempts: 1, retry: 'never', idempotent: true })
66
-
67
- assert.equal(d.take, false)
68
- assert.equal(d.skip, 'never', '우리 쪽에 고칠 것이 없다는 뜻이다')
69
- })
70
-
71
- /* ── `again` — 짧게 세 번, 그다음 접는다 ────────────────────────────────── */
72
-
73
- test('★ 물러서면서 세 번 한다', () => {
74
- for (const [i, expected] of AGAIN_BACKOFF_MS.entries()) {
75
- const d = at({ attempts: i, retry: 'again', idempotent: true, state: i === 0 ? 'approved' : 'failed' })
76
-
77
- assert.equal(d.take, true, `${i + 1}번째를 안 했다`)
78
- assert.equal(d.attempt, i + 1)
79
- assert.equal(Date.parse(d.nextAttemptAt!) - NOW, expected, `${i + 1}번째 물러섬이 다르다`)
80
- }
81
- })
82
-
83
- test('★ 세 번을 다 쓰면 접는다 — 끝없이 두드리는 것은 소음이다', () => {
84
- const d = at({ attempts: AGAIN_BACKOFF_MS.length, retry: 'again', idempotent: true })
85
-
86
- assert.equal(d.take, false)
87
- assert.equal(d.skip, 'attempts-spent')
88
- })
89
-
90
- /* ── `after-fix` — 접지 않는다. 이 파일에서 가장 중요한 것 ──────────────── */
91
-
92
- test('★ 설정 문제는 횟수로 접지 않는다 — 고쳐 놓고도 손으로 눌러야 하면 안 된다', () => {
93
- /*
94
- * 2026-09-02 사고가 그 모양이었다: 저쪽이 고쳐진 뒤 사람이 손으로 다시 넘겨서 나갔다.
95
- * `after-fix` 는 재시도가 아니라 **기다리는 것**이다.
96
- */
97
- for (const attempts of [1, 3, 10, 100]) {
98
- const d = at({ attempts, retry: 'after-fix', idempotent: true })
99
-
100
- assert.equal(d.take, true, `${attempts}번째에 접었다`)
101
- assert.equal(Date.parse(d.nextAttemptAt!) - NOW, AFTER_FIX_PERIOD_MS, '간격이 늘어났다')
102
- }
103
- })
104
-
105
- /* ── 물러섬을 표에서 읽는다 ─────────────────────────────────────────────── */
106
-
107
- test('★ 아직 이르면 기다린다', () => {
108
- const d = at({ attempts: 1, retry: 'again', idempotent: true, nextAttemptAt: new Date(NOW + 10_000).toISOString() })
109
-
110
- assert.equal(d.take, false)
111
- assert.equal(d.skip, 'backing-off')
112
- })
113
-
114
- test('★ 때가 되면 집는다', () => {
115
- const d = at({ attempts: 1, retry: 'again', idempotent: true, nextAttemptAt: new Date(NOW - 1).toISOString() })
116
-
117
- assert.equal(d.take, true)
118
- })
119
-
120
- test('★ 읽을 수 없는 시각으로 막지 않는다 — 막으면 그 조치가 표에 갇힌다', () => {
121
- const d = at({ attempts: 1, retry: 'again', idempotent: true, nextAttemptAt: '언젠가' })
122
-
123
- assert.equal(d.take, true)
124
- })
125
-
126
- /* ── 넘길 수 없는 상태 ──────────────────────────────────────────────────── */
127
-
128
- test('★ 종착이면 아무것도 하지 않는다', () => {
129
- const d = at({ state: 'acked', dispatchable: false, attempts: 1, retry: 'again', idempotent: true })
130
-
131
- assert.equal(d.take, false)
132
- assert.equal(d.skip, 'not-dispatchable')
133
- })
134
-
135
- test('넘길 수 없으면 다른 어떤 값도 그것을 뒤집지 않는다', () => {
136
- for (const retry of ['again', 'after-fix', 'never', undefined]) {
137
- assert.equal(at({ dispatchable: false, attempts: 0, retry, idempotent: true }).skip, 'not-dispatchable')
138
- }
139
- })