@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,250 +0,0 @@
1
- import type { IngestWarning, ReferenceMaster } from './reference-master.js'
2
-
3
- /*
4
- * **원본에서 읽은 뒤의 총평** — 사람이 한 장으로 읽는다.
5
- *
6
- * ── 왜 필요한가 (2026-08-22) ────────────────────────────────────────────────
7
- * 읽기가 끝나면 화면에 남는 것은 경고 열 줄이었고, 그 안에 이유가 문장으로 묻혀 있고 UUID 수백 개가
8
- * 붙어 있었다. 그래서 사람이 「가져올 것은 다 들어왔나」·「무엇이 비었나」·「다음에 무엇을 하면
9
- * 나아지나」를 스스로 세어야 했다 — 실제로 그 셋을 손으로 세는 대화가 하루를 채웠다.
10
- *
11
- * 그 셋은 이미 우리가 아는 사실이다. 세어 두었으니 **정리해서 내면 된다.**
12
- *
13
- * ── 두 층으로 나눈다 ────────────────────────────────────────────────────────
14
- * 여기는 **사실 층**이다: 센 것과 그 사유 코드만 담고 문장을 만들지 않는다. 화면이 표로 그리고,
15
- * 사람이 더 알고 싶으면 그때 AI 가 이 사실**만** 근거로 서술한다(말 층).
16
- *
17
- * **AI 는 로드베어링이 아니다.** 호출이 꺼져 있거나 실패해도 이 표가 그대로 화면에 남아야 한다 —
18
- * 그래서 사실 층이 스스로 완결이다.
19
- *
20
- * ── 무엇을 지어내지 않는가 ──────────────────────────────────────────────────
21
- * 「없음」의 뜻을 셋으로 구분해 둔다. 뭉치면 조치가 달라지는 것들이 한 칸에 섞인다.
22
- * · `gaps` — 원본에 있는데 우리가 옮기지 못했다. 고칠 대상이 있다(원본의 빈 칸이거나 우리 매핑).
23
- * · `absent` — 이 원본에 그 **개념이 없다.** 빠진 것이 아니므로 고칠 것이 없다.
24
- * · `grounding` — 값이 들어왔지만 **근거가 저장된 값이 아니다**(원본의 계산 규칙에서 왔다).
25
- */
26
-
27
- /** 센 것 — 화면이 그대로 표로 그린다. */
28
- export interface AssessmentCounts {
29
- locations: number
30
- areas: number
31
- equipment: number
32
- materialDefinitions: number
33
- operations: number
34
- /** 생산 선언이 없으면 없다 — 0 과 구별한다(선언 자체가 없는 것과 비어 있는 것은 다르다). */
35
- materials?: number
36
- materialsWithHome?: number
37
- routes?: number
38
- recipes?: number
39
- recipesWithRoute?: number
40
- /** 공정을 말하는 투입 / 전체 투입 — 공정별 소요를 아는 정도. */
41
- taggedInputs?: number
42
- totalInputs?: number
43
- /** 시험 명세(점검표)의 수 — 선언되지 않았으면 없다(0 과 구별한다). */
44
- testSpecifications?: number
45
- /** 그 명세들이 선언한 판정 기준의 수. */
46
- criteria?: number
47
- /**
48
- * 그중 **아무 한계도 말하지 않는** 기준의 수 — 커널의 `criterionSaysNothing` 과 같은 판정이다.
49
- *
50
- * 이 수가 0 이 아니면 「관리점이 있다」가 「판정된다」를 뜻하지 않는다. 세지 않으면 그 구별이 사라진다.
51
- */
52
- criteriaWithoutLimit?: number
53
- }
54
-
55
- /** 옮기지 못한 것 한 갈래 — 건수 큰 것부터. */
56
- export interface AssessmentGap {
57
- /** 무엇을 옮기다 못 옮겼나 — 커넥터가 붙인 이름(`material home warehouse`). */
58
- what: string
59
- count: number
60
- /** 못 옮긴 원본 값 몇 개 — 전부가 아니라 표본이다(수백 개가 붙던 자리다). */
61
- sample?: string
62
- /** 그 자리에 대신 들어간 값. */
63
- fallback?: string
64
- }
65
-
66
- export interface ImportAssessment {
67
- source: string
68
- siteId: string
69
- siteName?: string
70
- system?: string
71
- built: AssessmentCounts
72
- /**
73
- * **원본이 가지고 있던 수** — 커넥터가 말해 준 경우에만 있다.
74
- *
75
- * 이름을 `origin` 이라 하지 않는다 — 화면에서 그 낱말이 이미 **트윈의 출처**(`summary.origin`:
76
- * 템플릿인가 원본인가)를 뜻한다. 같은 이름을 두 뜻으로 쓰면 읽는 사람이 헷갈린다.
77
- *
78
- * `built` 와 비교해 「전부 옮겼는가」를 사람이 직접 셀 수 있게 한다. 커넥터가 말하지 않으면 이 자리는
79
- * 비어 있고, 화면은 분모 없이 옮긴 수만 보인다 — **분모를 지어내지 않는다.**
80
- */
81
- originCounts?: Record<string, number>
82
- gaps: AssessmentGap[]
83
- /** 이 원본에 개념이 없는 자리 — 커널 낱말로 적는다(화면이 번역한다). */
84
- absent: string[]
85
- /**
86
- * 값이 들어왔지만 **근거가 원본의 저장된 값이 아닌 것** — 파생·유추된 값이다.
87
- *
88
- * 이것을 `gaps` 에 섞으면 안 된다. 빈 자리가 아니라 **채워진 자리**이고, 사람이 물을 것은
89
- * 「왜 비었나」가 아니라 「그 값을 믿어도 되나」다. 조치도 다르다 — 원본을 채우는 것이 아니라
90
- * 그 규칙이 바뀌면 이 값도 바뀐다는 사실을 아는 것이다.
91
- */
92
- derived: AssessmentGap[]
93
- /** 되물은 횟수·잘린 목록 같은 운영 사실. */
94
- notes: IngestWarning[]
95
- }
96
-
97
- /** 이 마스터가 개념을 선언했나 — 「없다」와 「비어 있다」를 구분한다. */
98
- const declared = (v: unknown): boolean => Array.isArray(v) ? v.length > 0 : v !== undefined && v !== null
99
-
100
- /**
101
- * 마스터 한 벌 → 총평의 사실 층.
102
- *
103
- * 경고를 두 갈래로 나눈다: `connector-mapping-fallback` 은 **옮기지 못한 것**이므로 `gaps` 로,
104
- * 나머지(파생된 값·되물은 횟수·잘린 목록)는 `notes` 로 그대로 나른다. 판단하지 않는다 — 무엇이
105
- * 심각한지는 건수와 그 자리의 뜻이 말하고, 그 해석은 사람이나 말 층의 몫이다.
106
- */
107
- export function assessMaster(master: ReferenceMaster, siteId: string): ImportAssessment {
108
- const m: any = master
109
- const d = m.productionSpec?.definition
110
- const inputs = (d?.recipes ?? []).flatMap((r: any) => r.inputs ?? [])
111
-
112
- const built: AssessmentCounts = {
113
- locations: (m.locations ?? []).length,
114
- areas: (m.locations ?? []).filter((l: any) => l.role === 'area' || l.role === 'both').length,
115
- equipment: (m.equipment ?? []).length,
116
- materialDefinitions: (m.materialDefinitions ?? []).length,
117
- operations: (m.operations ?? []).length,
118
- ...(declared(m.testSpecifications)
119
- ? {
120
- testSpecifications: m.testSpecifications!.length,
121
- criteria: m.testSpecifications!.reduce((n, t) => n + (t.criteria?.length ?? 0), 0),
122
- /*
123
- * **한계를 말하지 않는 기준** — 커널의 `criterionSaysNothing` 과 같은 판정이다. 기준이
124
- * 선언됐다는 사실만 있고 판정할 재료가 없는 자리이고, 그것을 세지 않으면 「관리점이 있다」가
125
- * 「판정된다」로 읽힌다.
126
- */
127
- criteriaWithoutLimit: m.testSpecifications!.reduce(
128
- (n, t) => n + (t.criteria ?? []).filter(c => !c.expression && c.limit?.minimum === undefined && c.limit?.maximum === undefined).length,
129
- 0
130
- )
131
- }
132
- : {}),
133
- ...(d
134
- ? {
135
- materials: (d.materials ?? []).length,
136
- materialsWithHome: (d.materials ?? []).filter((x: any) => x.locationType).length,
137
- routes: (d.routes ?? []).length,
138
- recipes: (d.recipes ?? []).length,
139
- recipesWithRoute: (d.recipes ?? []).filter((x: any) => x.route).length,
140
- totalInputs: inputs.length,
141
- taggedInputs: inputs.filter((i: any) => i.operation).length
142
- }
143
- : {})
144
- }
145
-
146
- /* 원본의 수는 커넥터가 말한 그대로 나른다 — 여기서 고치거나 채우지 않는다. */
147
- const originCounts = m.originCounts && Object.keys(m.originCounts).length ? { ...m.originCounts } : undefined
148
-
149
- const gaps: AssessmentGap[] = []
150
- const derived: AssessmentGap[] = []
151
- const notes: IngestWarning[] = []
152
- /*
153
- * 커넥터가 「대체」 수집기로 남기는 것 중 일부는 **빈 자리가 아니라 파생된 값**이다(산출량이 원본의
154
- * 계산 규칙에서 온 경우처럼). 같은 통로로 오지만 뜻이 달라 구분해 담는다 — 이름에 그 사실이 적혀 있다.
155
- */
156
- const isDerived = (field: string) => /derived|not a stored field/i.test(field)
157
- for (const w of m.warnings ?? []) {
158
- if (w?.code === 'connector-mapping-fallback' && w.params?.field) {
159
- const values = String(w.params.values ?? '')
160
- const bin = isDerived(String(w.params.field)) ? derived : gaps
161
- bin.push({
162
- what: String(w.params.field),
163
- count: Number(w.params.count ?? 0),
164
- /* 값은 표본만 — 이 자리에 UUID 수백 개가 붙어 화면을 밀어냈다. 전체는 경고 원문에 남는다. */
165
- ...(values ? { sample: values.length > 120 ? `${values.slice(0, 120)}…` : values } : {}),
166
- ...(w.params.fallback ? { fallback: String(w.params.fallback) } : {})
167
- })
168
- continue
169
- }
170
- notes.push(w)
171
- }
172
- gaps.sort((a, b) => b.count - a.count)
173
- derived.sort((a, b) => b.count - a.count)
174
-
175
- /*
176
- * 이 원본에 개념이 없는 자리. **커널 낱말로 적는다** — 화면이 그것으로 번역하고, 개념 지도가 이미
177
- * 같은 낱말을 쓴다(두 화면이 다른 말을 하면 사람이 둘을 다른 사실로 읽는다).
178
- */
179
- const absent: string[] = []
180
- if (!declared(m.persons)) absent.push('persons')
181
- if (!declared(m.assets)) absent.push('assets')
182
- if (!declared(m.testSpecifications)) absent.push('testSpecifications')
183
- if (!declared(m.personnelClasses)) absent.push('personnelClasses')
184
- if (!declared(m.assetClasses)) absent.push('assetClasses')
185
- if (!declared(m.materialClasses)) absent.push('materialClasses')
186
- if (!d) absent.push('productionSpec')
187
-
188
- return {
189
- source: m.source,
190
- siteId,
191
- siteName: m.siteName,
192
- system: m.system,
193
- built,
194
- ...(originCounts ? { originCounts } : {}),
195
- gaps,
196
- derived,
197
- absent,
198
- notes
199
- }
200
- }
201
-
202
- /** 사람이 읽는 줄 — 터미널·로그가 읽는다(화면은 구조를 그대로 그린다). */
203
- export function formatAssessment(a: ImportAssessment): string {
204
- const c = a.built
205
- const out: string[] = []
206
- /**
207
- * 분모가 있으면 함께 적는다 — 「1,261」과 「원본 1,408 중 1,261」은 다른 말이다.
208
- * 커넥터가 그 수를 말하지 않았으면 옮긴 수만 적는다(지어내지 않는다).
209
- */
210
- const n = (key: keyof AssessmentCounts, v?: number) => {
211
- if (v === undefined) return '없음'
212
- const o = a.originCounts?.[key as string]
213
- return o === undefined ? String(v) : o === v ? `${v}(원본 전부)` : `${v} / 원본 ${o}`
214
- }
215
- out.push(`총평 ${a.siteName ?? a.siteId} (${a.system ?? '?'}) — 원본 ${a.source}`)
216
- out.push(
217
- ` 선 것: 로케이션 ${n('locations', c.locations)}(존 ${c.areas}) · 설비 ${n('equipment', c.equipment)} · ` +
218
- `품목 정의 ${n('materialDefinitions', c.materialDefinitions)} · 공정 ${n('operations', c.operations)}`
219
- )
220
- if (c.materials !== undefined) {
221
- out.push(
222
- ` 자재 ${n('materials', c.materials)}(보관 로케이션 있는 것 ${c.materialsWithHome}) · ` +
223
- `경로 ${n('routes', c.routes)} · 레시피 ${n('recipes', c.recipes)}(경로 붙은 것 ${c.recipesWithRoute}) · ` +
224
- `투입 ${n('totalInputs', c.totalInputs)}(공정을 말하는 것 ${c.taggedInputs})`
225
- )
226
- } else {
227
- out.push(' 생산 선언 없음 — 레시피가 하나도 성립하지 않았다')
228
- }
229
- if (a.gaps.length) {
230
- out.push(' 옮기지 못한 것(건수 순):')
231
- for (const g of a.gaps) out.push(` ${String(g.count).padStart(6)} ${g.what}${g.sample ? ` — ${g.sample}` : ''}`)
232
- }
233
- if (a.derived.length) {
234
- out.push(' 파생된 값(저장된 값이 아니다):')
235
- for (const g of a.derived) out.push(` ${g.what}${g.sample ? ` — ${g.sample}` : ''}`)
236
- }
237
- if (c.testSpecifications) {
238
- /*
239
- * 관리 기준은 계측이 오는지와 무관하게 값이 있다 — 「관리점이 셋인데 둘은 아무 한계도 말하지
240
- * 않는다」를 여기서 볼 수 있어야 판정에 근거가 있는지 사람이 안다.
241
- */
242
- out.push(
243
- ` 관리 기준: 점검표 ${n('testSpecifications', c.testSpecifications)} · 기준 ${c.criteria ?? 0}` +
244
- (c.criteriaWithoutLimit ? ` (한계를 말하지 않는 것 ${c.criteriaWithoutLimit})` : '')
245
- )
246
- }
247
- if (a.absent.length) out.push(` 이 원본에 개념이 없는 자리: ${a.absent.join(', ')}`)
248
- for (const n of a.notes) out.push(` 참고 ${n.code}: ${n.message}`)
249
- return out.join('\n')
250
- }
@@ -1,179 +0,0 @@
1
- /*
2
- * **빠진 구간을 다시 받는 일을 실제로 부른다** — `fillSince` 에 연결과 어댑터를 물려 주는 자리.
3
- *
4
- * ── 왜 이 파일이 없었나 ─────────────────────────────────────────────────────
5
- * `fillSince` 는 2026-08-31 에 만들어졌고 **부르는 곳이 0곳이었습니다.** 2026-09-05 에 저는 그것을
6
- * 못 보고 같은 일을 하는 것을 하나 더 만들었습니다(`backfillScope`). 두 벌이 되었고 둘 다 아무도
7
- * 부르지 않았습니다.
8
- *
9
- * 그래서 이런 상태였습니다.
10
- *
11
- * ```
12
- * 번호가 비면 어디서부터 다시 받을지 안다 ✔ takeInSequence 가 판정한다
13
- * 그 빈 것을 메운다 ✖ 부를 곳이 없다
14
- * ```
15
- *
16
- * 실제로 plant 아웃박스의 1~20 을 잃고 되찾을 방법이 없는 상태를 만났습니다.
17
- *
18
- * ── 같은 검사를 지난다 ──────────────────────────────────────────────────────
19
- * `fillSince` 가 `takeInSequence` 를 지나고, 유입은 `liveIngest` 를 지납니다 — 밀어 받는 길과 같은
20
- * 함수입니다. 여기서 따로 만들면 두 길이 다른 규칙으로 받고, 한쪽만 수정되는 날이 옵니다.
21
- *
22
- * ── 커서 열쇠는 프레임워크가 만든다 ─────────────────────────────────────────
23
- * 열쇠는 `instanceId::scope` 이고 그것을 아는 것은 프레임워크입니다. 어댑터가 만들면 두 곳이 같은
24
- * 규칙을 갖게 되고, 어긋나는 날 **다시 받기가 자기 커서를 0부터 새로 셉니다.**
25
- */
26
- import { getRepository } from '@things-factory/shell'
27
-
28
- import { TwinInstance } from '../twin-instance/twin-instance.js'
29
- import { TwinReference } from './twin-reference.js'
30
- import { getAdapter, type SeqReport, type SiteDescriptor } from './reference-adapter.js'
31
- import { firstSeqOf, pushCursorKey, seqOf, withSeq } from './hook-contract.js'
32
- import { fillSince, type FillOutcome } from './reference-fill.js'
33
- import { liveIngest } from './live-ingest.js'
34
- import { recordReferenceReconciliation } from './reference-reconciliation-writer.js'
35
- import { journalIdentities, spanOf } from './fill-dedupe.js'
36
- import { TwinEngine } from '../../engine/index.js'
37
- import { twinLog, twinWarn } from '../../engine/log.js'
38
-
39
- /** 한 연결의 한 단위를 다시 받은 결과. */
40
- export interface FillRunResult extends Partial<FillOutcome> {
41
- instanceId: string
42
- scope: string
43
- /**
44
- * 못 한 이유 — 성공이면 없습니다.
45
- *
46
- * `not-supported` 는 결함이 아닙니다. 주기로 물어보는 원본(chef · ppms)은 다음 주기가 곧 다시
47
- * 받는 것입니다.
48
- */
49
- skipped?: 'unknown-twin' | 'no-source' | 'no-adapter' | 'not-supported'
50
- }
51
-
52
- /**
53
- * 그 연결의 한 단위를 다시 받는다.
54
- *
55
- * **커서를 되돌리지 않습니다.** 받은 것이 번호 검사를 지나야 커서가 나아가고, 그 판정은 밀어 받는
56
- * 길과 같은 함수가 합니다.
57
- *
58
- * @param from 여기서부터 다시 받는다 — 주면 커서를 무시합니다. 잃은 구간을 되찾을 때만 씁니다.
59
- */
60
- export async function runFill(args: {
61
- domainId: string
62
- instanceId: string
63
- scope: string
64
- from?: number
65
- maxPages?: number
66
- }): Promise<FillRunResult> {
67
- const { domainId, instanceId, scope, from, maxPages } = args
68
- const base: FillRunResult = { instanceId, scope }
69
-
70
- const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })
71
- if (!inst) return { ...base, skipped: 'unknown-twin' }
72
-
73
- const repo = getRepository(TwinReference)
74
- const ref = await repo.findOne({ where: { domain: { id: domainId }, source: instanceId } })
75
- if (!ref) return { ...base, skipped: 'no-source' }
76
-
77
- const adapter = getAdapter(ref.adapterType)
78
- if (!adapter) return { ...base, skipped: 'no-adapter' }
79
- /* 다시 받기를 안 내는 원본이 있습니다 — 주기로 물어보는 쪽은 다음 주기가 곧 그것입니다. */
80
- if (typeof adapter.fetchSince !== 'function') return { ...base, skipped: 'not-supported' }
81
-
82
- const siteId = (inst.origin as any)?.siteId
83
- const site: SiteDescriptor = siteId ? { siteId } : { siteId: instanceId }
84
- const cursorKey = pushCursorKey(instanceId, scope)
85
-
86
- /*
87
- * `from` 을 주면 커서를 그 값으로 갈아 끼웁니다 — **저장된 커서를 건드리지 않습니다.** `fillSince`
88
- * 가 나아간 만큼만 적으므로, 잃은 구간을 되찾은 뒤 커서는 원래 자리보다 앞서지 않습니다.
89
- */
90
- const cursor = from === undefined ? ((ref as any).liveCursor ?? {}) : withSeq((ref as any).liveCursor, cursorKey, from)
91
- /* fillSince가 커서를 저장할 때 이 지역 값도 같이 바꾼다. 저장본을 다시 읽어 대사를 늦추지 않는다. */
92
- let persistedCursor: unknown = cursor
93
-
94
- const outcome = await fillSince({
95
- cfg: ref.connectionConfig ?? {},
96
- site,
97
- scope,
98
- cursorKey,
99
- cursor,
100
- fetch: (cfg, s, sc, since) => adapter.fetchSince!(cfg, s as SiteDescriptor, sc, since),
101
- ingest: records => liveIngest(domainId, instanceId, records, 'fill'),
102
- /*
103
- * ── 넣기 전에 기억을 채운다 (2026-09-06) ──────────────────────────────────
104
- * 중복 판정 기억은 프로세스 안에만 있다. 재기동하면 비워지고, 그러면 backfill 이 **이미 저널에
105
- * 있는 사실도 다시 앉힌다.** 실측으로 39건이 통째로 다시 앉았다(저널 44 → 83).
106
- *
107
- * push 경로에서는 안 한다 — 거기서는 재전송이 창 안에 들어와 이미 걸리고, 봉투마다 저널을
108
- * 조회하면 뜨거운 길이 느려진다.
109
- */
110
- beforeIngest: async records => {
111
- const span = spanOf(records)
112
- if (!span) return
113
- const { identities, scanned, truncated } = await journalIdentities(domainId, instanceId, span)
114
- const added = TwinEngine.warmDeduper(domainId, instanceId, identities)
115
- if (truncated) {
116
- twinWarn(
117
- `[twin-fill] "${instanceId}" 의 저널을 ${scanned}줄까지만 읽었습니다 — 그보다 앞의 사실은 ` +
118
- '다시 앉을 수 있습니다. 구간을 좁혀 부르거나 정체 색인이 필요합니다'
119
- )
120
- }
121
- if (added) twinLog(`[twin-fill] "${instanceId}" — 저널에서 정체 ${added}개를 기억에 채웠습니다`)
122
- },
123
- saveCursor: async next => {
124
- await repo.update({ id: (ref as any).id }, { liveCursor: next } as any)
125
- persistedCursor = next
126
- },
127
- ...(maxPages ? { maxPages } : {})
128
- })
129
-
130
- /* 원본이 실제로 답한 범위가 있을 때만 기록한다. 범위를 모르는 것은 "정상"으로 덮지 않는다. */
131
- await recordReferenceReconciliation({
132
- domainId,
133
- instanceId,
134
- scope,
135
- sourceRange: outcome.sourceRange,
136
- cursorSeq: seqOf(persistedCursor, cursorKey),
137
- firstSeqSeen: firstSeqOf(persistedCursor, cursorKey)
138
- }).catch(err => twinWarn(`[twin-reconcile] "${instanceId}" · ${scope} 상태를 적지 못했습니다: ${err?.message ?? err}`))
139
-
140
- const say = `[twin-fill] "${instanceId}" · ${scope} — ${outcome.applied}건 넣음 · ${outcome.pages}쪽 · ${outcome.stopped}${outcome.detail ? ` (${outcome.detail})` : ''}`
141
- /* 끝난 것과 막힌 것을 다른 소리로 남깁니다 — 구멍은 사람이 원본을 봐야 합니다. */
142
- if (outcome.stopped === 'done' || outcome.stopped === 'no-progress') twinLog(say)
143
- else twinWarn(say)
144
-
145
- return { ...base, ...outcome }
146
- }
147
-
148
- /**
149
- * **그 번호들이 무엇이었나** — 구멍을 만났을 때 사람이 묻는다.
150
- *
151
- * 커넥터는 「418 다음이 420」까지만 말한다. 그 419 가 무엇이었는지 알려면 원본에 물어야 하고,
152
- * 그 길이 없어서 사람이 아웃박스를 손으로 뒤졌다(2026-09-06).
153
- *
154
- * **판정하지 않는다.** 원본이 아는 것을 그대로 낸다 — 「그러니 포기해도 된다」는 되돌릴 수 없는
155
- * 판단이라 사람의 몫이다.
156
- */
157
- export async function seqReportOf(args: {
158
- domainId: string
159
- instanceId: string
160
- scope: string
161
- from: number
162
- to: number
163
- }): Promise<{ instanceId: string; scope: string; report?: SeqReport; skipped?: 'unknown-twin' | 'no-source' | 'no-adapter' | 'not-supported' }> {
164
- const { domainId, instanceId, scope, from, to } = args
165
- const base = { instanceId, scope }
166
-
167
- const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })
168
- if (!inst) return { ...base, skipped: 'unknown-twin' }
169
- const ref = await getRepository(TwinReference).findOne({ where: { domain: { id: domainId }, source: instanceId } })
170
- if (!ref) return { ...base, skipped: 'no-source' }
171
- const adapter = getAdapter(ref.adapterType)
172
- if (!adapter) return { ...base, skipped: 'no-adapter' }
173
- /* 번호를 매기지 않는 원본은 물을 것이 없다 — 결함이 아니다. */
174
- if (typeof adapter.seqReport !== 'function') return { ...base, skipped: 'not-supported' }
175
-
176
- const siteId = (inst.origin as any)?.siteId
177
- const site: SiteDescriptor | undefined = siteId ? { siteId } : undefined
178
- return { ...base, report: await adapter.seqReport(ref.connectionConfig ?? {}, site, scope, from, to) }
179
- }
@@ -1,223 +0,0 @@
1
- /*
2
- * **놓친 구간을 backfill 해 채운다** — 밀어 받는 길의 짝.
3
- *
4
- * ── 왜 필요한가 (2026-08-31, 인티그레이션 레인 지적) ──────────────────────
5
- * 훅은 반드시 놓친다 — 우리가 내려가 있을 때, 그쪽이 못 보냈을 때, 네트워크가 끊겼을 때. 받는 쪽이
6
- * 번호로 그것을 **알아채게** 되었지만(§`takeInSequence`), 알아챈 뒤 **그 사이를 채우는 길이 없었다.**
7
- * 설계가 그 길을 적어 두었는데 만들지 않았다.
8
- *
9
- * ── 같은 검사를 지난다 ───────────────────────────────────────────────────
10
- * backfill 한 것도 `takeInSequence` 를 지난다. 여기서 따로 만들면 두 길이 다른 규칙으로 받고, 한쪽만
11
- * 고쳐지는 날 어긋난 그 길에서만 사실이 사라진다.
12
- *
13
- * ── 멈추는 조건을 셋 둔다 ────────────────────────────────────────────────
14
- * 되풀이해서 요청하는 경로는 **끝나지 않는 것**이 가장 흔한 결함이다.
15
- *
16
- * 빈 답 더 줄 것이 없다. 끝
17
- * 번호가 안 나아간다 같은 것을 다시 받았다 — 무한히 요청하는 것을 막는다
18
- * 구멍 원본의 아웃박스에 구멍이 있다. 이어 받으면 커서가 그 번호를 지나쳐 적힌다
19
- *
20
- * 그리고 **쪽 상한**을 둔다. 상한에 닿았으면 조용히 끝내지 않고 말한다 — 조용히 자르면 사람은 다 받은
21
- * 줄로 읽는다.
22
- */
23
- import { seqOf, takeInSequence, withSeq } from './hook-contract.js'
24
- import type { InboundBatch } from './reference-adapter.js'
25
- import { twinWarn } from '../../engine/log.js'
26
-
27
- /** 한 번 채우고 나서 남는 사실. */
28
- export interface FillOutcome {
29
- /** 트윈에 넣은 레코드 수. */
30
- applied: number
31
- /**
32
- * ingest 가 낸 네 갈래의 합 — **두 갈래로는 셈이 안 닫힌다.**
33
- *
34
- * ```
35
- * 두 갈래 157 − 46 − 2 = 109 「설명 못 함」 진실은 되풀이 108 + 어휘 1
36
- * 네 갈래 157 − 46 − 2 − 108 − 1 = 0
37
- * ```
38
- *
39
- * 이 값이 없으면 원본 쪽에서 「보낸 것 20개 중 event 가 9개인데 나머지는 어디 갔나」를 셀 수
40
- * 없다. 실제로 인티그레이션 레인이 그것을 물었고, 그 수가 트윈에 저장되지 않아 답을 못 했다.
41
- */
42
- duplicates: number
43
- rejected: number
44
- /**
45
- * 왜 거절됐나 — **사유별 수.** 수만 내면 「26건이 안 들어온다」에서 멈춘다.
46
- *
47
- * 목록 전체가 아니라 사유별로 센다. 같은 이유로 거절된 26건이 26줄이면 읽는 사람이 그 줄을
48
- * 세어야 하고, 다른 이유 하나가 그 안에 묻힌다.
49
- */
50
- rejectedReasons?: Record<string, number>
51
- vocabulary: number
52
- /** 시각을 못 읽어 ingest 시각으로 떨어진 것 — 종류별. 비어 있으면 전부 자기 시각을 말했다. */
53
- undated?: Record<string, number>
54
- /** 몇 쪽을 받았나. */
55
- pages: number
56
- /** 커서가 어디까지 갔나 — 아무것도 못 받았으면 없다. */
57
- lastSeq?: number
58
- /**
59
- * 이 실행에서 **가장 낮게 받아들인 번호** — 밑에서부터 다시 받았을 때 이것이 곧 「우리가 가진
60
- * 가장 낮은 번호」다.
61
- */
62
- lowestSeq?: number
63
- /** 왜 멈췄나 — `done` · `gap` · `no-progress` · `page-limit` · `refused`. */
64
- stopped: 'done' | 'gap' | 'no-progress' | 'page-limit' | 'refused'
65
- /** 멈춘 이유의 사람 말. 알리지 않고 끝내지 않는다. */
66
- detail?: string
67
- /**
68
- * 마지막으로 받은 묶음이 말한 **원본의 번호 범위** — 원본이 안 말하면 없다.
69
- *
70
- * 우리 커서와 견주는 자리가 이 값을 쓴다. 없으면 「맞다」가 아니라 **「모른다」**로 답해야 한다.
71
- */
72
- sourceRange?: { first?: number; last?: number }
73
- }
74
-
75
- /** 몇 쪽까지 받나 — 한 번의 채우기가 서버를 오래 붙잡지 않게. */
76
- const MAX_PAGES = 50
77
-
78
- /**
79
- * 그 단위의 놓친 구간을 채운다.
80
- *
81
- * `ingest` 를 부르는 쪽이 넘겨 준다 — 훅과 같은 이유다(이 파일이 엔진을 직접 부르면 시험이 엔진을
82
- * 세워야 한다).
83
- */
84
- export async function fillSince(args: {
85
- cfg: Record<string, any>
86
- site: { siteId: string }
87
- /** 번호를 매기는 단위 — 커서 열쇠의 절반. 커넥터가 만들지 않는다. */
88
- scope: string
89
- /** 커서에 적힌 열쇠 — `pushCursorKey(instanceId, scope)`. */
90
- cursorKey: string
91
- /** 지금 커서 — 이 함수가 읽고, 나아간 만큼 되돌려 준다. */
92
- cursor: unknown
93
- fetch: (cfg: Record<string, any>, site: { siteId: string }, scope: string, since: number) => Promise<InboundBatch>
94
- ingest: (records: unknown[]) => { applied: number; duplicates: number; rejected: unknown[] }
95
- /**
96
- * 넣기 **직전에** 부른다 — 이 쪽의 레코드를 넘긴다.
97
- *
98
- * 중복 판정 기억을 저널에서 채우는 자리다(§`fill-dedupe.ts`). 그 기억은 프로세스 안에만 있어서
99
- * 재기동하면 비워지고, 그러면 이미 저널에 있는 사실도 「처음 본 것」이 된다.
100
- *
101
- * `ingest` 는 동기라 여기서 채울 수 없다. 이 훅은 비동기이므로 저널을 읽을 수 있다.
102
- *
103
- * 실패해도 넣기를 멈추지 않는다 — 기억을 못 채운 것이 사실을 못 받을 이유는 아니다.
104
- */
105
- beforeIngest?: (records: unknown[]) => Promise<void>
106
- saveCursor: (cursor: Record<string, unknown>) => Promise<void>
107
- maxPages?: number
108
- }): Promise<FillOutcome> {
109
- const { cfg, site, scope, cursorKey, fetch, ingest, saveCursor , beforeIngest } = args
110
- const maxPages = args.maxPages ?? MAX_PAGES
111
-
112
- let cursor = args.cursor
113
- let applied = 0
114
- let duplicates = 0
115
- let rejectedCount = 0
116
- const rejectedReasons: Record<string, number> = {}
117
- let vocabulary = 0
118
- const undated: Record<string, number> = {}
119
- /* 원본이 말한 번호 범위 — 마지막으로 받은 묶음의 것을 들고 나간다. 안 말하면 끝까지 없다. */
120
- let sourceRange: { first?: number; last?: number } | undefined
121
- /* 이 실행에서 가장 낮게 받아들인 번호 — 커서에 firstSeq 로 적는다. */
122
- let lowestSeq: number | undefined
123
- let pages = 0
124
-
125
- for (; pages < maxPages; pages++) {
126
- const since = seqOf(cursor, cursorKey) ?? 0
127
-
128
- let batch: InboundBatch
129
- try {
130
- batch = await fetch(cfg, site, scope, since)
131
- } catch (e: any) {
132
- return { applied, duplicates, rejected: rejectedCount, ...(Object.keys(rejectedReasons).length ? { rejectedReasons } : {}), vocabulary, ...(Object.keys(undated).length ? { undated } : {}), pages, ...seqPart(cursor, cursorKey), ...(sourceRange ? { sourceRange } : {}), ...(lowestSeq !== undefined ? { lowestSeq } : {}), stopped: 'refused', detail: String(e?.message ?? e) }
133
- }
134
-
135
- if (batch?.sourceRange) sourceRange = batch.sourceRange
136
-
137
- const items = batch?.items ?? []
138
- /* 빈 답은 더 줄 것이 없다는 뜻이다. 오류가 아니다. */
139
- if (!items.length) return { applied, duplicates, rejected: rejectedCount, ...(Object.keys(rejectedReasons).length ? { rejectedReasons } : {}), vocabulary, ...(Object.keys(undated).length ? { undated } : {}), pages, ...seqPart(cursor, cursorKey), ...(sourceRange ? { sourceRange } : {}), ...(lowestSeq !== undefined ? { lowestSeq } : {}), stopped: 'done' }
140
-
141
- const taken = takeInSequence({ items, scope, lastSeq: seqOf(cursor, cursorKey) })
142
- if (taken.refused) {
143
- return { applied, duplicates, rejected: rejectedCount, ...(Object.keys(rejectedReasons).length ? { rejectedReasons } : {}), vocabulary, ...(Object.keys(undated).length ? { undated } : {}), pages, ...seqPart(cursor, cursorKey), ...(sourceRange ? { sourceRange } : {}), ...(lowestSeq !== undefined ? { lowestSeq } : {}), stopped: 'refused', detail: taken.refused }
144
- }
145
-
146
- if (taken.records.length) {
147
- if (beforeIngest) {
148
- await beforeIngest(taken.records).catch(e =>
149
- twinWarn(`[twin-fill] 중복 판정 기억을 못 채웠다 — ${String(e?.message ?? e)}. 넣기는 그대로 간다`)
150
- )
151
- }
152
- const result = ingest(taken.records)
153
- applied += result.applied
154
- duplicates += result.duplicates ?? 0
155
- rejectedCount += result.rejected?.length ?? 0
156
- for (const r of result.rejected ?? []) {
157
- /* 사유가 여럿이면 첫 줄로 묶는다 — 뒤는 대개 같은 원인의 곁가지다. */
158
- const why = String((r as any)?.errors?.[0] ?? '(사유 없음)').slice(0, 120)
159
- rejectedReasons[why] = (rejectedReasons[why] ?? 0) + 1
160
- }
161
- vocabulary += (result as any).vocabulary ?? 0
162
- for (const [k, n] of Object.entries((result as any).undated ?? {})) undated[k] = (undated[k] ?? 0) + (n as number)
163
- }
164
-
165
- /*
166
- * **번호가 나아가야 다음 쪽을 요청한다.** 원본이 빈 묶음에 물어본 번호를 그대로 돌려주는 계약이면,
167
- * 나아감을 보지 않고 요청하면 무한히 돈다.
168
- */
169
- if (taken.advancedSeq === undefined || taken.advancedSeq <= since) {
170
- if (taken.gap) return { applied, duplicates, rejected: rejectedCount, ...(Object.keys(rejectedReasons).length ? { rejectedReasons } : {}), vocabulary, ...(Object.keys(undated).length ? { undated } : {}), pages: pages + 1, ...seqPart(cursor, cursorKey), ...(sourceRange ? { sourceRange } : {}), ...(lowestSeq !== undefined ? { lowestSeq } : {}), stopped: 'gap', detail: gapWord(taken.gap) }
171
- return {
172
- applied,
173
- duplicates,
174
- rejected: rejectedCount, ...(Object.keys(rejectedReasons).length ? { rejectedReasons } : {}),
175
- vocabulary,
176
- ...(Object.keys(undated).length ? { undated } : {}),
177
- pages: pages + 1,
178
- ...seqPart(cursor, cursorKey),
179
- ...(sourceRange ? { sourceRange } : {}), ...(lowestSeq !== undefined ? { lowestSeq } : {}),
180
- stopped: 'no-progress',
181
- detail: `번호가 ${since} 에서 나아가지 않았다 — 같은 것을 다시 받았다`
182
- }
183
- }
184
-
185
- if (lowestSeq === undefined) lowestSeq = taken.lowestSeq
186
- /* 밑에서부터 다시 받았으면 그 번호가 곧 우리가 가진 가장 낮은 번호다. */
187
- cursor = withSeq(cursor, cursorKey, taken.advancedSeq, taken.firstSeq ?? lowestSeq)
188
- await saveCursor(cursor as Record<string, unknown>).catch(err =>
189
- twinWarn(`[twin-fill] 번호를 커서에 적지 못했다 (${cursorKey}=${taken.advancedSeq}) — ${err?.message ?? err}`)
190
- )
191
-
192
- /*
193
- * **구멍이 있으면 멈춘다.** 원본의 아웃박스에 구멍이 있는 것이고, 이어 받으면 커서가 그 번호를
194
- * 지나쳐 적혀 빠진 사실이 다시 오지 않는다.
195
- */
196
- if (taken.gap) {
197
- return { applied, duplicates, rejected: rejectedCount, ...(Object.keys(rejectedReasons).length ? { rejectedReasons } : {}), vocabulary, ...(Object.keys(undated).length ? { undated } : {}), pages: pages + 1, ...seqPart(cursor, cursorKey), ...(sourceRange ? { sourceRange } : {}), ...(lowestSeq !== undefined ? { lowestSeq } : {}), stopped: 'gap', detail: gapWord(taken.gap) }
198
- }
199
- }
200
-
201
- /* 상한에 닿았다 — 조용히 끝내지 않는다. 사람이 다 받은 줄로 읽으면 안 된다. */
202
- return {
203
- applied,
204
- duplicates,
205
- rejected: rejectedCount, ...(Object.keys(rejectedReasons).length ? { rejectedReasons } : {}),
206
- vocabulary,
207
- ...(Object.keys(undated).length ? { undated } : {}),
208
- pages,
209
- ...seqPart(cursor, cursorKey),
210
- ...(sourceRange ? { sourceRange } : {}), ...(lowestSeq !== undefined ? { lowestSeq } : {}),
211
- stopped: 'page-limit',
212
- detail: `${maxPages}쪽까지 받고 멈췄다 — 남은 것이 있을 수 있다. 다음 주기가 이어 받는다`
213
- }
214
- }
215
-
216
- function seqPart(cursor: unknown, key: string): { lastSeq?: number } {
217
- const seq = seqOf(cursor, key)
218
- return seq === undefined ? {} : { lastSeq: seq }
219
- }
220
-
221
- function gapWord(gap: { expectedSeq: number; lastSeq: number }): string {
222
- return `번호가 비었다 — ${gap.lastSeq} 다음이 ${gap.expectedSeq} 이어야 한다. 원본의 아웃박스에 구멍이 있다`
223
- }