@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
- /*
2
- * 트윈 로그의 문 — **모든 줄에 시각을 찍는다.** 순수(프레임워크 의존 없음).
3
- *
4
- * ── 왜 필요한가 (2026-08-22) ────────────────────────────────────────────────
5
- * 「서버가 왜 느린가」를 조사하면서 루프가 55초 막힌 것을 계기로 알아냈는데(`loop-lag.ts`),
6
- * **그 시각에 무슨 일이 있었는지 로그에서 찾을 수 없었다.** 트윈의 로그가 `console.log` 로 나가
7
- * 시각이 없었기 때문이다. 프레임워크 로그(`2026-08-22T05:54:12+09:00 info: …`)와 섞여 있어서, 어느
8
- * 줄이 언제 찍혔는지 앞뒤 프레임워크 줄로 짐작해야 했다.
9
- *
10
- * ── 왜 프레임워크 로거를 그대로 쓰지 않나 ──────────────────────────────────
11
- * 재발명을 피하려고 `@things-factory/env` 의 `logger` 를 쓰려 했는데, 실측으로 막혔다: 앱 **밖**에서는
12
- * 그 로거에 전송지가 하나도 없다(설정이 앱에서 주입된다). 그래서 시험·도구에서 부르면
13
- *
14
- * [winston] Attempt to write logs with no transports … {"message":"…","level":"info"}
15
- *
16
- * 가 나오고 **메시지 자체가 사라진다.** 트윈 엔진은 시험과 CLI 도구에서도 불려 다니므로, 그 조건에서
17
- * 로그가 없어지는 것은 바꿔선 안 되는 거동이다(로그가 사라지는 것이 지금 문제의 원인이었다).
18
- *
19
- * 그래서 **싱크는 그대로 두고**(console) 빠진 사실 하나만 채운다 — 시각. 형식은 프레임워크와 같은
20
- * 모양으로 맞춰 한 파일에서 섞여 읽히게 하고, **밀리초까지** 남긴다(계기의 값이 epoch ms 라
21
- * 초 단위로는 같은 초 안의 순서를 가릴 수 없다).
22
- */
23
-
24
- /** 두 자리·세 자리 0 채우기 — 형식이 흔들리면 정렬해 읽을 수 없다. */
25
- const p2 = (n: number) => String(n).padStart(2, '0')
26
- const p3 = (n: number) => String(n).padStart(3, '0')
27
-
28
- /**
29
- * 지역 시각 + 오프셋 — `2026-08-22T05:54:12.345+09:00`.
30
- *
31
- * UTC 로 찍지 않는다: 이 로그를 읽는 사람은 현장의 시각으로 이야기하고, 프레임워크의 다른 줄도
32
- * 지역 시각이다. 두 줄이 다른 기준이면 나란히 놓고 읽을 수 없다.
33
- */
34
- export function stamp(at: Date = new Date()): string {
35
- const off = -at.getTimezoneOffset()
36
- const sign = off >= 0 ? '+' : '-'
37
- const abs = Math.abs(off)
38
- return (
39
- `${at.getFullYear()}-${p2(at.getMonth() + 1)}-${p2(at.getDate())}` +
40
- `T${p2(at.getHours())}:${p2(at.getMinutes())}:${p2(at.getSeconds())}.${p3(at.getMilliseconds())}` +
41
- `${sign}${p2(Math.floor(abs / 60))}:${p2(abs % 60)}`
42
- )
43
- }
44
-
45
- /**
46
- * 인자 여럿을 한 줄로 — **어떤 인자도 버리지 않는다.**
47
- *
48
- * `console.error(msg, err)` 처럼 쓰던 자리가 많다. 프레임워크 로거에 그대로 넘기면 두 번째 인자는
49
- * meta 로 들어가 우리 형식(`message` 만 찍는다)에서 **오류 없이 사라진다.** 그래서 여기서 문자열로 편다.
50
- * 오류는 스택까지 — 스택이 없으면 「어디서 났나」를 잃는다.
51
- */
52
- export function line(args: unknown[]): string {
53
- return args
54
- .map(a => {
55
- if (typeof a === 'string') return a
56
- if (a instanceof Error) return a.stack ?? a.message
57
- if (a === undefined) return 'undefined'
58
- if (a === null) return 'null'
59
- try {
60
- return typeof a === 'object' ? JSON.stringify(a) : String(a)
61
- } catch {
62
- /* 순환 참조 등 — 값을 못 적어도 **무엇이 있었다는 사실**은 남긴다. */
63
- return String(a)
64
- }
65
- })
66
- .join(' ')
67
- }
68
-
69
- /* 수준 표기는 프레임워크와 같은 낱말을 쓴다(`info`·`warn`·`error`) — 같은 파일에서 걸러 읽는다. */
70
- export const twinLog = (...args: unknown[]): void => console.log(`${stamp()} info: ${line(args)}`)
71
- export const twinWarn = (...args: unknown[]): void => console.warn(`${stamp()} warn: ${line(args)}`)
72
- export const twinError = (...args: unknown[]): void => console.error(`${stamp()} error: ${line(args)}`)
@@ -1,120 +0,0 @@
1
- /*
2
- * 이벤트 루프 지체 — **화면이 느린 이유를 지어내지 않기 위해.** 순수(import 없음).
3
- *
4
- * ── 왜 필요한가 (2026-08-21) ────────────────────────────────────────────────
5
- * 「UI 반응성이 느리다」를 진단하려 했는데, 있는 계기판으로는 답이 나오지 않았다. `twinLoad` 는 **트윈의
6
- * 계측된 작업**만 재고, `processCpuRatio` 는 프로세스 전체를 재지만 **언제 얼마나 멈췄나**를 말하지
7
- * 못한다. 밖에서 HTTP 지연을 재 보니 같은 요청이 44ms 와 5.8초로 갈라졌는데, 그 5.8초가 트윈 때문인지
8
- * webpack 재빌드 때문인지 남의 재기동 때문인지 **가릴 근거가 없었다.**
9
- *
10
- * 근거 없이 원인을 고르면 엉뚱한 곳을 고친다. 그래서 루프가 실제로 얼마나 막혔는지를 잰다.
11
- *
12
- * ── 어떻게 재나 ─────────────────────────────────────────────────────────────
13
- * 일정 간격으로 깨어나는 타이머를 두고, **예정 시각과 실제 시각의 차이**를 본다. 루프가 막혀 있었으면
14
- * 그만큼 늦게 깨어난다. 재는 비용은 그 차이 계산 하나뿐이다(창마다 값 다섯).
15
- *
16
- * 이 값은 **원인을 말하지 않는다** — 「200ms 이상 막힌 일이 이 창에서 세 번, 가장 긴 것은 4.6초」까지가
17
- * 사실이다. 원인은 그 시각의 트윈 부하(`twinLoad`)와 프로세스 CPU 와 나란히 놓고 사람이 가린다.
18
- * 재지 않은 것을 0 으로 적지 않는다 — 한 번도 깨어나지 않았으면 `null` 이다.
19
- */
20
-
21
- /** 표본 간격(ms) — 촘촘할 필요가 없다. 긴 정체를 놓치지 않는 정도면 된다. */
22
- export const LAG_SAMPLE_MS = 500
23
- /** 이 값을 넘는 지체만 「정체」로 센다(ms). 사람이 화면에서 느끼기 시작하는 크기. */
24
- export const LAG_STALL_MS = 200
25
- /** 창 길이(ms) — `twinLoad` 의 창과 같은 크기로 두어 나란히 읽는다. */
26
- export const LAG_WINDOW_MS = 10_000
27
-
28
- export interface LoopLagWindow {
29
- /** 이 창에서 가장 길게 막힌 시간(ms). */
30
- maxMs: number
31
- /** 정체(문턱 초과) 횟수. */
32
- stalls: number
33
- /** 표본 수 — 분모다. */
34
- samples: number
35
- /** 지체 합(ms) — 평균은 읽는 쪽에서 낸다. */
36
- totalMs: number
37
- /** 창이 열린 시각. */
38
- startMs: number
39
- }
40
-
41
- export interface LoopLagView {
42
- /** 마지막으로 닫힌 창 — 「지금 어떤가」. 아직 한 창도 안 지났으면 null. */
43
- recent: (LoopLagWindow & { endMs: number }) | null
44
- /** 기동 이후 누적. */
45
- total: LoopLagWindow
46
- /** 기동 이후 가장 길게 막힌 시각(ms, epoch) — 언제였는지가 원인을 가리는 데 쓰인다. */
47
- worstAtMs: number | null
48
- /** 표본 간격 — 읽는 쪽이 이 값보다 짧은 정체는 못 본다는 것을 알아야 한다. */
49
- sampleMs: number
50
- /** 정체로 세는 문턱. */
51
- stallMs: number
52
- }
53
-
54
- const emptyWindow = (startMs: number): LoopLagWindow => ({ maxMs: 0, stalls: 0, samples: 0, totalMs: 0, startMs })
55
-
56
- export class LoopLagSampler {
57
- private window: LoopLagWindow
58
- private closed: (LoopLagWindow & { endMs: number }) | null = null
59
- private total: LoopLagWindow
60
- private worstAtMs: number | null = null
61
- private timer: any
62
- private expectedMs: number
63
-
64
- private sampleMs: number
65
- private stallMs: number
66
- private windowMs: number
67
- private now: () => number
68
-
69
- /* 생성자 파라미터 프로퍼티(`private x = …`)는 쓰지 않는다 — 시험이 소스를 그대로 실행하는데
70
- (타입 제거 실행 방식) 그 문법은 지원되지 않아 파일 전체가 열리지 않는다. */
71
- constructor(sampleMs = LAG_SAMPLE_MS, stallMs = LAG_STALL_MS, windowMs = LAG_WINDOW_MS, now: () => number = Date.now) {
72
- this.sampleMs = sampleMs
73
- this.stallMs = stallMs
74
- this.windowMs = windowMs
75
- this.now = now
76
- const t = this.now()
77
- this.window = emptyWindow(t)
78
- this.total = emptyWindow(t)
79
- this.expectedMs = t + sampleMs
80
- }
81
-
82
- /** 표본을 하나 넣는다 — 타이머가 부르고, 시험은 직접 부른다(시계를 밀어 넣어 잰다). */
83
- sample(atMs = this.now()): number {
84
- const lag = Math.max(0, atMs - this.expectedMs)
85
- this.expectedMs = atMs + this.sampleMs
86
- for (const w of [this.window, this.total]) {
87
- w.samples += 1
88
- w.totalMs += lag
89
- if (lag > this.stallMs) w.stalls += 1
90
- if (lag > w.maxMs) w.maxMs = lag
91
- }
92
- if (lag >= this.total.maxMs && lag > this.stallMs) this.worstAtMs = atMs
93
- if (atMs - this.window.startMs >= this.windowMs) {
94
- this.closed = { ...this.window, endMs: atMs }
95
- this.window = emptyWindow(atMs)
96
- }
97
- return lag
98
- }
99
-
100
- /** 계기판이 읽는 값. **한 창도 닫히지 않았으면 `recent` 는 null** — 채우는 중인 창은 과소 집계다. */
101
- view(): LoopLagView {
102
- return { recent: this.closed, total: this.total, worstAtMs: this.worstAtMs, sampleMs: this.sampleMs, stallMs: this.stallMs }
103
- }
104
-
105
- /** 표본 타이머 기동(1회) — 프로세스 종료를 막지 않는다. */
106
- start(): void {
107
- if (this.timer) return
108
- this.timer = setInterval(() => this.sample(), this.sampleMs)
109
- if (typeof this.timer?.unref === 'function') this.timer.unref()
110
- }
111
-
112
- stop(): void {
113
- if (!this.timer) return
114
- clearInterval(this.timer)
115
- this.timer = undefined
116
- }
117
- }
118
-
119
- /** 프로세스 하나의 루프를 재는 것이므로 표본기도 하나다. */
120
- export const loopLag = new LoopLagSampler()
@@ -1,91 +0,0 @@
1
- /*
2
- * 실측 소요 추정기 — **이력에서 배운 값이 상수·선언값을 이긴다.**
3
- *
4
- * 배경(operato-twin design/plans/simulation-spec.md §5-4): 소요시간을 명세로 받을 수 있게 됐지만
5
- * 명세는 선언이다 — 그 현장에서 실제로 얼마 걸리는지는 저널이 안다. `gap-analytics` 는 지표 수준의
6
- * 편향만 배웠고(예측값 보정), **공정별 소요를 추정기로 되먹이는 경로는 없었다.**
7
- *
8
- * 여기서 하는 일: KPI 폴드가 작업 종류별로 낸 **작업시간(착수→완료) p50** 을 그 종류의 소요로 쓴다.
9
- * 리드타임(생성→완료)이 아니라 작업시간을 쓰는 이유: 리드타임에는 **대기가 섞여 있고**, 대기는
10
- * 시뮬레이션이 자원 경합으로 스스로 만들어야 하는 값이다. 대기를 소요에 넣으면 이중 계산이 된다.
11
- *
12
- * **평균만 배우면 대기와 병목을 과소평가한다.** 소요가 늘 정확히 같으면 줄이 생기지 않는다 — 현장의
13
- * 줄은 흔들림에서 나온다. 그래서 p50 만이 아니라 **관측된 퍼짐(p10..p90)** 을 함께 넘기고, 표본은
14
- * 커널이 자기 난수로 뽑는다(fork 결정성). 양쪽 꼬리를 다 관측에서 가져오는 이유: p90 만 있으면
15
- * 아래쪽을 위쪽에서 거울처럼 베껴야 하는데 그건 발명이다.
16
- *
17
- * 정직 규율:
18
- * - 표본이 적으면 쓰지 않는다(`minSamples`). 한두 건의 p50 은 그 현장의 값이 아니다.
19
- * - 'unknown' 축은 쓰지 않는다 — 종류를 모르는 기록을 특정 종류의 근거로 삼을 수 없다.
20
- * - 퍼짐이 성립하지 않으면(p10 ≥ p90, 또는 0) **퍼짐 없이 평균만** 넘긴다. 없는 흔들림을 만들지 않는다.
21
- * - 무엇을 배웠고 무엇을 표본 부족으로 버렸는지 함께 낸다(알리지 않고 일부만 반영하지 않는다).
22
- */
23
-
24
- /** 커널 `DurationEstimate` 와 같은 모양(커널 타입에 의존하지 않기 위해 구조로 맞춘다). */
25
- export interface MeasuredEstimate {
26
- meanMs: number
27
- spread?: { distribution: 'triangular'; minMs: number; maxMs: number; modeMs: number }
28
- }
29
-
30
- export interface MeasuredEstimatorResult {
31
- estimator?: {
32
- estimate(ctx: { kind: string; fromNode: string; toNode: string; resourceKind?: string }): MeasuredEstimate | undefined
33
- }
34
- /** 작업 종류 → 실측 소요(ms). 추정기가 답하는 종류들. */
35
- learned: Record<string, number>
36
- /** 퍼짐까지 배운 종류 — 평균만 배운 것과 구별한다(변동 없는 소요는 대기를 과소평가한다). */
37
- spreads: Record<string, { minMs: number; maxMs: number }>
38
- /** 표본이 모자라 쓰지 않은 종류와 그 건수 — 배우지 못한 것을 밝힌다. */
39
- skipped: { kind: string; count: number }[]
40
- minSamples: number
41
- }
42
-
43
- /** 기본 표본 하한 — 이보다 적으면 그 종류는 배우지 않는다(작은 표본의 p50 을 현장 값으로 승격 금지). */
44
- export const DEFAULT_MIN_SAMPLES = 5
45
-
46
- /**
47
- * 작업 종류별 KPI 그룹에서 추정기를 만든다(순수 — DB·커널 모름).
48
- * `groups` 는 `computeTwinKpi({ groupBy: 'taskKind' })` 의 `groups.items` 를 그대로 넘긴다.
49
- */
50
- export function buildMeasuredEstimator(
51
- groups: { key: string; workTime?: { count: number; p10Ms?: number; p50Ms: number; p90Ms?: number } }[] | undefined,
52
- opts: { minSamples?: number } = {}
53
- ): MeasuredEstimatorResult {
54
- const minSamples = opts.minSamples ?? DEFAULT_MIN_SAMPLES
55
- const learned: Record<string, number> = {}
56
- const spreads: Record<string, { minMs: number; maxMs: number }> = {}
57
- const estimates: Record<string, MeasuredEstimate> = {}
58
- const skipped: { kind: string; count: number }[] = []
59
- for (const g of groups ?? []) {
60
- if (!g?.key || g.key === 'unknown') continue
61
- const w = g.workTime
62
- const count = w?.count ?? 0
63
- const p50 = w?.p50Ms ?? 0
64
- if (count < minSamples || !(p50 > 0)) { skipped.push({ kind: g.key, count }); continue }
65
- const mean = Math.round(p50)
66
- learned[g.key] = mean
67
- /* 퍼짐은 **관측된 두 꼬리**로만 만든다. 한쪽이라도 없거나 구간이 성립하지 않으면 평균만 넘긴다. */
68
- const lo = w?.p10Ms
69
- const hi = w?.p90Ms
70
- if (typeof lo === 'number' && typeof hi === 'number' && lo > 0 && hi > lo) {
71
- const minMs = Math.round(lo)
72
- const maxMs = Math.round(hi)
73
- spreads[g.key] = { minMs, maxMs }
74
- estimates[g.key] = { meanMs: mean, spread: { distribution: 'triangular', minMs, maxMs, modeMs: mean } }
75
- } else {
76
- estimates[g.key] = { meanMs: mean }
77
- }
78
- }
79
- if (!Object.keys(learned).length) return { learned, spreads, skipped, minSamples }
80
- return {
81
- learned,
82
- spreads,
83
- skipped,
84
- minSamples,
85
- estimator: {
86
- estimate(ctx) {
87
- return estimates[ctx.kind]
88
- }
89
- }
90
- }
91
- }
@@ -1,89 +0,0 @@
1
- /*
2
- * 실측 양품률 추정기 — **이력에서 배운 수율이 선언값·상수를 이긴다.**
3
- *
4
- * ── 왜 필요했나 (2026-08-19) ────────────────────────────────────────────────
5
- * 소요시간에는 이력 층이 있었다(`measured-estimator`): 저널이 「그 현장에서 실제로 얼마 걸렸나」를 안다.
6
- * 수율에는 그 층이 없었다 — 양품률의 기본값은 커널 소스의 상수(0.8)였고, **그 상수가 불량 과다 주목
7
- * 신호까지 만들었다.** 초기 라인이든 성숙한 라인이든 같은 수로 판정된다는 뜻이다.
8
- *
9
- * 그런데 이력을 만들 재료도 없었다: 양품/불량은 설비 누적 카운터(종류를 모른다)와 EPCIS disposition
10
- * (종류를 모른다)에만 남았다. 그래서 커널이 **판정을 일어난 자리(작업 완료)에 적게** 했고
11
- * (`TaskStatusDelta.outcome`), 폴드가 축으로 들고(`TaskFacets.outcome`), KPI 가 종류별로 센다
12
- * (`KpiGroup.quality`). 이 파일은 그 수를 비율로 바꿔 커널 시임에 넣는다.
13
- *
14
- * ── 정직 규율 (소요 추정기와 같은 것) ───────────────────────────────────────
15
- * - **표본이 적으면 쓰지 않는다**(`minSamples`). 세 건 중 한 건 불량은 「불량률 33%」가 아니다.
16
- * - `'unknown'` 축은 쓰지 않는다 — 종류를 모르는 기록을 특정 종류의 근거로 삼을 수 없다.
17
- * - **판정이 없는 작업은 분모에 넣지 않는다.** KPI 가 이미 그렇게 세지만(`quality` 는 판정된 것만),
18
- * 여기서도 `good + scrap` 만 쓴다 — `tasks` 를 분모로 쓰면 이동·체류가 섞여 양품률이 낮게 나온다.
19
- * - **0 도 사실이다.** 전부 불량이면 0 을 배운다(그 현장이 그랬다). 「값이 없다」와 구별해 다룬다 —
20
- * 커널이 `0` 을 받으면 전량 불량으로 굴러가고, 그것이 관측과 같은 결론이다.
21
- * - 무엇을 배웠고 무엇을 표본 부족으로 버렸는지 함께 낸다(알리지 않고 일부만 반영하지 않는다).
22
- */
23
-
24
- /** 커널 `YieldEstimator` 와 같은 모양(커널 타입에 의존하지 않기 위해 구조로 맞춘다). */
25
- export interface YieldEstimatorResult {
26
- estimator?: {
27
- estimate(ctx: { kind: string }): number | undefined
28
- }
29
- /** 작업 종류 → 실측 양품률(0..1). 추정기가 답하는 종류들. */
30
- learned: Record<string, number>
31
- /** 종류별 표본 — 배운 값의 근거 크기(화면·로그가 「몇 건에서 배웠나」를 말할 수 있게). */
32
- samples: Record<string, { good: number; scrap: number }>
33
- /** 표본이 모자라 쓰지 않은 종류와 판정 건수 — 배우지 못한 것을 밝힌다. */
34
- skipped: { kind: string; judged: number }[]
35
- minSamples: number
36
- }
37
-
38
- /**
39
- * 기본 표본 하한 — 판정 20건 미만이면 그 종류는 배우지 않는다.
40
- *
41
- * 소요(5건)보다 높게 잡는 이유: 비율은 **드문 사건**을 재는 값이다. 불량률 5% 인 공정에서 20건을 봐도
42
- * 불량은 한 건이고, 그 한 건이 있고 없음으로 비율이 0% 와 5% 사이를 오간다. 낮게 잡으면 추정기가
43
- * 이력이라는 이름으로 잡음을 실어 보낸다.
44
- */
45
- export const DEFAULT_YIELD_MIN_SAMPLES = 20
46
-
47
- /**
48
- * 작업 종류별 KPI 그룹에서 양품률 추정기를 만든다(순수 — DB·커널 모름).
49
- * `groups` 는 `computeTwinKpi({ groupBy: 'taskKind' })` 의 `groups.items` 를 그대로 넘긴다.
50
- */
51
- export function buildYieldEstimator(
52
- groups: { key: string; quality?: { good: number; scrap: number } }[] | undefined,
53
- opts: { minSamples?: number } = {}
54
- ): YieldEstimatorResult {
55
- const minSamples = opts.minSamples ?? DEFAULT_YIELD_MIN_SAMPLES
56
- const learned: Record<string, number> = {}
57
- const samples: Record<string, { good: number; scrap: number }> = {}
58
- const skipped: { kind: string; judged: number }[] = []
59
-
60
- for (const g of groups ?? []) {
61
- if (!g?.key || g.key === 'unknown') continue
62
- const good = g.quality?.good ?? 0
63
- const scrap = g.quality?.scrap ?? 0
64
- const judged = good + scrap
65
- /* 판정이 아예 없는 종류는 **건너뛴 것이 아니다** — 품질을 가리지 않는 공정(이동·체류)이 정상이다. */
66
- if (judged === 0) continue
67
- if (judged < minSamples) {
68
- skipped.push({ kind: g.key, judged })
69
- continue
70
- }
71
- learned[g.key] = good / judged
72
- samples[g.key] = { good, scrap }
73
- }
74
-
75
- const kinds = Object.keys(learned)
76
- if (!kinds.length) return { learned, samples, skipped, minSamples }
77
-
78
- return {
79
- /*
80
- * 시임은 **무상태**다(커널이 fork 할 때 참조를 공유한다 — 소요 추정기와 같은 규약).
81
- * 배우지 않은 종류에는 `undefined` 를 답한다: 그러면 커널이 선언값 → 상수로 내려간다.
82
- */
83
- estimator: { estimate: ({ kind }) => learned[kind] },
84
- learned,
85
- samples,
86
- skipped,
87
- minSamples
88
- }
89
- }
@@ -1,162 +0,0 @@
1
- /*
2
- * 모델 근거 — **배운 모델에만 보정을 적용하기 위한 비교.**
3
- *
4
- * 예측 출력 보정(P3.2 `twinLearnCalibration`)은 "우리 모델이 늘 이만큼 적게 본다" 를 배워 결과를
5
- * 밀어 준다. 그 학습은 **그때의 모델**을 전제로 한다. 그런데 소요시간 추정기(실측·거리계산)와 공정
6
- * 명세가 들어오면서 모델 자체가 바뀔 수 있게 됐다 — 모델이 이미 그 편향을 잃었는데 보정이 또 밀어
7
- * 주면 **이중 보정**이 되어 정확도가 나빠진다. 학습 시점의 accAfter 도 더는 유효하지 않다.
8
- *
9
- * 그래서 보정 기록에 **그때 모델의 근거**를 함께 남기고, 적용 전에 지금 근거와 비교한다. 달라졌으면
10
- * 적용하지 않고 **그 사실을 응답에 싣는다**(오류 없이 사라지면 사용자는 학습이 왜 안 듣는지 모른다).
11
- *
12
- * 비교는 **상대 허용오차**로 한다(양자화 지문이 아니라). 실측 p50 은 새 기록이 쌓일 때마다 1~2초씩
13
- * 흔들리는데, 값을 버킷으로 합쳐 비교하면 버킷 경계에 걸린 값이 1초 드리프트로도 달라져 버린다 —
14
- * "작은 드리프트로 학습을 무효화하지 않는다" 는 목적을 경계에서 못 지킨다. 비율로 비교하면 어디서든
15
- * 같은 규칙이 성립한다: 10% 이내는 같은 모델, 30초→47초(57%)는 다른 모델.
16
- *
17
- * 재료는 호스트가 아는 것들이다(커널 API 에 의존하지 않아 발행 상태와 무관하게 동작한다):
18
- * ① 실측으로 배운 작업 종류별 소요 ② 자원 종류별 속도 ③ 선언된 공정 소요.
19
- */
20
-
21
- /**
22
- * 허용오차의 **기본값** — 선언이 아무 말도 없을 때만 쓴다.
23
- *
24
- * 10% 는 근거에서 나온 수가 아니라 **판단값**이다(그 사실을 적어 두는 것이 이 주석의 목적이다). 그리고
25
- * 단일 잣대로 쓰면 틀린다 — 우리 트레일러 템플릿이 그것을 보여 준다: 용접은 변동폭을 `PT55M~PT1H35M`
26
- * (선언 소요 `PT1H10M` 기준 −21%~+36%)로 **스스로 선언한다.** 10% 관문은 그 공정의 **정상 변동조차**
27
- * "다른 모델" 로 판정해 보정을 끊는다. 반대로 1% 변동도 치명적인 공정에는 10% 가 너무 느슨하다.
28
- *
29
- * 그래서 허용오차는 **그 공정이 선언한 변동폭에서 나온다**(§toleranceOf). 선언이 있으면 선언이 이기고,
30
- * 없을 때만 이 값으로 떨어진다 — 도메인 설정을 새로 만들지 않는다(현장이 이미 말한 것을 읽는다).
31
- */
32
- export const BASIS_TOLERANCE = 0.1
33
-
34
- export interface ModelBasis {
35
- /** 작업 종류 → 실측 소요(ms). `buildMeasuredEstimator().learned`. */
36
- measured?: Record<string, number>
37
- /** 자원 종류 → 속도(m/s). `buildTravelEstimator().speedsByKind`. */
38
- speeds?: Record<string, number>
39
- /**
40
- * 선언된 공정 — key + ISO 8601 원문(문자열은 그대로 비교한다: 선언이 바뀌면 다른 모델).
41
- *
42
- * **변동폭도 지문에 든다.** 변동폭이 허용오차를 정하므로(§toleranceOf), 그것이 바뀌었는데 "같은 모델"
43
- * 이라고 하면 판정의 잣대가 알리지 않고 바뀐 채로 학습이 이어진다.
44
- */
45
- declared?: DeclaredOperation[]
46
- }
47
-
48
- /** 선언된 공정 하나 — 소요와 변동폭(모델의 `operations` 원형에서 필요한 만큼만). */
49
- export interface DeclaredOperation {
50
- key: string
51
- duration?: string
52
- variability?: { distribution?: string; min?: string; max?: string; mode?: string }
53
- }
54
-
55
- /** ISO 8601 기간 → 밀리초. 읽을 수 없으면 `undefined`(짐작해 고치지 않는다). */
56
- function isoMs(iso?: string): number | undefined {
57
- if (!iso) return undefined
58
- const m = /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:([\d.]+)S)?)?$/.exec(iso)
59
- if (!m || !m.slice(1).some(Boolean)) return undefined
60
- return ((Number(m[1] ?? 0) * 24 + Number(m[2] ?? 0)) * 60 + Number(m[3] ?? 0)) * 60_000 + Number(m[4] ?? 0) * 1000
61
- }
62
-
63
- /**
64
- * 작업 종류별 **허용오차** — 그 공정이 선언한 변동폭에서 나온다.
65
- *
66
- * 실측 p50 은 정상 변동 안에서 흔들린다. 그 흔들림을 "다른 모델" 로 읽으면 보정이 자꾸 끊기고, 사용자는
67
- * 학습이 왜 안 듣는지 모른다. 얼마나 흔들리는 것이 정상인지는 **현장이 이미 선언했다**(`variability`).
68
- *
69
- * 반폭을 쓴다(`(max − min) / 2 / 소요`) — 중앙에서 어느 쪽으로든 그만큼은 정상이라는 뜻이다.
70
- * 선언이 없거나 읽을 수 없으면 기본값으로 떨어진다(짐작해 만들지 않는다).
71
- */
72
- export function toleranceOf(declared?: DeclaredOperation[]): Record<string, number> {
73
- const out: Record<string, number> = {}
74
- for (const o of declared ?? []) {
75
- if (!o?.key) continue
76
- const base = isoMs(o.duration)
77
- const min = isoMs(o.variability?.min)
78
- const max = isoMs(o.variability?.max)
79
- if (!base || min === undefined || max === undefined || !(max > min)) continue
80
- const half = (max - min) / 2 / base
81
- if (Number.isFinite(half) && half > 0) out[o.key] = half
82
- }
83
- return out
84
- }
85
-
86
- /** 뜻 있는 수만 남긴다 — 0·음수·NaN 은 모델이 아니다. */
87
- function clean(map?: Record<string, number>): Record<string, number> {
88
- const out: Record<string, number> = {}
89
- for (const [k, v] of Object.entries(map ?? {})) if (Number.isFinite(v) && v > 0) out[k] = v
90
- return out
91
- }
92
-
93
- function declaredMap(list?: DeclaredOperation[]): Record<string, string> {
94
- const out: Record<string, string> = {}
95
- for (const o of list ?? []) {
96
- if (!o?.key) continue
97
- const v = o.variability
98
- /* 변동폭까지 한 문장으로 — 순서를 고정해 같은 선언이 같은 문자열이 되게 한다. */
99
- const spread = v ? `~${v.distribution ?? '?'}:${v.min ?? ''}..${v.max ?? ''}@${v.mode ?? ''}` : ''
100
- if (o.duration || spread) out[o.key] = `${o.duration ?? ''}${spread}`
101
- }
102
- return out
103
- }
104
-
105
- /** 두 수치 지도가 실질적으로 다른가 — 키 집합이 다르거나, 값이 허용오차를 넘어 다르면 다르다. */
106
- function numericChanged(a: Record<string, number>, b: Record<string, number>, tolOf: (key: string) => number): boolean {
107
- const keys = new Set([...Object.keys(a), ...Object.keys(b)])
108
- for (const k of keys) {
109
- const x = a[k]
110
- const y = b[k]
111
- if (x === undefined || y === undefined) return true // 새로 배운 종류·사라진 종류 = 다른 모델
112
- const base = Math.max(Math.abs(x), Math.abs(y))
113
- if (base > 0 && Math.abs(x - y) / base > tolOf(k)) return true
114
- }
115
- return false
116
- }
117
-
118
- /**
119
- * 모델이 달라졌는가 — 보정을 적용하기 전의 관문.
120
- * 한쪽 근거를 모르면 **판정하지 않는다**(false) — 모르는 것을 근거로 학습을 끊지 않는다.
121
- */
122
- export function modelBasisChanged(before?: ModelBasis, after?: ModelBasis, tol: number = BASIS_TOLERANCE): boolean {
123
- if (!before || !after) return false
124
- /*
125
- * 허용오차는 **선언이 정한다** — 배운 시점과 지금의 선언이 다를 수 있으므로 둘 중 **넓은 쪽**을 쓴다.
126
- * 좁은 쪽을 쓰면 선언을 넓힌 직후에 정상 변동이 "다른 모델" 로 잡힌다(그 변경 자체는 아래 선언 비교가
127
- * 이미 잡으므로, 여기서 또 잡을 필요가 없다).
128
- */
129
- const tolBefore = toleranceOf(before.declared)
130
- const tolAfter = toleranceOf(after.declared)
131
- const tolOf = (key: string): number => Math.max(tolBefore[key] ?? tol, tolAfter[key] ?? tol)
132
- if (numericChanged(clean(before.measured), clean(after.measured), tolOf)) return true
133
- /* 속도는 자원 종류별이고 선언된 변동폭이 없다 — 기본값이 그대로 쓰인다. */
134
- if (numericChanged(clean(before.speeds), clean(after.speeds), () => tol)) return true
135
- const da = declaredMap(before.declared)
136
- const db = declaredMap(after.declared)
137
- const keys = new Set([...Object.keys(da), ...Object.keys(db)])
138
- for (const k of keys) if (da[k] !== db[k]) return true
139
- return false
140
- }
141
-
142
- /**
143
- * 사람이 읽는 근거 요약 — **로그·진단용**(비교의 근거가 아니다).
144
- * 지문으로 같음을 판정하지 않는 이유는 위 주석 참조. 두 근거가 왜 달라졌는지 눈으로 보려면 이것을 찍는다.
145
- */
146
- export function describeModelBasis(basis?: ModelBasis): string {
147
- if (!basis) return 'unknown'
148
- const seg: string[] = []
149
- const m = Object.entries(clean(basis.measured))
150
- .map(([k, v]) => `${k}=${Math.round(v / 1000)}s`)
151
- .sort()
152
- if (m.length) seg.push(`measured(${m.join(',')})`)
153
- const s = Object.entries(clean(basis.speeds))
154
- .map(([k, v]) => `${k}=${Math.round(v * 10) / 10}m/s`)
155
- .sort()
156
- if (s.length) seg.push(`speed(${s.join(',')})`)
157
- const d = Object.entries(declaredMap(basis.declared))
158
- .map(([k, v]) => `${k}=${v}`)
159
- .sort()
160
- if (d.length) seg.push(`declared(${d.join(',')})`)
161
- return seg.length ? seg.join(' ') : 'kernel defaults only'
162
- }