@things-factory/headless-twin 10.1.278 → 10.1.280

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (614) hide show
  1. package/package.json +21 -7
  2. package/dist-server/engine/attention-digest.js.map +0 -1
  3. package/dist-server/engine/canonical-ingest.js.map +0 -1
  4. package/dist-server/engine/checkpoint-fold.js.map +0 -1
  5. package/dist-server/engine/command-routing.js.map +0 -1
  6. package/dist-server/engine/declared-stimulus.js.map +0 -1
  7. package/dist-server/engine/energy-topology.js.map +0 -1
  8. package/dist-server/engine/event-time.js.map +0 -1
  9. package/dist-server/engine/index.js.map +0 -1
  10. package/dist-server/engine/ingest-dedupe.js.map +0 -1
  11. package/dist-server/engine/ingest-health.js.map +0 -1
  12. package/dist-server/engine/integration-coverage.js.map +0 -1
  13. package/dist-server/engine/integration-probes.js.map +0 -1
  14. package/dist-server/engine/integration-runner.js.map +0 -1
  15. package/dist-server/engine/integration-target-profile.js.map +0 -1
  16. package/dist-server/engine/kpi-baseline.js.map +0 -1
  17. package/dist-server/engine/kpi-fold.js.map +0 -1
  18. package/dist-server/engine/kpi-query.js.map +0 -1
  19. package/dist-server/engine/kpi-target.js.map +0 -1
  20. package/dist-server/engine/live-attentions.js.map +0 -1
  21. package/dist-server/engine/live-feed-registry.js.map +0 -1
  22. package/dist-server/engine/load-meter.js.map +0 -1
  23. package/dist-server/engine/local-declarations.js.map +0 -1
  24. package/dist-server/engine/log.js.map +0 -1
  25. package/dist-server/engine/loop-lag.js.map +0 -1
  26. package/dist-server/engine/measured-estimator.js.map +0 -1
  27. package/dist-server/engine/measured-yield.js.map +0 -1
  28. package/dist-server/engine/model-basis.js.map +0 -1
  29. package/dist-server/engine/model-gap.js.map +0 -1
  30. package/dist-server/engine/model-refusal.js.map +0 -1
  31. package/dist-server/engine/model-vocabulary.js.map +0 -1
  32. package/dist-server/engine/oee-accumulator.js.map +0 -1
  33. package/dist-server/engine/operation-basis.js.map +0 -1
  34. package/dist-server/engine/producer-guard.js.map +0 -1
  35. package/dist-server/engine/property-effects.js.map +0 -1
  36. package/dist-server/engine/read-time.js.map +0 -1
  37. package/dist-server/engine/restart-policy.js.map +0 -1
  38. package/dist-server/engine/runtime-key.js.map +0 -1
  39. package/dist-server/engine/spec-coverage.js.map +0 -1
  40. package/dist-server/engine/stage-path.js.map +0 -1
  41. package/dist-server/engine/state-axes.js.map +0 -1
  42. package/dist-server/engine/structure-diff.js.map +0 -1
  43. package/dist-server/engine/travel-estimator.js.map +0 -1
  44. package/dist-server/engine/twin-engine.js.map +0 -1
  45. package/dist-server/engine/twin-state-channel.js.map +0 -1
  46. package/dist-server/engine/warm-start.js.map +0 -1
  47. package/dist-server/index.js.map +0 -1
  48. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +0 -1
  49. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +0 -1
  50. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +0 -1
  51. package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +0 -1
  52. package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +0 -1
  53. package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +0 -1
  54. package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +0 -1
  55. package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +0 -1
  56. package/dist-server/migrations/1786800000000-CreateTwinReferenceReconciliations.js.map +0 -1
  57. package/dist-server/migrations/index.js.map +0 -1
  58. package/dist-server/routes.js.map +0 -1
  59. package/dist-server/service/actuation/actuation-advisor.js.map +0 -1
  60. package/dist-server/service/actuation/actuation-outcome.js.map +0 -1
  61. package/dist-server/service/actuation/actuation-rule-resolver.js.map +0 -1
  62. package/dist-server/service/actuation/actuation-rule.js.map +0 -1
  63. package/dist-server/service/actuation/approval-gateway.js.map +0 -1
  64. package/dist-server/service/actuation/catch-up-effects.js.map +0 -1
  65. package/dist-server/service/actuation/command-dispatcher.js.map +0 -1
  66. package/dist-server/service/actuation/command-store.js.map +0 -1
  67. package/dist-server/service/actuation/dispatch-after-approval.js.map +0 -1
  68. package/dist-server/service/actuation/effect-match.js.map +0 -1
  69. package/dist-server/service/actuation/index.js.map +0 -1
  70. package/dist-server/service/actuation/retry-plan.js.map +0 -1
  71. package/dist-server/service/actuation/rule-evaluate.js.map +0 -1
  72. package/dist-server/service/actuation/rule-loop.js.map +0 -1
  73. package/dist-server/service/actuation/rule-runner.js.map +0 -1
  74. package/dist-server/service/actuation/rule-wiring.js.map +0 -1
  75. package/dist-server/service/actuation/settle-effects.js.map +0 -1
  76. package/dist-server/service/actuation/sweep-dispatch.js.map +0 -1
  77. package/dist-server/service/actuation/twin-command-resolver.js.map +0 -1
  78. package/dist-server/service/actuation/twin-command.js.map +0 -1
  79. package/dist-server/service/actuation/twin-now.js.map +0 -1
  80. package/dist-server/service/index.js.map +0 -1
  81. package/dist-server/service/reference/actuation-routing.js.map +0 -1
  82. package/dist-server/service/reference/actuation-target.js.map +0 -1
  83. package/dist-server/service/reference/actuation-verification.js.map +0 -1
  84. package/dist-server/service/reference/attention-lane.js.map +0 -1
  85. package/dist-server/service/reference/connection-portability-resolver.js.map +0 -1
  86. package/dist-server/service/reference/connection-portability.js.map +0 -1
  87. package/dist-server/service/reference/control-routing.js.map +0 -1
  88. package/dist-server/service/reference/discovery-result.js.map +0 -1
  89. package/dist-server/service/reference/fill-cadence.js.map +0 -1
  90. package/dist-server/service/reference/fill-dedupe.js.map +0 -1
  91. package/dist-server/service/reference/fill-loop.js.map +0 -1
  92. package/dist-server/service/reference/fill-span.js.map +0 -1
  93. package/dist-server/service/reference/hook-contract.js.map +0 -1
  94. package/dist-server/service/reference/hook-rejected.js.map +0 -1
  95. package/dist-server/service/reference/hook-store.js.map +0 -1
  96. package/dist-server/service/reference/index.js.map +0 -1
  97. package/dist-server/service/reference/ingest-space.js.map +0 -1
  98. package/dist-server/service/reference/knob-defaults.js.map +0 -1
  99. package/dist-server/service/reference/live-cadence.js.map +0 -1
  100. package/dist-server/service/reference/live-feed-lease.js.map +0 -1
  101. package/dist-server/service/reference/live-ingest.js.map +0 -1
  102. package/dist-server/service/reference/reference-adapter.js.map +0 -1
  103. package/dist-server/service/reference/reference-assessment.js.map +0 -1
  104. package/dist-server/service/reference/reference-fill-run.js.map +0 -1
  105. package/dist-server/service/reference/reference-fill.js.map +0 -1
  106. package/dist-server/service/reference/reference-hook.js.map +0 -1
  107. package/dist-server/service/reference/reference-link-groups.js.map +0 -1
  108. package/dist-server/service/reference/reference-links.js.map +0 -1
  109. package/dist-server/service/reference/reference-live.js.map +0 -1
  110. package/dist-server/service/reference/reference-master.js.map +0 -1
  111. package/dist-server/service/reference/reference-probe.js.map +0 -1
  112. package/dist-server/service/reference/reference-progress-channel.js.map +0 -1
  113. package/dist-server/service/reference/reference-progress-subscription.js.map +0 -1
  114. package/dist-server/service/reference/reference-progress.js.map +0 -1
  115. package/dist-server/service/reference/reference-reconciliation-query.js.map +0 -1
  116. package/dist-server/service/reference/reference-reconciliation-writer.js.map +0 -1
  117. package/dist-server/service/reference/reference-reconciliation.js.map +0 -1
  118. package/dist-server/service/reference/reference-registry.js.map +0 -1
  119. package/dist-server/service/reference/reference-resolver.js.map +0 -1
  120. package/dist-server/service/reference/template-registry.js.map +0 -1
  121. package/dist-server/service/reference/twin-reference-reconciliation.js.map +0 -1
  122. package/dist-server/service/reference/twin-reference.js.map +0 -1
  123. package/dist-server/service/twin-attention/index.js.map +0 -1
  124. package/dist-server/service/twin-attention/twin-attention-query.js.map +0 -1
  125. package/dist-server/service/twin-audit/command-audit.js.map +0 -1
  126. package/dist-server/service/twin-audit/index.js.map +0 -1
  127. package/dist-server/service/twin-audit/twin-audit-event.js.map +0 -1
  128. package/dist-server/service/twin-audit/twin-audit-query.js.map +0 -1
  129. package/dist-server/service/twin-backfill/backfill-period-facts.js.map +0 -1
  130. package/dist-server/service/twin-backfill/backfill-shape.js.map +0 -1
  131. package/dist-server/service/twin-backfill/index.js.map +0 -1
  132. package/dist-server/service/twin-backfill/twin-backfill-resolver.js.map +0 -1
  133. package/dist-server/service/twin-control/index.js.map +0 -1
  134. package/dist-server/service/twin-control/twin-control-mutation.js.map +0 -1
  135. package/dist-server/service/twin-event/index.js.map +0 -1
  136. package/dist-server/service/twin-event/journal-count.js.map +0 -1
  137. package/dist-server/service/twin-event/twin-event-keys.js.map +0 -1
  138. package/dist-server/service/twin-event/twin-event-type.js.map +0 -1
  139. package/dist-server/service/twin-event/twin-event.js.map +0 -1
  140. package/dist-server/service/twin-forecast/forecast-metrics.js.map +0 -1
  141. package/dist-server/service/twin-forecast/forecast-tuning.js.map +0 -1
  142. package/dist-server/service/twin-forecast/gap-analytics.js.map +0 -1
  143. package/dist-server/service/twin-forecast/index.js.map +0 -1
  144. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +0 -1
  145. package/dist-server/service/twin-ingest-window/index.js.map +0 -1
  146. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +0 -1
  147. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +0 -1
  148. package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +0 -1
  149. package/dist-server/service/twin-instance/index.js.map +0 -1
  150. package/dist-server/service/twin-instance/twin-instance.js.map +0 -1
  151. package/dist-server/service/twin-journal/event-type-split-shape.js.map +0 -1
  152. package/dist-server/service/twin-journal/event-type-split.js.map +0 -1
  153. package/dist-server/service/twin-journal/index.js.map +0 -1
  154. package/dist-server/service/twin-journal/journal-order.js.map +0 -1
  155. package/dist-server/service/twin-journal/twin-journal-query.js.map +0 -1
  156. package/dist-server/service/twin-lifecycle/domain-catalog.js.map +0 -1
  157. package/dist-server/service/twin-lifecycle/index.js.map +0 -1
  158. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +0 -1
  159. package/dist-server/service/twin-metrics/index.js.map +0 -1
  160. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +0 -1
  161. package/dist-server/service/twin-model/axis-journal-evidence.js.map +0 -1
  162. package/dist-server/service/twin-model/choose-recipe.js.map +0 -1
  163. package/dist-server/service/twin-model/epcis-coverage.js.map +0 -1
  164. package/dist-server/service/twin-model/external-resolver.js.map +0 -1
  165. package/dist-server/service/twin-model/iec61850-coverage.js.map +0 -1
  166. package/dist-server/service/twin-model/index.js.map +0 -1
  167. package/dist-server/service/twin-model/isa95-coverage.js.map +0 -1
  168. package/dist-server/service/twin-model/item-ref.js.map +0 -1
  169. package/dist-server/service/twin-model/name-index.js.map +0 -1
  170. package/dist-server/service/twin-model/project-structure.js.map +0 -1
  171. package/dist-server/service/twin-model/standard-coverage.js.map +0 -1
  172. package/dist-server/service/twin-model/status-tally.js.map +0 -1
  173. package/dist-server/service/twin-model/twin-equipment.js.map +0 -1
  174. package/dist-server/service/twin-model/twin-lineage-query.js.map +0 -1
  175. package/dist-server/service/twin-model/twin-location.js.map +0 -1
  176. package/dist-server/service/twin-model/twin-model-item-query.js.map +0 -1
  177. package/dist-server/service/twin-model/twin-model-mutation.js.map +0 -1
  178. package/dist-server/service/twin-model/twin-model-query.js.map +0 -1
  179. package/dist-server/service/twin-model/twin-model-tree-query.js.map +0 -1
  180. package/dist-server/service/twin-model/twin-operation.js.map +0 -1
  181. package/dist-server/service/twin-readiness/index.js.map +0 -1
  182. package/dist-server/service/twin-readiness/twin-readiness-query.js.map +0 -1
  183. package/dist-server/service/twin-space/area-resolver.js.map +0 -1
  184. package/dist-server/service/twin-space/index.js.map +0 -1
  185. package/dist-server/service/twin-space/move-space.js.map +0 -1
  186. package/dist-server/service/twin-space/representation-role.js.map +0 -1
  187. package/dist-server/service/twin-space/space-integrity.js.map +0 -1
  188. package/dist-server/service/twin-space/twin-area.js.map +0 -1
  189. package/dist-server/service/twin-space/twin-space-area.js.map +0 -1
  190. package/dist-server/service/twin-space/twin-space-representation.js.map +0 -1
  191. package/dist-server/service/twin-space/twin-space-resolver.js.map +0 -1
  192. package/dist-server/service/twin-space/twin-space.js.map +0 -1
  193. package/dist-server/service/twin-state/index.js.map +0 -1
  194. package/dist-server/service/twin-state/twin-state-subscription.js.map +0 -1
  195. package/dist-server/service/twin-structure/index.js.map +0 -1
  196. package/dist-server/service/twin-structure/twin-structure.js.map +0 -1
  197. package/dist-server/service/twin-subject/event-subjects.js.map +0 -1
  198. package/dist-server/service/twin-subject/index.js.map +0 -1
  199. package/dist-server/service/twin-subject/item-resolver.js.map +0 -1
  200. package/dist-server/service/twin-subject/subject-query-shape.js.map +0 -1
  201. package/dist-server/service/twin-subject/twin-subject-backfill.js.map +0 -1
  202. package/dist-server/service/twin-subject/twin-subject-event.js.map +0 -1
  203. package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +0 -1
  204. package/dist-server/service/twin-subject/twin-subject-query.js.map +0 -1
  205. package/dist-server/service/twin-subject/twin-subject-writer.js.map +0 -1
  206. package/dist-server/service/twin-target/index.js.map +0 -1
  207. package/dist-server/service/twin-target/twin-target-resolver.js.map +0 -1
  208. package/dist-server/service/twin-target/twin-target.js.map +0 -1
  209. package/dist-shared/axis-read.js.map +0 -1
  210. package/dist-shared/entity-delta.js.map +0 -1
  211. package/dist-shared/kpi-broadcast.js.map +0 -1
  212. package/dist-shared/touched-items.js.map +0 -1
  213. package/dist-shared/twin-level.js.map +0 -1
  214. package/server/engine/attention-digest.ts +0 -102
  215. package/server/engine/canonical-ingest.ts +0 -511
  216. package/server/engine/checkpoint-fold.ts +0 -12
  217. package/server/engine/command-routing.ts +0 -67
  218. package/server/engine/declared-stimulus.ts +0 -66
  219. package/server/engine/energy-topology.ts +0 -189
  220. package/server/engine/event-time.ts +0 -96
  221. package/server/engine/index.ts +0 -51
  222. package/server/engine/ingest-dedupe.ts +0 -24
  223. package/server/engine/ingest-health.ts +0 -24
  224. package/server/engine/integration-coverage.ts +0 -147
  225. package/server/engine/integration-probes.ts +0 -144
  226. package/server/engine/integration-runner.ts +0 -95
  227. package/server/engine/integration-target-profile.ts +0 -103
  228. package/server/engine/kpi-baseline.ts +0 -202
  229. package/server/engine/kpi-fold.ts +0 -1516
  230. package/server/engine/kpi-query.ts +0 -1210
  231. package/server/engine/kpi-target.ts +0 -248
  232. package/server/engine/live-attentions.ts +0 -30
  233. package/server/engine/live-feed-registry.ts +0 -59
  234. package/server/engine/load-meter.ts +0 -393
  235. package/server/engine/local-declarations.ts +0 -779
  236. package/server/engine/log.ts +0 -72
  237. package/server/engine/loop-lag.ts +0 -120
  238. package/server/engine/measured-estimator.ts +0 -91
  239. package/server/engine/measured-yield.ts +0 -89
  240. package/server/engine/model-basis.ts +0 -162
  241. package/server/engine/model-gap.ts +0 -168
  242. package/server/engine/model-refusal.ts +0 -31
  243. package/server/engine/model-vocabulary.ts +0 -82
  244. package/server/engine/oee-accumulator.ts +0 -195
  245. package/server/engine/operation-basis.ts +0 -131
  246. package/server/engine/producer-guard.ts +0 -64
  247. package/server/engine/property-effects.ts +0 -216
  248. package/server/engine/read-time.ts +0 -77
  249. package/server/engine/restart-policy.ts +0 -55
  250. package/server/engine/runtime-key.ts +0 -58
  251. package/server/engine/spec-coverage.ts +0 -105
  252. package/server/engine/stage-path.ts +0 -172
  253. package/server/engine/state-axes.ts +0 -60
  254. package/server/engine/structure-diff.ts +0 -88
  255. package/server/engine/travel-estimator.ts +0 -138
  256. package/server/engine/twin-engine.ts +0 -4979
  257. package/server/engine/twin-state-channel.ts +0 -39
  258. package/server/engine/warm-start.ts +0 -265
  259. package/server/index.ts +0 -90
  260. package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +0 -43
  261. package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +0 -54
  262. package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +0 -53
  263. package/server/migrations/1786300000000-IndexEventTypeByTime.ts +0 -48
  264. package/server/migrations/1786400000000-IndexEventCreatedAt.ts +0 -38
  265. package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +0 -93
  266. package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +0 -66
  267. package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +0 -82
  268. package/server/migrations/1786800000000-CreateTwinReferenceReconciliations.ts +0 -39
  269. package/server/migrations/index.ts +0 -25
  270. package/server/routes.ts +0 -75
  271. package/server/service/actuation/actuation-advisor.ts +0 -131
  272. package/server/service/actuation/actuation-outcome.ts +0 -97
  273. package/server/service/actuation/actuation-rule-resolver.ts +0 -147
  274. package/server/service/actuation/actuation-rule.ts +0 -139
  275. package/server/service/actuation/approval-gateway.ts +0 -44
  276. package/server/service/actuation/catch-up-effects.ts +0 -152
  277. package/server/service/actuation/command-dispatcher.ts +0 -474
  278. package/server/service/actuation/command-store.ts +0 -236
  279. package/server/service/actuation/dispatch-after-approval.ts +0 -71
  280. package/server/service/actuation/effect-match.ts +0 -124
  281. package/server/service/actuation/index.ts +0 -27
  282. package/server/service/actuation/retry-plan.ts +0 -145
  283. package/server/service/actuation/rule-evaluate.ts +0 -352
  284. package/server/service/actuation/rule-loop.ts +0 -160
  285. package/server/service/actuation/rule-runner.ts +0 -216
  286. package/server/service/actuation/rule-wiring.ts +0 -84
  287. package/server/service/actuation/settle-effects.ts +0 -115
  288. package/server/service/actuation/sweep-dispatch.ts +0 -179
  289. package/server/service/actuation/twin-command-resolver.ts +0 -387
  290. package/server/service/actuation/twin-command.ts +0 -232
  291. package/server/service/actuation/twin-now.ts +0 -97
  292. package/server/service/index.ts +0 -100
  293. package/server/service/reference/actuation-routing.ts +0 -192
  294. package/server/service/reference/actuation-target.ts +0 -163
  295. package/server/service/reference/actuation-verification.ts +0 -85
  296. package/server/service/reference/attention-lane.ts +0 -21
  297. package/server/service/reference/connection-portability-resolver.ts +0 -171
  298. package/server/service/reference/connection-portability.ts +0 -329
  299. package/server/service/reference/control-routing.ts +0 -62
  300. package/server/service/reference/discovery-result.ts +0 -95
  301. package/server/service/reference/fill-cadence.ts +0 -29
  302. package/server/service/reference/fill-dedupe.ts +0 -66
  303. package/server/service/reference/fill-loop.ts +0 -153
  304. package/server/service/reference/fill-span.ts +0 -31
  305. package/server/service/reference/hook-contract.ts +0 -364
  306. package/server/service/reference/hook-rejected.ts +0 -53
  307. package/server/service/reference/hook-store.ts +0 -28
  308. package/server/service/reference/index.ts +0 -18
  309. package/server/service/reference/ingest-space.ts +0 -104
  310. package/server/service/reference/knob-defaults.ts +0 -59
  311. package/server/service/reference/live-cadence.ts +0 -129
  312. package/server/service/reference/live-feed-lease.ts +0 -56
  313. package/server/service/reference/live-ingest.ts +0 -94
  314. package/server/service/reference/reference-adapter.ts +0 -985
  315. package/server/service/reference/reference-assessment.ts +0 -250
  316. package/server/service/reference/reference-fill-run.ts +0 -179
  317. package/server/service/reference/reference-fill.ts +0 -223
  318. package/server/service/reference/reference-hook.ts +0 -479
  319. package/server/service/reference/reference-link-groups.ts +0 -21
  320. package/server/service/reference/reference-links.ts +0 -77
  321. package/server/service/reference/reference-live.ts +0 -420
  322. package/server/service/reference/reference-master.ts +0 -999
  323. package/server/service/reference/reference-probe.ts +0 -264
  324. package/server/service/reference/reference-progress-channel.ts +0 -26
  325. package/server/service/reference/reference-progress-subscription.ts +0 -78
  326. package/server/service/reference/reference-progress.ts +0 -95
  327. package/server/service/reference/reference-reconciliation-query.ts +0 -28
  328. package/server/service/reference/reference-reconciliation-writer.ts +0 -38
  329. package/server/service/reference/reference-reconciliation.ts +0 -55
  330. package/server/service/reference/reference-registry.ts +0 -17
  331. package/server/service/reference/reference-resolver.ts +0 -969
  332. package/server/service/reference/template-registry.ts +0 -85
  333. package/server/service/reference/twin-reference-reconciliation.ts +0 -27
  334. package/server/service/reference/twin-reference.ts +0 -190
  335. package/server/service/twin-attention/index.ts +0 -3
  336. package/server/service/twin-attention/twin-attention-query.ts +0 -70
  337. package/server/service/twin-audit/command-audit.ts +0 -114
  338. package/server/service/twin-audit/index.ts +0 -5
  339. package/server/service/twin-audit/twin-audit-event.ts +0 -158
  340. package/server/service/twin-audit/twin-audit-query.ts +0 -72
  341. package/server/service/twin-backfill/backfill-period-facts.ts +0 -168
  342. package/server/service/twin-backfill/backfill-shape.ts +0 -86
  343. package/server/service/twin-backfill/index.ts +0 -3
  344. package/server/service/twin-backfill/twin-backfill-resolver.ts +0 -35
  345. package/server/service/twin-control/index.ts +0 -3
  346. package/server/service/twin-control/twin-control-mutation.ts +0 -150
  347. package/server/service/twin-event/index.ts +0 -3
  348. package/server/service/twin-event/journal-count.ts +0 -53
  349. package/server/service/twin-event/twin-event-keys.ts +0 -215
  350. package/server/service/twin-event/twin-event-type.ts +0 -68
  351. package/server/service/twin-event/twin-event.ts +0 -250
  352. package/server/service/twin-forecast/forecast-metrics.ts +0 -106
  353. package/server/service/twin-forecast/forecast-tuning.ts +0 -40
  354. package/server/service/twin-forecast/gap-analytics.ts +0 -139
  355. package/server/service/twin-forecast/index.ts +0 -3
  356. package/server/service/twin-forecast/twin-forecast-query.ts +0 -486
  357. package/server/service/twin-ingest-window/index.ts +0 -7
  358. package/server/service/twin-ingest-window/twin-ingest-window-query.ts +0 -125
  359. package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +0 -57
  360. package/server/service/twin-ingest-window/twin-ingest-window.ts +0 -113
  361. package/server/service/twin-instance/index.ts +0 -3
  362. package/server/service/twin-instance/twin-instance.ts +0 -199
  363. package/server/service/twin-journal/event-type-split-shape.ts +0 -112
  364. package/server/service/twin-journal/event-type-split.ts +0 -144
  365. package/server/service/twin-journal/index.ts +0 -3
  366. package/server/service/twin-journal/journal-order.ts +0 -20
  367. package/server/service/twin-journal/twin-journal-query.ts +0 -615
  368. package/server/service/twin-lifecycle/domain-catalog.ts +0 -51
  369. package/server/service/twin-lifecycle/index.ts +0 -3
  370. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +0 -285
  371. package/server/service/twin-metrics/index.ts +0 -3
  372. package/server/service/twin-metrics/twin-metrics-query.ts +0 -172
  373. package/server/service/twin-model/axis-journal-evidence.ts +0 -57
  374. package/server/service/twin-model/choose-recipe.ts +0 -31
  375. package/server/service/twin-model/epcis-coverage.ts +0 -251
  376. package/server/service/twin-model/external-resolver.ts +0 -173
  377. package/server/service/twin-model/iec61850-coverage.ts +0 -111
  378. package/server/service/twin-model/index.ts +0 -25
  379. package/server/service/twin-model/isa95-coverage.ts +0 -320
  380. package/server/service/twin-model/item-ref.ts +0 -80
  381. package/server/service/twin-model/name-index.ts +0 -94
  382. package/server/service/twin-model/project-structure.ts +0 -213
  383. package/server/service/twin-model/standard-coverage.ts +0 -35
  384. package/server/service/twin-model/status-tally.ts +0 -37
  385. package/server/service/twin-model/twin-equipment.ts +0 -191
  386. package/server/service/twin-model/twin-lineage-query.ts +0 -327
  387. package/server/service/twin-model/twin-location.ts +0 -147
  388. package/server/service/twin-model/twin-model-item-query.ts +0 -1029
  389. package/server/service/twin-model/twin-model-mutation.ts +0 -503
  390. package/server/service/twin-model/twin-model-query.ts +0 -792
  391. package/server/service/twin-model/twin-model-tree-query.ts +0 -211
  392. package/server/service/twin-model/twin-operation.ts +0 -157
  393. package/server/service/twin-readiness/index.ts +0 -3
  394. package/server/service/twin-readiness/twin-readiness-query.ts +0 -96
  395. package/server/service/twin-space/area-resolver.ts +0 -75
  396. package/server/service/twin-space/index.ts +0 -8
  397. package/server/service/twin-space/move-space.ts +0 -262
  398. package/server/service/twin-space/representation-role.ts +0 -15
  399. package/server/service/twin-space/space-integrity.ts +0 -293
  400. package/server/service/twin-space/twin-area.ts +0 -63
  401. package/server/service/twin-space/twin-space-area.ts +0 -66
  402. package/server/service/twin-space/twin-space-representation.ts +0 -99
  403. package/server/service/twin-space/twin-space-resolver.ts +0 -582
  404. package/server/service/twin-space/twin-space.ts +0 -148
  405. package/server/service/twin-state/index.ts +0 -3
  406. package/server/service/twin-state/twin-state-subscription.ts +0 -62
  407. package/server/service/twin-structure/index.ts +0 -3
  408. package/server/service/twin-structure/twin-structure.ts +0 -96
  409. package/server/service/twin-subject/event-subjects.ts +0 -162
  410. package/server/service/twin-subject/index.ts +0 -10
  411. package/server/service/twin-subject/item-resolver.ts +0 -92
  412. package/server/service/twin-subject/subject-query-shape.ts +0 -84
  413. package/server/service/twin-subject/twin-subject-backfill.ts +0 -196
  414. package/server/service/twin-subject/twin-subject-event.ts +0 -101
  415. package/server/service/twin-subject/twin-subject-fast-path.ts +0 -346
  416. package/server/service/twin-subject/twin-subject-query.ts +0 -210
  417. package/server/service/twin-subject/twin-subject-writer.ts +0 -189
  418. package/server/service/twin-target/index.ts +0 -5
  419. package/server/service/twin-target/twin-target-resolver.ts +0 -142
  420. package/server/service/twin-target/twin-target.ts +0 -97
  421. package/server/types/global.d.ts +0 -22
  422. package/shared/axis-read.ts +0 -28
  423. package/shared/entity-delta.ts +0 -335
  424. package/shared/kpi-broadcast.ts +0 -13
  425. package/shared/touched-items.ts +0 -73
  426. package/shared/twin-level.ts +0 -48
  427. package/test/ack-shape-alignment.test.ts +0 -97
  428. package/test/actuation-advisor.test.ts +0 -55
  429. package/test/actuation-approval-door.test.ts +0 -411
  430. package/test/actuation-dispatch.test.ts +0 -209
  431. package/test/actuation-effect.test.ts +0 -162
  432. package/test/actuation-outcome.test.ts +0 -152
  433. package/test/actuation-rule-runner.test.ts +0 -281
  434. package/test/actuation-rule.test.ts +0 -266
  435. package/test/actuation-seam.test.ts +0 -255
  436. package/test/actuation-settle.test.ts +0 -164
  437. package/test/actuation-target.test.ts +0 -145
  438. package/test/actuation-verification-state.test.ts +0 -139
  439. package/test/adopt-structure-live.test.ts +0 -133
  440. package/test/aggregate-not-findone.test.ts +0 -112
  441. package/test/area-resolver-db.test.ts +0 -110
  442. package/test/attention-digest.test.ts +0 -161
  443. package/test/axis-declaration-passthrough-db.test.ts +0 -152
  444. package/test/axis-journal-evidence.test.ts +0 -71
  445. package/test/axis-read.test.ts +0 -188
  446. package/test/backfill-shape.test.ts +0 -89
  447. package/test/boot-resume.test.ts +0 -287
  448. package/test/broadcast-cost-baseline.test.ts +0 -201
  449. package/test/broadcast-period.test.ts +0 -58
  450. package/test/broadcast-queue-overflow.test.ts +0 -244
  451. package/test/canonical-ingest-vocabularies.test.ts +0 -451
  452. package/test/canonical-quantity-door.test.ts +0 -61
  453. package/test/capability-mapping.test.ts +0 -89
  454. package/test/checkpoint-refuses-empty.test.ts +0 -103
  455. package/test/choose-recipe.test.ts +0 -117
  456. package/test/column-type-portability.test.ts +0 -122
  457. package/test/command-routing.test.ts +0 -61
  458. package/test/command-store-writes-columns.test.ts +0 -126
  459. package/test/connection-portability-doors.test.ts +0 -87
  460. package/test/connector-capability-declaration.test.ts +0 -195
  461. package/test/contract-layer-guard.test.ts +0 -48
  462. package/test/control-capability.test.ts +0 -98
  463. package/test/cursor-stall-not-read-failure.test.ts +0 -126
  464. package/test/declaration-reaches-model.test.ts +0 -226
  465. package/test/declared-location-types.test.ts +0 -89
  466. package/test/declared-stimulus.test.ts +0 -88
  467. package/test/dedupe-transformation.test.ts +0 -112
  468. package/test/discovery-result.test.ts +0 -75
  469. package/test/dispatch-after-approval-source.test.ts +0 -81
  470. package/test/duration-estimators.test.ts +0 -144
  471. package/test/energy-topology.test.ts +0 -113
  472. package/test/entity-delta.test.ts +0 -352
  473. package/test/equipment-identity-reaches.test.ts +0 -57
  474. package/test/event-subjects.test.ts +0 -148
  475. package/test/event-time-column.test.ts +0 -67
  476. package/test/event-type-split.test.ts +0 -178
  477. package/test/external-resolver.test.ts +0 -177
  478. package/test/fact-scope-wiring.test.ts +0 -96
  479. package/test/fill-dedupe.test.ts +0 -59
  480. package/test/fill-loop.test.ts +0 -35
  481. package/test/first-envelope.test.ts +0 -153
  482. package/test/fold-gap-speaks.test.ts +0 -53
  483. package/test/fold-shift-dst.test.ts +0 -110
  484. package/test/forecast-metrics.test.ts +0 -157
  485. package/test/forecast-tuning.test.ts +0 -42
  486. package/test/gap-analytics.test.ts +0 -113
  487. package/test/generated-not-counted.test.ts +0 -99
  488. package/test/guard-roots.ts +0 -76
  489. package/test/home-in-area.test.ts +0 -90
  490. package/test/hook-address.test.ts +0 -28
  491. package/test/hook-rejected-shape.test.ts +0 -86
  492. package/test/hook-response-sum.test.ts +0 -193
  493. package/test/hook-sequence.test.ts +0 -333
  494. package/test/ingest-bench.test.ts +0 -70
  495. package/test/ingest-dedupe.test.ts +0 -56
  496. package/test/ingest-expected-quiet.test.ts +0 -111
  497. package/test/ingest-health-engine.test.ts +0 -248
  498. package/test/ingest-health-wiring.test.ts +0 -120
  499. package/test/ingest-health.test.ts +0 -306
  500. package/test/ingest-history.test.ts +0 -247
  501. package/test/ingest-idempotent.test.ts +0 -211
  502. package/test/ingest-reconcile-four-ways.test.ts +0 -97
  503. package/test/ingest-rules-header.test.ts +0 -100
  504. package/test/ingest-running-guard.test.ts +0 -136
  505. package/test/ingest-space.test.ts +0 -78
  506. package/test/ingest-window-rolls-unobserved.test.ts +0 -72
  507. package/test/ingest-wiring-guard.test.ts +0 -197
  508. package/test/instance-cache-lifecycle.test.ts +0 -110
  509. package/test/intake-mapping-parity.test.ts +0 -175
  510. package/test/integration-probes.test.ts +0 -103
  511. package/test/integration-runner.test.ts +0 -95
  512. package/test/item-ref.test.ts +0 -78
  513. package/test/journal-order-axis.test.ts +0 -80
  514. package/test/journal-read-discipline.test.ts +0 -186
  515. package/test/journal-retention.test.ts +0 -275
  516. package/test/journal-sort-axis.test.ts +0 -142
  517. package/test/journal-write-door.test.ts +0 -110
  518. package/test/journal-write-trend.test.ts +0 -115
  519. package/test/kernel-kind-guard.test.ts +0 -98
  520. package/test/knob-defaults.test.ts +0 -72
  521. package/test/kpi-baseline-db.test.ts +0 -216
  522. package/test/kpi-baseline.test.ts +0 -196
  523. package/test/kpi-fold.test.ts +0 -1456
  524. package/test/kpi-query-bench.test.ts +0 -130
  525. package/test/lens-own-places.test.ts +0 -50
  526. package/test/lineage-survives-restart.test.ts +0 -234
  527. package/test/live-cadence.test.ts +0 -170
  528. package/test/live-cursor-wiring.test.ts +0 -87
  529. package/test/live-feed-lease.test.ts +0 -63
  530. package/test/live-feed-registry.test.ts +0 -75
  531. package/test/live-kernel-facts.test.ts +0 -161
  532. package/test/live-mirror-parity.test.ts +0 -286
  533. package/test/load-meter.test.ts +0 -328
  534. package/test/local-declarations.test.ts +0 -662
  535. package/test/log-stamp.test.ts +0 -59
  536. package/test/loop-lag.test.ts +0 -82
  537. package/test/master-to-twin.test.ts +0 -279
  538. package/test/measured-yield.test.ts +0 -90
  539. package/test/merge-streams.test.ts +0 -70
  540. package/test/mirror-resumes-from-checkpoint.test.ts +0 -192
  541. package/test/model-basis.test.ts +0 -141
  542. package/test/model-gap.test.ts +0 -153
  543. package/test/model-refusal.test.ts +0 -75
  544. package/test/model-vocabulary.test.ts +0 -114
  545. package/test/move-space.test.ts +0 -149
  546. package/test/mutation-gate.test.ts +0 -122
  547. package/test/oee-accumulator.test.ts +0 -204
  548. package/test/oee-site-calendar.test.ts +0 -146
  549. package/test/open-doors.test.ts +0 -197
  550. package/test/operation-basis.test.ts +0 -127
  551. package/test/operational-vocabulary.test.ts +0 -108
  552. package/test/operations-capability-db.test.ts +0 -165
  553. package/test/order-and-transaction-split.test.ts +0 -107
  554. package/test/order-fold-host.test.ts +0 -112
  555. package/test/producer-guard.test.ts +0 -66
  556. package/test/project-structure-db.test.ts +0 -226
  557. package/test/projection-reaches-screen.test.ts +0 -277
  558. package/test/projection-reads-declared.test.ts +0 -109
  559. package/test/property-effects.test.ts +0 -128
  560. package/test/provenance-promotion.test.ts +0 -99
  561. package/test/read-failure-ledger.test.ts +0 -106
  562. package/test/read-failure-visible.test.ts +0 -145
  563. package/test/read-time.test.ts +0 -118
  564. package/test/reference-fill.test.ts +0 -235
  565. package/test/reference-grounding.test.ts +0 -70
  566. package/test/reference-hook.test.ts +0 -177
  567. package/test/reference-links.test.ts +0 -56
  568. package/test/reference-reconciliation.test.ts +0 -39
  569. package/test/registry-key-guard.test.ts +0 -80
  570. package/test/rejection-carries-event-id.test.ts +0 -101
  571. package/test/rename-twin.test.ts +0 -89
  572. package/test/resolve-ts-siblings.mjs +0 -52
  573. package/test/restart-policy.test.ts +0 -111
  574. package/test/resync-origin-site.test.ts +0 -83
  575. package/test/retry-plan.test.ts +0 -139
  576. package/test/revision-axis.test.ts +0 -110
  577. package/test/runtime-key.test.ts +0 -66
  578. package/test/save-intake-collision.test.ts +0 -91
  579. package/test/scale-twin-bench.test.ts +0 -103
  580. package/test/secrets-at-rest.test.ts +0 -135
  581. package/test/snapshot-freshness.test.ts +0 -60
  582. package/test/source-outcome-audit.test.ts +0 -104
  583. package/test/space-integrity.test.ts +0 -223
  584. package/test/space-representation.test.ts +0 -66
  585. package/test/space-scope-includes-stopped.test.ts +0 -55
  586. package/test/spec-coverage.test.ts +0 -113
  587. package/test/stage-path.test.ts +0 -95
  588. package/test/standard-coverage.test.ts +0 -148
  589. package/test/state-axes.test.ts +0 -74
  590. package/test/status-tally.test.ts +0 -55
  591. package/test/streamline-e2e.test.ts +0 -76
  592. package/test/structure-revision-db.test.ts +0 -315
  593. package/test/subject-fast-path.test.ts +0 -148
  594. package/test/subject-read-model.test.ts +0 -175
  595. package/test/sweep-dispatch.test.ts +0 -191
  596. package/test/tenant-registry-db.test.ts +0 -149
  597. package/test/time-range.test.ts +0 -152
  598. package/test/touched-items.test.ts +0 -61
  599. package/test/twin-audit.test.ts +0 -83
  600. package/test/twin-event-keys.test.ts +0 -193
  601. package/test/twin-model-item-db.test.ts +0 -319
  602. package/test/twin-model-parent-relation-db.test.ts +0 -125
  603. package/test/twin-model-tree-db.test.ts +0 -209
  604. package/test/twin-origin-resync.test.ts +0 -133
  605. package/test/twin-state-channel.test.ts +0 -111
  606. package/test/vocabulary-guard.test.ts +0 -43
  607. package/test/warm-start-seam.test.ts +0 -162
  608. package/test/warm-start.test.ts +0 -297
  609. package/test/withheld-door.test.ts +0 -95
  610. package/test/yield-loop.test.ts +0 -199
  611. package/tsconfig.json +0 -15
  612. package/tsconfig.shared.json +0 -23
  613. package/tsconfig.shared.tsbuildinfo +0 -1
  614. package/tsconfig.tsbuildinfo +0 -1
@@ -1,72 +0,0 @@
1
- import { Args, Ctx, Query, Resolver } from 'type-graphql'
2
-
3
- import { ListParam, getQueryBuilderFromListParams, getRepository, ScalarObject } from '@things-factory/shell'
4
-
5
- import { TwinAuditEvent } from './twin-audit-event.js'
6
-
7
- /*
8
- * 승인 기록 조회 — **감사의 기본 질문에 답한다.**
9
- *
10
- * "요즘 무슨 조치가 나갔나" → 최근순 목록
11
- * "김현장이 승인한 것 전부" → 행위자 검색(인덱스 있음)
12
- * "AI 가 제안한 것만" → origin 필터
13
- * "거절된 시도" → accepted 필터
14
- *
15
- * 저널에 섞여 있을 때는 이 중 어느 것도 못 했다 — 행위자가 payload JSON 안이라 인덱스를 걸 수 없었다.
16
- */
17
- /** 시각 필터 값을 날짜로 — 못 읽는 값은 그대로 둔다(지어내지 않는다). */
18
- function toDateValue(v: any): any {
19
- const one = (x: any) => {
20
- if (x instanceof Date) return x
21
- const t = typeof x === 'string' ? Date.parse(x) : NaN
22
- return Number.isNaN(t) ? x : new Date(t)
23
- }
24
- return Array.isArray(v) ? v.map(one) : one(v)
25
- }
26
-
27
- @Resolver()
28
- export class TwinAuditQuery {
29
- /* 조회 게이트는 달지 않는다 — 이 저장소의 규약이고(mutation-gate 검사가 정본을 지킨다),
30
- 도메인 필터가 테넌트 경계를 이미 지킨다. 테넌트를 넘어 읽는 계기판만 OPS_GATE 를 쓴다. */
31
- @Query(returns => ScalarObject, {
32
- nullable: true,
33
- description:
34
- 'List twin command audit records (who approved what, and what the kernel answered) with the standard list contract, plus the total match count.'
35
- })
36
- async twinAuditList(
37
- /* 표준 목록 계약은 `@Args` 로 펼쳐 받는다 — `@Arg` 로 받으면 type-graphql 이 입력 타입을
38
- 결정하지 못해 **스키마 조립 자체가 실패**한다(서버가 아예 안 뜬다). */
39
- @Args(type => ListParam) params: ListParam,
40
- @Ctx() context: ResolverContext
41
- ): Promise<any> {
42
- const domainId = context.state.domain?.id
43
- if (!domainId) return { items: [], total: 0 }
44
-
45
- const effective: ListParam = {
46
- ...(params ?? ({} as ListParam)),
47
- /* 기본 정렬 — 최근 것부터. 감사는 "요즘" 에서 시작한다. */
48
- sortings: params?.sortings?.length ? params.sortings : [{ name: 'eventTime', desc: true }],
49
- /* 시각 필터는 날짜로 옮겨서 넘긴다 — 문자열 그대로면 알리지 않고 0건이 된다(저널과 같은 이유). */
50
- filters: (params?.filters ?? []).map(f => (f.name === 'eventTime' ? { ...f, value: toDateValue(f.value) } : f))
51
- }
52
-
53
- const qb = getQueryBuilderFromListParams({
54
- repository: getRepository(TwinAuditEvent),
55
- params: effective,
56
- domain: context.state.domain,
57
- alias: 'a',
58
- /*
59
- * `searchables` 는 전부 **실컬럼**이다 — 프레임워크 질의 빌더는 여기 없는 컬럼의 LIKE 를
60
- * 경고 후 무시한다(인덱스 없는 전체 스캔 방지). 행위자로 찾는 것이 이 테이블을 구분한 이유다.
61
- */
62
- searchables: ['actorEmail', 'actorName', 'commandType', 'origin', 'errorCode', 'reason'],
63
- sortables: ['eventTime', 'commandType', 'actorEmail', 'origin', 'accepted'],
64
- /* 감사 목록은 사람이 읽는 속도로 본다 — 크게 퍼 오는 것이 이득이 아니다. */
65
- defaultLimit: 50,
66
- maxLimit: 200
67
- })
68
-
69
- const [items, total] = await qb.getManyAndCount()
70
- return { items, total }
71
- }
72
- }
@@ -1,168 +0,0 @@
1
- import { getRepository } from '@things-factory/shell'
2
-
3
- import { TwinEvent } from '../twin-event/twin-event.js'
4
- import { TwinEngine } from '../../engine/twin-engine.js'
5
- import { ingestCanonicalRecords } from '../../engine/canonical-ingest.js'
6
- import { absoluteTime } from '../../engine/read-time.js'
7
- import { judgeBackfill, splitAlreadyThere } from './backfill-shape.js'
8
-
9
- /*
10
- * 지난 기록 채우기 — **저널에만 쓴다. 트윈의 「지금」을 건드리지 않는다.**
11
- *
12
- * ── 왜 라이브 문으로 넣을 수 없나 (2026-08-30) ──────────────────────────────
13
- * 커널의 상태는 「지금」이다. 늦게 온 옛 표본은 가드가 막는다(그렇게 만들었다). 지난 기록을 라이브
14
- * 문으로 넣으면 둘 중 하나다 — 가드에 막히거나, 트윈의 시계가 과거로 끌린다. 둘 다 나쁘다.
15
- *
16
- * 그래서 이 길은 저널에만 쓴다. 상태는 그대로 두고, 저널을 읽는 쪽(성과 계산·이력 화면)만 그 사실을
17
- * 보게 된다.
18
- *
19
- * ── 무엇을 받나 ────────────────────────────────────────────────────────────
20
- * **마감된 구간 사실만** 받는다. 시점의 관측(계량 표본·설비 상태·발전 적산)은 받지 않는다 — 그것들은
21
- * 커널의 상태를 바꾸는 사실이라, 상태를 건너뛰고 저널에만 넣으면 상태와 저널이 갈라진다.
22
- *
23
- * ── 같은 기간을 두 번 넣지 않는다 ──────────────────────────────────────────
24
- * 마감된 구간 사실은 정체성이 내용에 있다(커널 0.7.81: 종류·대상·시작·끝). 그 id 로 이미 있는 것을
25
- * 가려낸다. 저장소의 제약으로 막지 않는 이유는 드라이버가 다섯이고 충돌 처리가 제각각이기 때문이다 —
26
- * 구간 단위로 한 번 읽어 가려내는 편이 이식성이 있고 값도 싸다(한 시간에 한 줄이면 하루 24줄이다).
27
- *
28
- * ── 보존보다 오래된 것은 받지 않는다 ───────────────────────────────────────
29
- * 저널은 보존 기간이 지나면 지운다. 그보다 오래된 것을 채우면 다음 정리에서 지워진다. 조용히 넣고
30
- * 지워지면 아무도 모르므로, **거절하고 이유를 말한다.**
31
- */
32
-
33
- export interface BackfillResult {
34
- /** 저널에 새로 적은 수. */
35
- written: number
36
- /** 이미 있어서 건너뛴 수 — 다시 읽어도 중복이 쌓이지 않는다는 뜻이다. */
37
- skipped: number
38
- /** 받지 않은 것과 그 이유. 조용히 버리지 않는다. */
39
- refused: { record: unknown; reason: string }[]
40
- }
41
-
42
- /** 이 도메인의 보존 기간(일). 정책이 없으면 `undefined` — 그때는 오래됨을 판정하지 않는다. */
43
- async function retentionDaysOf(domainId: string): Promise<number | undefined> {
44
- const perDomain = TwinEngine.retentionDaysOf ? await TwinEngine.retentionDaysOf(domainId).catch(() => undefined) : undefined
45
- const days = perDomain ?? TwinEngine.JOURNAL_RETENTION_DAYS
46
- return days && days > 0 ? days : undefined
47
- }
48
-
49
- /**
50
- * 지난 기록을 저널에 채운다.
51
- *
52
- * `records` 는 라이브와 **같은 모양**이다 — 커넥터가 다른 어휘를 배울 필요가 없다. 검증·갈림·id 만들기는
53
- * 커널의 유입이 그대로 한다(§`ingestCanonicalRecords`).
54
- */
55
- export async function backfillPeriodFacts(input: {
56
- domainId: string
57
- instanceId: string
58
- records: unknown[]
59
- /** 이 시각을 「지금」으로 본다 — 보존 판정의 기준. 시험이 시각을 정할 수 있게 받는다. */
60
- nowMs?: number
61
- }): Promise<BackfillResult> {
62
- const { domainId, instanceId, records } = input
63
- const nowMs = input.nowMs ?? Date.now()
64
- const refused: { record: unknown; reason: string }[] = []
65
-
66
- if (!Array.isArray(records) || !records.length) return { written: 0, skipped: 0, refused }
67
-
68
- /* 검증과 갈림은 라이브와 같은 것을 쓴다 — 두 벌이 되면 채운 사실과 관측한 사실이 다른 규칙을 지난다. */
69
- const { accepted, rejected } = ingestCanonicalRecords(
70
- records as any,
71
- domainId,
72
- new Date(nowMs).toISOString(),
73
- /* 어느 트윈의 사실인가 — 마감된 구간의 이름이 이것으로 갈린다(커널 §`SubjectBasis`). */
74
- TwinEngine.factScope(domainId, instanceId)
75
- )
76
- for (const r of rejected) refused.push({ record: r.record, reason: (r.errors ?? []).join(' · ') })
77
-
78
- const days = await retentionDaysOf(domainId)
79
-
80
- const judged = judgeBackfill(accepted as any[], { nowMs, retentionDays: days })
81
- refused.push(...judged.refused)
82
- const keep = judged.keep
83
-
84
- if (!keep.length) {
85
- TwinEngine.recordIngestResult(
86
- domainId,
87
- instanceId,
88
- records.length,
89
- refused.map(r => ({ record: r.record, errors: [r.reason] })),
90
- nowMs,
91
- 0
92
- )
93
- return { written: 0, skipped: 0, refused }
94
- }
95
-
96
- /*
97
- * 이미 있는 것을 가려낸다 — 그 구간의 그 종류만 읽는다(색인이 받쳐 준다). 페이로드의 id 로 견주고,
98
- * 저장소 제약에 기대지 않는다(드라이버 다섯).
99
- */
100
- const times = keep.map(e => absoluteTime(e.eventTime)!.getTime())
101
- const fromAt = new Date(Math.min(...times))
102
- const toAt = new Date(Math.max(...times))
103
- const types = [...new Set(keep.map(e => String(e.eventType)))]
104
-
105
- const existing = await getRepository(TwinEvent)
106
- .createQueryBuilder('e')
107
- .select(['e.payload AS "payload"'])
108
- .where('e.domain = :domainId', { domainId })
109
- .andWhere('e.instanceId = :instanceId', { instanceId })
110
- .andWhere('e.eventType IN (:...types)', { types })
111
- .andWhere('e.eventTime BETWEEN :fromAt AND :toAt', { fromAt, toAt })
112
- .getRawMany<{ payload: unknown }>()
113
-
114
- const seen = new Set<string>()
115
- for (const row of existing) {
116
- const p: any = typeof row.payload === 'string' ? safeParse(row.payload) : row.payload
117
- const id = p?.eventId
118
- if (typeof id === 'string' && id) seen.add(id)
119
- }
120
-
121
- const { fresh, skipped } = splitAlreadyThere(keep, seen)
122
- if (!fresh.length) {
123
- TwinEngine.recordIngestResult(
124
- domainId,
125
- instanceId,
126
- records.length,
127
- refused.map(r => ({ record: r.record, errors: [r.reason] })),
128
- nowMs,
129
- skipped
130
- )
131
- return { written: 0, skipped, refused }
132
- }
133
-
134
- /*
135
- * 리비전은 **쓴 순서**다(일어난 순서가 아니다). 지난 사실이 지금 번호를 받는 것이 맞다 — 저널을
136
- * 시각으로 읽는 쪽은 `eventTime` 을 보고, 리비전은 같은 시각을 가릴 때만 쓴다.
137
- */
138
- const start = TwinEngine.journalHead(domainId, instanceId)
139
- const items = fresh.map((event, i) => ({ event, revision: start + i + 1 }))
140
-
141
- await TwinEngine.persistCarried(domainId, instanceId, items)
142
- TwinEngine.advanceJournalHead(domainId, instanceId, items.length)
143
-
144
- /*
145
- * 장부에 적는다 — **유입을 부르는 곳은 모두 적는다.** 한 경로만 빠지면 그 트윈의 유입 건강이
146
- * 「모름」으로 보인다(§`ingest-health-wiring`).
147
- *
148
- * 건네받지 못한 수(`undelivered`)는 **거절한 것과 이미 있어서 건너뛴 것의 합**이다. 건너뛴 것은
149
- * 버려진 것이 아니지만 이번에 새로 적히지도 않았다 — 「통과」로 세면 채운 양이 실제보다 커 보인다.
150
- */
151
- TwinEngine.recordIngestResult(
152
- domainId,
153
- instanceId,
154
- records.length,
155
- refused.map(r => ({ record: r.record, errors: [r.reason] })),
156
- nowMs,
157
- skipped
158
- )
159
- return { written: items.length, skipped, refused }
160
- }
161
-
162
- function safeParse(text: string): unknown {
163
- try {
164
- return JSON.parse(text)
165
- } catch {
166
- return undefined
167
- }
168
- }
@@ -1,86 +0,0 @@
1
- /*
2
- * 지난 기록 채우기의 **판단** — 저장소를 모르는 순수 함수.
3
- *
4
- * 무엇을 받고 무엇을 거절하는지가 이 파일에 다 있다. 저장소를 아는 코드(`backfill-period-facts`)는
5
- * 이 판단을 부르고 쓰기만 한다. 갈라 두는 이유는 이 저장소가 이미 쓰는 방식이다 —
6
- * 판단은 시험이 데이터베이스 없이 지킬 수 있어야 한다(§`event-type-split-shape`).
7
- */
8
-
9
- /** 이 길이 받는 사실 — 마감된 구간을 말하는 것들. */
10
- export const PERIOD_FACTS: readonly string[] = [
11
- 'energy.usage.period',
12
- 'energy.generation.period',
13
- 'energy.generation.price',
14
- 'energy.tariff.basis',
15
- 'energy.bill'
16
- ]
17
-
18
- export interface BackfillJudgement {
19
- /** 저널에 넣어도 되는 것. */
20
- keep: any[]
21
- /** 받지 않은 것과 그 이유 — 조용히 버리지 않는다. */
22
- refused: { record: unknown; reason: string }[]
23
- }
24
-
25
- /**
26
- * 무엇을 채울 수 있나.
27
- *
28
- * 세 가지로 거절한다.
29
- *
30
- * 마감된 구간이 아니다 상태를 바꾸는 사실을 저널에만 넣으면 상태와 저널이 갈라진다
31
- * 아직 오지 않은 시각 지난 기록이 아니다
32
- * 보존보다 오래됐다 넣어도 다음 정리에서 지워진다 — 조용히 사라지느니 거절한다
33
- */
34
- export function judgeBackfill(
35
- envelopes: readonly any[],
36
- opts: { nowMs: number; retentionDays?: number }
37
- ): BackfillJudgement {
38
- const keep: any[] = []
39
- const refused: { record: unknown; reason: string }[] = []
40
- const horizonMs = opts.retentionDays === undefined ? undefined : opts.nowMs - opts.retentionDays * 86_400_000
41
-
42
- for (const env of envelopes) {
43
- const type = String(env?.eventType ?? '')
44
- if (!PERIOD_FACTS.includes(type)) {
45
- refused.push({
46
- record: env,
47
- reason:
48
- `${type} 는 마감된 구간 사실이 아니다 — 이 길은 저널에만 쓰므로, 상태를 바꾸는 사실을 여기로 넣으면 ` +
49
- '상태와 저널이 갈라진다. 라이브 문으로 보내라'
50
- })
51
- continue
52
- }
53
- const atMs = Date.parse(String(env?.eventTime ?? ''))
54
- if (!Number.isFinite(atMs)) {
55
- refused.push({ record: env, reason: '사건 시각을 읽을 수 없다' })
56
- continue
57
- }
58
- if (atMs > opts.nowMs) {
59
- refused.push({ record: env, reason: `아직 오지 않은 시각이다(${env?.eventTime}) — 지난 기록이 아니다` })
60
- continue
61
- }
62
- if (horizonMs !== undefined && atMs < horizonMs) {
63
- refused.push({
64
- record: env,
65
- reason:
66
- `보존 기간(${opts.retentionDays}일)보다 오래됐다(${env?.eventTime}) — 넣어도 다음 정리에서 지워진다. ` +
67
- '더 뒤까지 보려면 보존 기간을 늘려야 한다'
68
- })
69
- continue
70
- }
71
- keep.push(env)
72
- }
73
-
74
- return { keep, refused }
75
- }
76
-
77
- /**
78
- * 이미 있는 것을 가려낸다 — **정체성은 내용에 있다**(커널 0.7.81).
79
- *
80
- * 저장소의 제약으로 막지 않는 이유는 드라이버가 다섯이고 충돌 처리가 제각각이기 때문이다.
81
- * 구간 단위로 한 번 읽어 가려내는 편이 이식성이 있고 값도 싸다.
82
- */
83
- export function splitAlreadyThere(keep: readonly any[], existingIds: ReadonlySet<string>): { fresh: any[]; skipped: number } {
84
- const fresh = keep.filter(e => typeof e?.eventId === 'string' && e.eventId && !existingIds.has(e.eventId))
85
- return { fresh, skipped: keep.length - fresh.length }
86
- }
@@ -1,3 +0,0 @@
1
- import { TwinBackfillResolver } from './twin-backfill-resolver.js'
2
-
3
- export const resolvers = [TwinBackfillResolver]
@@ -1,35 +0,0 @@
1
- import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
2
- import { ScalarObject } from '@things-factory/shell'
3
-
4
- import { backfillPeriodFacts } from './backfill-period-facts.js'
5
-
6
- /*
7
- * 지난 기록 채우기의 **문** — 커넥터가 트윈이 없던 동안의 날들을 뒤늦게 넣는다.
8
- *
9
- * ── 왜 문을 따로 두나 (2026-08-30) ────────────────────────────────────────
10
- * 라이브 유입과 판단이 다르다. 라이브는 트윈의 「지금」을 바꾸고, 이쪽은 저널에만 쓴다. 같은 문으로
11
- * 받으면 옛 표본이 가드에 막히거나 트윈의 시계가 과거로 끌린다(§`backfill-period-facts`).
12
- *
13
- * 레코드의 **모양은 라이브와 같다** — 커넥터가 다른 어휘를 배울 필요가 없다. 다른 것은 받는 종류뿐이고,
14
- * 그 판단은 커널의 유입과 `judgeBackfill` 이 한다.
15
- *
16
- * ── 왜 이 파일이 늦게 생겼나 ──────────────────────────────────────────────
17
- * 채우기 자체는 만들어 두고 **부르는 곳을 만들지 않아** 쓸 수 없는 채로 있었다. 8월 29일 발전량을
18
- * 되살리려다 드러났다. 같은 부류를 그날 두 번 겪었다(커널의 발전 기간 문도 없었다).
19
- */
20
- @Resolver()
21
- export class TwinBackfillResolver {
22
- /* 트윈의 모든 변경과 같은 게이트다(ADR-0027) — 저널에 사실을 적는 일이므로 변경이다. */
23
- @Directive('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
24
- @Mutation(returns => ScalarObject, {
25
- description:
26
- 'Backfill closed-period facts into a twin journal without touching its live state. Records use the same shape as live ingest; only closed-period facts are accepted (usage/generation periods, generation price, tariff basis, bill). Point-in-time observations are refused with a reason, as are times beyond journal retention. Re-running is safe: a period already present is skipped, because a closed period is identified by its content. Returns { written, skipped, refused }.'
27
- })
28
- async backfillTwinPeriodFacts(
29
- @Arg('instanceId') instanceId: string,
30
- @Arg('records', type => [ScalarObject]) records: unknown[],
31
- @Ctx() context: ResolverContext
32
- ): Promise<{ written: number; skipped: number; refused: { record: unknown; reason: string }[] }> {
33
- return await backfillPeriodFacts({ domainId: context.state.domain.id, instanceId, records })
34
- }
35
- }
@@ -1,3 +0,0 @@
1
- import { TwinControlMutation } from './twin-control-mutation.js'
2
-
3
- export const resolvers = [TwinControlMutation]
@@ -1,150 +0,0 @@
1
- import { twinError } from '../../engine/log.js'
2
- import { Arg, Ctx, Mutation, Query, Resolver, Directive } from 'type-graphql'
3
-
4
- import { validateScenario } from '@operato/ops-contract'
5
-
6
- import { ScalarObject } from '@things-factory/shell'
7
-
8
- import { getRepository } from '@things-factory/shell'
9
-
10
- import { TwinEngine } from '../../engine/index.js'
11
- import { TwinAuditEvent } from '../twin-audit/twin-audit-event.js'
12
- import { buildCommandAudit } from '../twin-audit/command-audit.js'
13
- /* 구동은 원본을 지난다(ADR-0029 §8) — 트윈 런타임을 직접 잡지 않는다. */
14
- import { routeControl, controlCapabilityOf } from '../reference/control-routing.js'
15
-
16
- /*
17
- * 트윈 Command·Scenario 채널 — 상향 mutation.
18
- * Command: runtime.dispatch(행위). Scenario: runtime.scenario.load/start/pause/setSpeed(예측 자극).
19
- * (State 하향은 twin-state subscription. tick 은 워커.)
20
- *
21
- * 인가: data 구독 리졸버와 대칭으로, 대상 인스턴스가 **호출자 도메인 소속**인지 검증한다(cross-tenant 커맨드 주입 차단).
22
- * command 채널은 sim 상태를 변이하므로 도메인 스코프가 필수.
23
- */
24
- @Resolver()
25
- export class TwinControlMutation {
26
- /** Command 채널 — 오더 hold/resume/release 등. 커널 dispatch 로 위임, ack{accepted,error} 반환. */
27
- @Directive('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
28
- @Mutation(returns => ScalarObject, { description: 'dispatch a twin command (order.hold/resume/release …). Returns {accepted, error?}.' })
29
- async dispatchTwinCommand(
30
- @Arg('instanceId') instanceId: string,
31
- @Arg('command', type => ScalarObject) command: any,
32
- @Ctx() context: ResolverContext
33
- ): Promise<{ accepted: boolean; error?: string; errorCode?: string; errorParams?: Record<string, string | number> }> {
34
- const domainId = context.state.domain?.id
35
- if (!domainId) return { accepted: false, error: 'no-domain', errorCode: 'no-domain' }
36
- /*
37
- * 라우팅은 엔진이 한다 — 예전에는 여기서 `inst.runtime.dispatch` 를 곧바로 불렀고, `runtime` 이
38
- * 시뮬에만 있어서 미러 트윈에서는 이 한 줄이 TypeError 로 터졌다(깔끔한 거절이 아니라 실패).
39
- * 권위(모드) × 성격(주석/액추에이션) 판정은 한 곳에만 둔다.
40
- */
41
- /* 원본을 그대로 감사에 넘긴다 — 무엇이 들어왔는지가 기록의 대상이다(정규화는 감사 모듈이 한다). */
42
- const cmdWithOrigin = command
43
- const ack = await TwinEngine.dispatchCommand(domainId, instanceId, command)
44
- /* 라이브 구조 변이(resource.add)는 저장 model 에도 반영 — 프로비저닝 편집기·재기동이 추가분을 잃지 않게. */
45
- if (ack?.accepted && command?.type === 'resource.add') {
46
- await TwinEngine.syncBoardEquipment(domainId, instanceId).catch(err => twinError('twin syncBoardEquipment fail', err))
47
- }
48
- /*
49
- * 감사 기록 — 승인 게이트가 앞을 막고, 이 줄이 뒤를 설명한다. 둘 다 있어야 "사람 손을 거쳤다" 를
50
- * 증명할 수 있다. 커널이 거절한 것도 남긴다 — 무엇을 시도했는지가 감사의 절반이다.
51
- *
52
- * 기록이 실패해도 커맨드 결과는 그대로 돌려준다. 감사가 본업을 막으면 안 되지만, 실패를 삼키지도
53
- * 않는다(로그에 남긴다) — 알리지 않고 안 남으면 나중에 "기록이 없다" 와 "일이 없었다" 를 구분 못 한다.
54
- */
55
- try {
56
- const audit = buildCommandAudit({ command: cmdWithOrigin, ack, actor: context.state.user, at: new Date() })
57
- const repo = getRepository(TwinAuditEvent)
58
- await repo.save(repo.create({ domain: context.state.domain, instanceId, ...audit }))
59
- } catch (err) {
60
- twinError(`[twin-control] command audit not recorded for "${instanceId}"`, err)
61
- }
62
-
63
- /* 거절 사유는 **언어 중립 코드**로 함께 돌려준다 — 화면이 `twin.cmderr.<code>` 로 사람 말을 만든다. */
64
- return { accepted: !!ack?.accepted, error: ack?.error, errorCode: ack?.errorCode, errorParams: ack?.errorParams }
65
- }
66
-
67
- /**
68
- * 구동 채널 — **원본을 지난다**(ADR-0029 §8).
69
- *
70
- * ── 무엇이 바뀌었나 (2026-08-19) ──────────────────────────────────────────
71
- * 예전에는 이 문이 `TwinEngine.runtime(...).scenario` 를 **직접** 잡았다. 시뮬만 할 수 있는 일(자극·배속·
72
- * 정지)이 계약 밖의 지름길로 들어온 셈이고, 실 시스템에는 그 자리가 아예 없었다. 이제 길은 하나다:
73
- * 트윈 → 그 트윈의 원본 → 어댑터가 **선언한** `control` 능력. 선언하지 않은 원본에는 문이 열리지 않고,
74
- * 그 사실을 사유 코드로 말한다(`not-declared`) — 실 WMS 가 정지되지 않는 것은 결손이 아니다.
75
- *
76
- * 반환을 Boolean 에서 객체로 바꿨다: 예전에는 거절 사유를 실을 자리가 없어 **로그로만** 남겼다.
77
- * 화면은 왜 안 되는지 알 수 없었다.
78
- */
79
- @Directive('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
80
- @Mutation(returns => ScalarObject, {
81
- description:
82
- "Drive the source behind a twin: stimulus | start | pause | speed | reset. The command goes through the source adapter's declared control capability — a source that does not declare it refuses with code 'not-declared' (a real system is not paused or seeded, and that is a fact rather than a gap). Returns { ok, code?, detail? }."
83
- })
84
- async controlTwinSource(
85
- @Arg('instanceId') instanceId: string,
86
- @Arg('action') action: string,
87
- @Ctx() context: ResolverContext,
88
- @Arg('scenario', type => ScalarObject, { nullable: true }) scenario?: any,
89
- @Arg('speed', { nullable: true }) speed?: number
90
- ): Promise<any> {
91
- const domainId = context.state.domain?.id
92
- if (!domainId) return { ok: false, code: 'no-domain' }
93
- const allowed = ['stimulus', 'start', 'pause', 'speed', 'reset']
94
- if (!allowed.includes(action)) return { ok: false, code: 'unsupported-action', detail: `one of ${allowed.join(' | ')}` }
95
- /*
96
- * **잘못된 선언은 문 앞에서 막는다.** 예전에는 검증 없이 실었고, 다음 tick 에서 `rate.meanPerHour` 를
97
- * 읽다 터져 **서버 프로세스가 내려갔다**(클라이언트가 보낸 값 하나로 앱 전체가 죽었다). 규칙은 커널이
98
- * 들고 있다(계약의 주인) — 호스트가 따로 만들면 방언이 생긴다.
99
- */
100
- if (action === 'stimulus') {
101
- const v = validateScenario(scenario)
102
- if (v.ok === false) return { ok: false, code: 'invalid', detail: v.errorCode, params: v.errorParams }
103
- }
104
- if (action === 'speed' && !(Number(speed) > 0)) return { ok: false, code: 'invalid', detail: 'speed must be greater than 0' }
105
-
106
- /*
107
- * **구동도 사람이 한 일이다 — 남긴다** (ADR-0029 §1 결정 C, 2026-08-19).
108
- *
109
- * 이 문은 감사를 아예 남기지 않았다. 그런데 자극을 바꾸고 배속을 올리고 원본을 멈추는 것은 그 트윈의
110
- * 사실을 바꾸는 행위다 — 커맨드 채널은 남기는데 이쪽이 비어 있으면, 나중에 「무엇이 이 공장을
111
- * 흔들었나」에 답할 수 없다.
112
- *
113
- * 결정 C 그대로: 게이트는 여기 남고(위 `@privilege`), **원본의 답을 같은 행에 닫는다.** 답을 못 받으면
114
- * `unknown` 이다 — 성공으로 적지 않는다.
115
- */
116
- let result: { ok: boolean; code?: string; detail?: string }
117
- try {
118
- result = await routeControl(domainId, instanceId, { action: action as any, scenario, speed: speed != null ? Number(speed) : undefined })
119
- } catch (e: any) {
120
- result = { ok: false, code: 'failed', detail: e?.message ?? 'control failed' }
121
- }
122
- try {
123
- const audit = buildCommandAudit({
124
- /* 커맨드 채널과 같은 모양으로 적는다 — 감사를 읽는 쪽이 두 어휘를 배우지 않게. */
125
- command: { type: `source.${action}`, origin: 'user', args: { ...(scenario ? { scenario } : {}), ...(speed != null ? { speed } : {}) } },
126
- /* 게이트는 통과했다(여기까지 왔다) — 그 사실과 원본의 답은 다른 칸이다. */
127
- ack: { accepted: true },
128
- source: { answered: typeof result?.ok === 'boolean', ok: result?.ok, code: result?.code },
129
- actor: context.state.user,
130
- at: new Date()
131
- })
132
- const repo = getRepository(TwinAuditEvent)
133
- await repo.save(repo.create({ domain: context.state.domain, instanceId, ...audit }))
134
- } catch (err) {
135
- /* 기록이 실패해도 결과는 돌려준다 — 다만 삼키지 않는다(「기록 없음」과 「일 없음」을 구별해야 한다). */
136
- twinError(`[twin-control] source control audit not recorded for "${instanceId}"`, err)
137
- }
138
- return result
139
- }
140
-
141
- /** 이 트윈의 원본이 **무엇을 받을 수 있나** — 화면이 버튼을 열기 전에 묻는 자리. */
142
- @Query(returns => ScalarObject, {
143
- description: "What the source behind this twin can do: its declared capabilities ('live', 'control'). Empty when the twin has no source or its adapter declares nothing."
144
- })
145
- async twinSourceCapability(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any> {
146
- const domainId = context.state.domain?.id
147
- if (!domainId) return { capabilities: [] }
148
- return controlCapabilityOf(domainId, instanceId)
149
- }
150
- }
@@ -1,3 +0,0 @@
1
- import { TwinEvent } from './twin-event.js'
2
-
3
- export const entities = [TwinEvent]
@@ -1,53 +0,0 @@
1
- /*
2
- * 저널을 **상한까지만 센다** — 세는 것도 읽는 것이다 (2026-08-22).
3
- *
4
- * ── 왜 (실측) ───────────────────────────────────────────────────────────────
5
- * 조건에 맞는 행을 전부 세는 질의는 행을 실어 오지 않아도 비싸다. 개발 저널에서 트윈 하나가 358만
6
- * 행이었고 그 한 번이 **5.32초**였다. 색인만 상한까지 읽으면 같은 조건에서 **0.04초**다(130배).
7
- *
8
- * 그 5초 동안 이벤트 루프는 다른 요청을 처리하지 못한다 — 이력 화면 한 번, 준비도 화면 한 번이
9
- * 사용자에게는 「눌렀는데 아무 반응이 없다」로 나타난다. 준비도 화면은 그런 세기를 **넷** 했다.
10
- *
11
- * ── 규율 ────────────────────────────────────────────────────────────────────
12
- * 세는 목적이 둘 중 하나다.
13
- * ① **판정** — 「한 건이라도 있나」. 그때는 하나만 찾으면 끝이다(`anyJournalRow`).
14
- * ② **표시** — 사람에게 수를 보인다. 그때는 상한까지 세고, 넘으면 **모른다고 말한다**(`countUpTo`).
15
- *
16
- * 상한을 넘었을 때 상한값을 전체로 적으면 화면이 거짓을 말한다. 그래서 `capped` 를 함께 낸다 —
17
- * 없는 것과 모르는 것을 가르는 이 프로젝트의 규율이 세기에도 같이 적용된다.
18
- */
19
- import type { ObjectLiteral, Repository } from 'typeorm'
20
-
21
- /** 표시용 세기의 기본 상한 — 화면이 한 번에 보여 줄 범위를 훨씬 넘는 값. */
22
- export const JOURNAL_COUNT_CAP = 10_000
23
-
24
- export interface CappedCount {
25
- /** 센 수. `capped` 면 상한까지만 센 값이므로 **전체가 아니다**. */
26
- count: number
27
- /** 상한을 넘었나 — 그때 전체 수는 모르는 것이 사실이다. */
28
- capped: boolean
29
- }
30
-
31
- /**
32
- * 상한까지만 세기 — 키 컬럼만 읽으므로 행 본문을 만들지 않는다.
33
- *
34
- * `count()` 를 쓰지 않는 이유: 그것은 상한을 받지 않는다(조건에 맞는 전부를 센다).
35
- */
36
- export async function countUpTo<T extends ObjectLiteral>(
37
- repo: Repository<T>,
38
- where: any,
39
- cap = JOURNAL_COUNT_CAP
40
- ): Promise<CappedCount> {
41
- const rows = await repo.find({ where, select: ['id'] as any, take: cap + 1 })
42
- return rows.length > cap ? { count: cap, capped: true } : { count: rows.length, capped: false }
43
- }
44
-
45
- /**
46
- * 한 건이라도 있나 — **판정에는 수가 필요 없다.**
47
- *
48
- * 예전에는 전부 센 뒤 `> 0` 을 봤다. 그 답을 얻는 데 358만 행을 세고 있었다.
49
- */
50
- export async function anyJournalRow<T extends ObjectLiteral>(repo: Repository<T>, where: any): Promise<boolean> {
51
- const rows = await repo.find({ where, select: ['id'] as any, take: 1 })
52
- return rows.length > 0
53
- }