@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,144 +0,0 @@
1
- /*
2
- * 연결 적합성 하네스 — **통합을 시험 스위트처럼 돌린다.**
3
- *
4
- * 선언 적합성 하네스 세 벌과 같은 규율을 **연결**에 적용한다: 사실이 오류 없이 사라지는 것을 막는다.
5
- * 다른 점은 대상이 우리 선언이 아니라 **남의 시스템**이라는 것이고, 그래서 두 규칙이 더 붙는다.
6
- *
7
- * ① **돌리지 않은 프로브는 「실패」가 아니라 「모른다」다.** 실패로 처리하면 사람이 그 빨간 칸을
8
- * 없애려고 무엇이든 하게 되고, 모른다로 처리하면 **무엇을 아직 모르는지**가 남는다. 판정
9
- * (`assessStagePath`)이 「모른다」를 달성으로 바꾸지 않으므로 이 구분이 끝까지 살아 있다.
10
- * ② **쓰기 프로브는 명시 동의 없이 돌지 않는다.** 이 스위트는 고객의 운영 시스템을 두드린다.
11
- * 읽기는 기본으로 돌리고, 남의 공장에 명령을 넣는 프로브는 사람이 켜야 돈다 — 켜지 않으면
12
- * 폐루프 칸은 「검증되지 않음」으로 남는다(그게 사실이다).
13
- *
14
- * 순수 모듈이다(전송·DB 무의존). 실행기는 이 선언을 읽어 프로브를 돌리고 `ProbeResult[]` 를 낸다.
15
- * 화면은 그 결과와 `assessStagePath` 의 판정을 함께 보인다 — 초록/빨강과 **그 초록이 무엇을 증명하나**.
16
- */
17
-
18
- import type { StageEvidence, StageId } from './stage-path.ts'
19
-
20
- export type ProbeId =
21
- | 'connect' // 붙는다
22
- | 'discover' // 사이트가 열거된다
23
- | 'master' // 구조가 들어온다
24
- | 'master-warnings' // 못 옮긴 값을 세었다
25
- | 'items' // 자리에 물품이 놓인다(비직렬 수량 포함)
26
- | 'live-ingest' // 이벤트가 들어온다
27
- | 'live-removal' // **반출이 관측된다** — 진짜 delta 의 증거
28
- | 'declarations' // 공정 선언이 실려 있다
29
- | 'forecast' // 예측이 돈다
30
- | 'actuate-declared' // 액추에이션 능력이 선언∩구현이다
31
- | 'actuate-effect' // 명령의 효과가 상관되어 돌아온다 (쓰기)
32
-
33
- export interface ProbeSpec {
34
- id: ProbeId
35
- /** 이 프로브가 증거를 대는 단계. */
36
- stage: StageId
37
- /** **무엇을 증명하나** — 언어중립 키(사람 말은 표현계층이 렌더). 「무엇을 호출하나」가 아니다. */
38
- proves: string
39
- /** 대상 시스템을 바꾸는가. 참이면 사람이 켜야 돈다. */
40
- writes: boolean
41
- /** 이 프로브가 실패하면 뒤 프로브를 돌릴 의미가 없다. */
42
- gating: boolean
43
- }
44
-
45
- /**
46
- * 시퀀스 — 순서가 곧 방법론이다. 앞이 막히면 뒤는 돌리지 않는다(돌려도 답이 무의미하다).
47
- *
48
- * `master-warnings` 를 **별개 프로브**로 둔 이유: 구조가 들어오는 것과 못 옮긴 값을 세는 것은 다른
49
- * 사실이고, 세지 않은 인제스트는 도크를 랙으로 바꿔 놓고도 성공으로 보인다.
50
- */
51
- export const PROBE_SEQUENCE: readonly ProbeSpec[] = [
52
- { id: 'connect', stage: 'structure', proves: 'probe.connect', writes: false, gating: true },
53
- { id: 'discover', stage: 'structure', proves: 'probe.discover', writes: false, gating: true },
54
- { id: 'master', stage: 'structure', proves: 'probe.master', writes: false, gating: true },
55
- { id: 'master-warnings', stage: 'structure', proves: 'probe.masterWarnings', writes: false, gating: false },
56
- { id: 'items', stage: 'structure', proves: 'probe.items', writes: false, gating: false },
57
- { id: 'live-ingest', stage: 'live', proves: 'probe.liveIngest', writes: false, gating: true },
58
- { id: 'live-removal', stage: 'live', proves: 'probe.liveRemoval', writes: false, gating: false },
59
- { id: 'declarations', stage: 'forecast', proves: 'probe.declarations', writes: false, gating: false },
60
- { id: 'forecast', stage: 'forecast', proves: 'probe.forecast', writes: false, gating: false },
61
- { id: 'actuate-declared', stage: 'closed-loop', proves: 'probe.actuateDeclared', writes: false, gating: true },
62
- { id: 'actuate-effect', stage: 'closed-loop', proves: 'probe.actuateEffect', writes: true, gating: false }
63
- ]
64
-
65
- /** 프로브 한 건의 결과. `ran: false` = 돌리지 않았다(실패가 아니다). */
66
- export interface ProbeResult {
67
- id: ProbeId
68
- ran: boolean
69
- /**
70
- * 이 대상에 **해당하지 않는다**. 통과도 실패도 미측정도 아닌 네 번째 값이다.
71
- *
72
- * 시뮬레이션 트윈에 라이브 프로브를 들이대면 빨간 칸이 생기는데 그건 결함이 아니다 — 시뮬은 원천에서
73
- * 받는 것이 없다. 레퍼런스 없이 템플릿으로 세운 트윈에는 옮겨 온 마스터가 없으므로 「못 옮긴 값」도 없다.
74
- * 이걸 통과로 처리하면 없는 능력을 주장하고, 미측정으로 처리하면 영원히 배선을 기다린다.
75
- */
76
- applicable?: boolean
77
- /** 돌렸을 때의 판정. 돌리지 않았으면 무의미하다. */
78
- passed?: boolean
79
- /** 센 값(자리 수·반출 건수·선언 수 등). 세지 않았으면 없다. */
80
- count?: number
81
- /** 선언 적재량 프로브만 — `declared`/`total`. */
82
- coverage?: { declared: number; total: number }
83
- /** 왜 실패했나·왜 건너뛰었나. 언어중립 코드 또는 원문 오류. */
84
- detail?: string
85
- }
86
-
87
- const by = (rs: readonly ProbeResult[], id: ProbeId) => rs.find(r => r.id === id)
88
- /** 돌렸고 셌으면 그 수, 아니면 `null`(모른다). 실패한 프로브의 수를 0 으로 읽지 않는다. */
89
- /**
90
- * 센 값은 **판정과 무관한 사실**이다 — `passed` 를 요구하면 「세어서 0 을 얻었다」가 「모른다」와 구별되지 않는다.
91
- * 그 구분이 이 하네스의 전부이므로 여기서 잃으면 나머지가 무의미하다. 해당 없음만 `null` 이다.
92
- */
93
- const counted = (r: ProbeResult | undefined): number | null =>
94
- r?.applicable === false ? null : r?.ran && r.count !== undefined ? r.count : null
95
- /** 돌렸고 셌으면 그 수, 아니면 0. **존재 여부**를 묻는 자리에만 쓴다(모름과 0 을 구별할 필요가 없는 축). */
96
- const countedOrZero = (r: ProbeResult | undefined): number => counted(r) ?? 0
97
-
98
- /**
99
- * 프로브 결과를 **증거**로 처리한다.
100
- *
101
- * 계산 규칙의 정수: **돌리지 않은 프로브는 `null`** 로 간다. 그러면 판정이 그 단계를 달성으로
102
- * 만들지 않고 `unmeasured` 로 말한다 — 스위트를 절반만 돌리고 초록을 주장할 길이 없다.
103
- */
104
- export function foldProbeResults(results: readonly ProbeResult[]): StageEvidence {
105
- return {
106
- locationCount: countedOrZero(by(results, 'master')),
107
- itemCount: countedOrZero(by(results, 'items')),
108
- masterWarnings: counted(by(results, 'master-warnings')),
109
- /* 해당 없음은 **미측정이 아니다** — 물을 대상이 아닌 축을 판정에서 뺀다. */
110
- masterWarningsApplicable: by(results, 'master-warnings')?.applicable !== false,
111
- liveIngestTotal: countedOrZero(by(results, 'live-ingest')),
112
- removalsObserved: counted(by(results, 'live-removal')),
113
- forecastRan: by(results, 'forecast')?.ran === true && by(results, 'forecast')?.passed === true,
114
- specCoverage: (() => {
115
- const r = by(results, 'declarations')
116
- return r?.ran && r.passed && r.coverage ? r.coverage : null
117
- })(),
118
- actuateCapability: by(results, 'actuate-declared')?.passed === true,
119
- correlatedEffectObserved: counted(by(results, 'actuate-effect'))
120
- }
121
- }
122
-
123
- /**
124
- * 지금 돌릴 프로브 — 게이팅과 쓰기 동의를 지킨다.
125
- *
126
- * 앞의 게이팅 프로브가 실패했으면 **거기서 멈춘다.** 뒤를 돌려 빨간 칸을 늘리는 것은 정보를 주지
127
- * 않는다(원인은 이미 앞에 있다). 쓰기 프로브는 `allowWrites` 없이는 목록에 들어오지 않는다.
128
- */
129
- export function plannedProbes(results: readonly ProbeResult[], opts: { allowWrites?: boolean } = {}): ProbeId[] {
130
- const out: ProbeId[] = []
131
- for (const spec of PROBE_SEQUENCE) {
132
- if (spec.writes && !opts.allowWrites) continue
133
- const prior = by(results, spec.id)
134
- if (prior?.applicable === false) continue // 해당 없는 프로브는 계획하지 않는다
135
- if (!prior?.ran) out.push(spec.id)
136
- if (spec.gating && prior?.ran && prior.passed === false) break
137
- }
138
- return out
139
- }
140
-
141
- /** 해당 없음으로 판정된 프로브 — 화면이 「왜 회색인가」를 말할 수 있게 사유와 함께 낸다. */
142
- export function notApplicable(results: readonly ProbeResult[]): { id: ProbeId; detail?: string }[] {
143
- return results.filter(r => r.applicable === false).map(r => ({ id: r.id, ...(r.detail ? { detail: r.detail } : {}) }))
144
- }
@@ -1,95 +0,0 @@
1
- /*
2
- * 실행기 — 모은 사실을 프로브 결과로 옮기고, 단계 판정과 프로파일까지 한 번에 낸다.
3
- *
4
- * I/O 는 여기 없다(호출자가 모은다). 그래서 판정 전체가 테스트된다.
5
- */
6
- import { PROBE_SEQUENCE, foldProbeResults, notApplicable, plannedProbes, type ProbeId, type ProbeResult } from './integration-probes.ts'
7
- import { assessStagePath, forbiddenClaims, type StagePath } from './stage-path.ts'
8
- import { narrowProfile, unknownProfile, type FeedKind, type TargetProfile } from './integration-target-profile.ts'
9
-
10
- /** 호출자가 모아 오는 사실. 전부 `null` 이 「모른다」다 — 0 이나 false 로 채우지 않는다. */
11
- export interface SuiteFacts {
12
- /** 이 트윈이 무엇인가. 시뮬은 원천에서 받는 것이 없다(라이브 프로브는 해당 없음). */
13
- subject: 'live' | 'sim' | 'stopped' | 'unknown'
14
- /** 레퍼런스(원천 어댑터)에서 왔나. 템플릿으로 세운 트윈은 옮겨 온 마스터가 없다. */
15
- fromReference: boolean
16
- /** `capabilitiesOf(adapter)` — 선언∩구현. */
17
- adapterCapabilities: readonly string[]
18
- connectOk: boolean | null
19
- siteCount: number | null
20
- locationCount: number | null
21
- itemCount: number | null
22
- /** 마지막 동기의 못 옮긴 값 수(`TwinReference.lastWarningCount`). */
23
- lastWarningCount: number | null
24
- /** 저널 누적 — 재시작에도 남는다(인메모리 계기와 다르다). */
25
- journalTotal: number | null
26
- /** 저널의 `action='DELETE'` 수 — **반출 관측**. 승격 전 행은 세어지지 않으므로 `null` 이 정직하다. */
27
- removalsJournaled: number | null
28
- specCoverage: { declared: number; total: number } | null
29
- forecastRan: boolean | null
30
- feed: FeedKind
31
- }
32
-
33
- export interface SuiteAssessment {
34
- results: ProbeResult[]
35
- profile: TargetProfile
36
- path: StagePath
37
- notApplicable: { id: ProbeId; detail?: string }[]
38
- forbiddenClaims: string[]
39
- /** 다음에 돌릴 프로브 — 쓰기 동의 없이는 쓰기 프로브가 빠진다. */
40
- planned: ProbeId[]
41
- }
42
-
43
- const r = (id: ProbeId, o: Partial<ProbeResult>): ProbeResult => ({ id, ran: false, ...o })
44
-
45
- /** 값이 있으면 돌린 것으로 보고 판정한다. `null` = 안 돌렸다(실패 아님). */
46
- const fromNumber = (id: ProbeId, v: number | null, min = 1): ProbeResult =>
47
- v === null ? r(id, { ran: false }) : r(id, { ran: true, passed: v >= min, count: v })
48
-
49
- export function assessSuite(f: SuiteFacts, opts: { allowWrites?: boolean } = {}): SuiteAssessment {
50
- const liveApplies = f.subject !== 'sim'
51
- const results: ProbeResult[] = [
52
- f.connectOk === null ? r('connect', { ran: false }) : r('connect', { ran: true, passed: f.connectOk }),
53
- fromNumber('discover', f.siteCount),
54
- fromNumber('master', f.locationCount),
55
- /* 레퍼런스 없이 세운 트윈에는 옮겨 온 마스터가 없다 — 「못 옮긴 값」을 물을 대상이 아니다. */
56
- f.fromReference
57
- ? fromNumber('master-warnings', f.lastWarningCount, 0)
58
- : r('master-warnings', { ran: false, applicable: false, detail: 'not-from-reference' }),
59
- fromNumber('items', f.itemCount),
60
- liveApplies ? fromNumber('live-ingest', f.journalTotal) : r('live-ingest', { ran: false, applicable: false, detail: 'subject-is-simulation' }),
61
- liveApplies ? fromNumber('live-removal', f.removalsJournaled, 1) : r('live-removal', { ran: false, applicable: false, detail: 'subject-is-simulation' }),
62
- f.specCoverage === null
63
- ? r('declarations', { ran: false })
64
- : r('declarations', { ran: true, passed: f.specCoverage.declared > 0, coverage: f.specCoverage }),
65
- f.forecastRan === null ? r('forecast', { ran: false }) : r('forecast', { ran: true, passed: f.forecastRan }),
66
- r('actuate-declared', { ran: true, passed: f.adapterCapabilities.includes('actuate') }),
67
- /* 액추에이션은 계약에 아직 없다(ADR-0036). 측정을 만들면 없는 것을 있는 척한다. */
68
- r('actuate-effect', { ran: false, detail: 'actuation-not-wired' })
69
- ]
70
-
71
- /* 반출을 셌는데 0 이면 「세지 않음」과 구별해 프로브를 실패로 남긴다 — count 0 은 사실이다. */
72
- const removal = results.find(x => x.id === 'live-removal')!
73
- if (removal.ran && f.removalsJournaled === 0) removal.count = 0
74
-
75
- const profile = narrowProfile(unknownProfile(), {
76
- feed: f.feed,
77
- multiSite: f.siteCount === null ? null : f.siteCount > 1,
78
- write: f.adapterCapabilities.includes('actuate') ? 'command' : 'unknown'
79
- })
80
-
81
- const evidence = { ...foldProbeResults(results), subject: liveApplies ? ('live' as const) : ('sim' as const), feed: f.feed }
82
- const path = assessStagePath(evidence)
83
-
84
- return {
85
- results,
86
- profile,
87
- path,
88
- notApplicable: notApplicable(results),
89
- forbiddenClaims: forbiddenClaims(path),
90
- planned: plannedProbes(results, opts)
91
- }
92
- }
93
-
94
- /** 시퀀스 명세 — 화면이 회색 칸의 이유(해당 없음·미실행)를 나란히 보이도록 함께 낸다. */
95
- export const SUITE_SPEC = PROBE_SEQUENCE
@@ -1,103 +0,0 @@
1
- /*
2
- * 대상 프로파일 — **스위트가 갈리는 근거.**
3
- *
4
- * ── 왜 프로파일이 먼저인가 ──────────────────────────────────────────────────
5
- * 처음 만든 시퀀스는 직선이었다. 모든 대상에게 같은 순서를 강요했고, 그래서 두 방향으로 거짓말을
6
- * 했다: push 소스에 커서 프로브를 들이대 빨간 칸을 만들고(결함이 아닌데), 반대로 스냅샷 소스에는
7
- * 반출을 못 본 이유를 「아직 안 돌렸다」로 적었다(구조적으로 못 내는 것인데).
8
- *
9
- * 갈림의 근거는 **대상의 성격**이고, 그 성격은 **우리가 정하는 것이 아니라 발견하는 것**이다.
10
- * 그래서 프로파일의 모든 축은 `'unknown'` 에서 시작해 프로브가 좁힌다. 모르는 축으로는 라우팅하지
11
- * 않는다 — 모르면 그 축에 걸린 프로브는 「아직 판단할 수 없음」이고, 짐작으로 건너뛰지 않는다.
12
- *
13
- * ── 축을 고른 기준 ─────────────────────────────────────────────────────────
14
- * 실제로 **다른 프로브를 요구하는 것만** 축이 된다. 「벤더 이름」은 축이 아니다(같은 벤더가 REST 도
15
- * 파일도 준다). 아래 일곱은 각각 적어도 한 프로브의 적용 여부를 바꾼다.
16
- */
17
-
18
- /** 무엇으로 붙나 — 페이지·상한·질의 형태가 여기서 갈린다. */
19
- export type Transport = 'rest' | 'graphql' | 'db' | 'file' | 'mqtt' | 'opc' | 'unknown'
20
-
21
- /**
22
- * 변화를 어떻게 아나 — **라이브 단계의 성격이 통째로 이 축에 달려 있다.**
23
- *
24
- * · `push` 원천이 밀어 준다(구독·웹훅·큐·CDC). 커서가 필요 없다.
25
- * · `delta-poll` 거래 이력을 커서로 읽는다. **커서 정합이 급소다.**
26
- * · `snapshot-poll` 현재 상태를 되풀어 읽는다. **반출을 원리적으로 낼 수 없다** — 라이브 단계는
27
- * 「아직」이 아니라 **구조적으로 불가**이고, 그 사실을 그대로 말한다.
28
- * · `none` 변화를 알 길이 없다(구조 전용 소스).
29
- */
30
- export type FeedKind = 'push' | 'delta-poll' | 'snapshot-poll' | 'none' | 'unknown'
31
-
32
- /** 물건을 무엇이라 부르나 — 발명해야 하는지가 여기서 갈린다. */
33
- export type IdentityKind = 'gs1' | 'local' | 'none' | 'unknown'
34
-
35
- /**
36
- * 양을 어떻게 세나 — **개수냐 연속량이냐.**
37
- *
38
- * 식품·화학·제약은 KG·L 로 오고, 조립 제조는 대수로 온다. 커널·미러는 둘 다 다루지만(비직렬
39
- * `MaterialSubLot`), **요구하는 프로브가 다르다**: 연속량이면 단위 어휘와 환산을 반드시 묻고,
40
- * 직렬이면 그 프로브는 해당 없음이다.
41
- */
42
- export type Quantization = 'serial' | 'continuous' | 'mixed' | 'unknown'
43
-
44
- /** 이 원천이 겸하는 버티컬 — 둘 이상이면 트윈이 여럿이고 **핸드오버 경계**를 물어야 한다. */
45
- export type Vertical = 'wms' | 'mes' | 'yms' | 'ems'
46
-
47
- /** 밖으로 나가는 문 — 폐루프 프로브의 적용 여부. */
48
- export type WriteSurface = 'none' | 'command' | 'unknown'
49
-
50
- export interface TargetProfile {
51
- transport: Transport
52
- feed: FeedKind
53
- multiSite: boolean | null
54
- identity: IdentityKind
55
- quantization: Quantization
56
- /** 빈 배열 = 아직 모른다(없다는 뜻이 아니다). */
57
- verticals: readonly Vertical[]
58
- write: WriteSurface
59
- }
60
-
61
- /** 아무것도 모르는 상태 — 스위트는 여기서 시작한다. */
62
- export function unknownProfile(): TargetProfile {
63
- return { transport: 'unknown', feed: 'unknown', multiSite: null, identity: 'unknown', quantization: 'unknown', verticals: [], write: 'unknown' }
64
- }
65
-
66
- /** 이 축을 아직 모르나 — 모르는 축으로는 라우팅하지 않는다. */
67
- export function isUnknown(p: TargetProfile, axis: keyof TargetProfile): boolean {
68
- const v = p[axis]
69
- if (axis === 'multiSite') return v === null
70
- if (axis === 'verticals') return (v as readonly Vertical[]).length === 0
71
- return v === 'unknown'
72
- }
73
-
74
- /**
75
- * 프로브가 알아낸 것을 프로파일에 반영한다 — **좁히기만 한다.**
76
- *
77
- * 이미 알아낸 축을 나중 프로브가 `'unknown'` 으로 덮지 못하게 한다. 스위트는 여러 번 돌고, 뒤에
78
- * 돌린 프로브가 그 축을 다루지 않는다는 이유로 앞의 발견을 지우면 라우팅이 왕복한다.
79
- */
80
- export function narrowProfile(base: TargetProfile, found: Partial<TargetProfile>): TargetProfile {
81
- const out: TargetProfile = { ...base }
82
- for (const k of Object.keys(found) as (keyof TargetProfile)[]) {
83
- const v = found[k]
84
- if (v === undefined) continue
85
- if (k === 'multiSite') { if (v !== null) out.multiSite = v as boolean; continue }
86
- if (k === 'verticals') { const list = v as readonly Vertical[]; if (list.length) out.verticals = [...new Set([...out.verticals, ...list])]; continue }
87
- if (v !== 'unknown') (out as any)[k] = v
88
- }
89
- return out
90
- }
91
-
92
- /**
93
- * 이 프로파일에서 **라이브가 구조적으로 가능한가.**
94
- *
95
- * `snapshot-poll` 은 불가다 — 사라진 것은 그냥 없어지고 `OBSERVE` 만 남는다. 이걸 「아직 반출을 못
96
- * 봤다」로 적으면 사람이 더 기다리게 되는데, 더 기다려도 오지 않는다. 방식을 바꿔야 한다는 것이 답이다.
97
- */
98
- export function liveFeasible(p: TargetProfile): { ok: boolean; reason?: string } {
99
- if (p.feed === 'unknown') return { ok: false, reason: 'feed-unknown' }
100
- if (p.feed === 'none') return { ok: false, reason: 'no-feed' }
101
- if (p.feed === 'snapshot-poll') return { ok: false, reason: 'snapshot-only-feed' }
102
- return { ok: true }
103
- }
@@ -1,202 +0,0 @@
1
- /*
2
- * 여러 구간 동시 비교 — **"어제보다 나아졌다" 를 넘어선다.** 순수.
3
- *
4
- * ── 왜 필요한가 (성과 맵 ③) ─────────────────────────────────────────────────
5
- * 지금 비교 축은 **한 구간**만 본다(직전 구간 또는 하루 전). 그래서 판단이 딱 한 문장에서 멈춘다:
6
- * "어제보다 나아졌다." **어제도 나빴으면 그 말은 쓸모가 없다.** 목표(`kpi-target`)가 그 한계를 한쪽에서
7
- * 풀지만, 목표를 아직 걸지 않은 현장은 여전히 자기 숫자가 평소와 같은지도 알 수 없다.
8
- *
9
- * 최근 며칠의 **같은 시간대**를 함께 계산하면 목표 없이도 말할 수 있다 — "오늘 이 시간대는 지난 7일 중
10
- * 가장 낮다." 그것이 이 파일이 만드는 것이다: 창 여러 개의 **분포**와 그 안에서 현재의 **자리**.
11
- *
12
- * ── 이 파일이 하지 않는 것 ──────────────────────────────────────────────────
13
- * · **지표 어휘를 모른다.** 이름·방향·값 꺼내는 법은 `kpi-target.ts` 의 `TWIN_METRIC` 이 소유한다. 여기는
14
- * **이미 꺼낸 값**만 받는다 — 어휘가 두 곳에 생기면 그 사이에 매핑 표가 자라고 그것이 곧 방언이다.
15
- * (덤으로: 이 모듈은 런타임 import 가 없어 테스트가 소스를 그대로 든다.)
16
- * · **DB·조회를 모른다.** 창 목록만 계산하고, 그 창을 읽는 것은 호출부의 일이다.
17
- * · **좋고 나쁨의 임계를 발명하지 않는다.** "평소보다 나쁘다" 는 중앙값과의 비교로만 말한다 — 임의의
18
- * 퍼센트 임계를 두면 그 숫자가 곧 숨은 목표가 된다.
19
- *
20
- * ── 정직성 규율 (이 도메인의 핵심) ──────────────────────────────────────────
21
- * ① **결측 창을 알리지 않고 빼지 않는다.** 요청한 창 전부를 `measured` 와 함께 돌려주고, 분포는 측정된
22
- * 것만으로 만든다. 빼고 말하면 "지난 7일" 이 실제로는 3일이었다는 것을 아무도 모른다.
23
- * ② **표본이 둘 미만이면 자리를 말하지 않는다.** 하나를 분포라 부를 수 없다.
24
- * ③ **현재 값이 없으면 자리를 말하지 않는다.** 결측을 0 으로 읽으면 시간 지표는 "낮을수록 좋다" 라서
25
- * **일이 없던 구간이 최고 성적**으로 보고된다(목표 판정에서 이미 겪은 결함이다).
26
- * ④ 왜 말하지 않는지를 `reason` 으로 밝힌다 — 알리지 않고 빈 값을 주면 화면이 "분포 없음" 을 "평범함" 으로
27
- * 그린다.
28
- */
29
-
30
- /** 창 하나 — 폴드의 창과 같은 모양(ms). */
31
- export interface BaselineWindow {
32
- fromMs: number
33
- toMs: number
34
- }
35
-
36
- /** 며칠 전 같은 시간대인가, 몇 주 전 같은 요일·시간대인가. */
37
- export type BaselineStride = 'day' | 'week'
38
-
39
- /** 한 번에 볼 수 있는 과거 구간 수 — 창마다 조회가 한 번 더 붙으므로 상한을 둔다. */
40
- export const MAX_BASELINE_PERIODS = 14
41
-
42
- const MS_DAY = 24 * 60 * 60_000
43
-
44
- /**
45
- * 비교할 과거 창들 — 현재 창을 **같은 길이로** 하루(또는 한 주)씩 뒤로 옮긴다.
46
- *
47
- * 가까운 것부터 준다(어제 → 그제 → …). 화면이 시간 순서를 다시 정하지 않아도 되게.
48
- *
49
- * **한계를 밝힌다**: 옮기는 것은 ms 산술이다. 트윈 공간은 고정 오프셋(`utcOffsetMinutes`)을 선언하므로
50
- * 현재 모델에서는 "같은 시간대" 가 정확하다. 일광절약시간을 쓰는 시간대를 나중에 지원하면 전환이 있는
51
- * 주의 하루가 한 시간 밀린다 — 그때는 오프셋 기준 캘린더 산술로 바꿔야 한다(지금 지어내지 않는다).
52
- */
53
- export function baselineWindows(
54
- fromMs: number,
55
- toMs: number,
56
- periods: number,
57
- stride: BaselineStride = 'day'
58
- ): BaselineWindow[] {
59
- if (!Number.isFinite(fromMs) || !Number.isFinite(toMs) || toMs <= fromMs) return []
60
- const count = Math.max(0, Math.min(MAX_BASELINE_PERIODS, Math.floor(periods)))
61
- const step = stride === 'week' ? 7 * MS_DAY : MS_DAY
62
-
63
- return Array.from({ length: count }, (_, i) => ({
64
- fromMs: fromMs - step * (i + 1),
65
- toMs: toMs - step * (i + 1)
66
- }))
67
- }
68
-
69
- /** 지표의 성질 — 이름과 값 꺼내기는 호출부(`TWIN_METRIC`)가 소유한다. */
70
- export interface MetricSpecLike {
71
- direction: 'higher' | 'lower'
72
- unit: string
73
- }
74
-
75
- /** 과거 창 하나에서 꺼낸 값들 — 그 창에 기록이 없으면 값이 `undefined` 다. */
76
- export interface BaselineSampleInput<M extends string> {
77
- fromMs: number
78
- toMs: number
79
- values: Partial<Record<M, number | undefined>>
80
- }
81
-
82
- /** 과거 창 하나의 결과 — **결측도 남긴다**(빼면 "지난 7일" 이 거짓이 된다). */
83
- export interface BaselineSample {
84
- fromMs: number
85
- toMs: number
86
- measured: boolean
87
- value?: number
88
- }
89
-
90
- /** 왜 자리를 말하지 않는지. */
91
- export type BaselineNoPosition = 'no-current' | 'too-few-samples'
92
-
93
- /**
94
- * 분포 안에서 현재의 자리 — **방향을 적용한 읽기.**
95
- *
96
- * 임의의 임계가 없다: 표본 전부보다 좋으면 `best`, 전부보다 나쁘면 `worst`, 그 사이는 중앙값을 기준으로
97
- * 구분한다. `typical` 은 중앙값과 **같을 때**만이다.
98
- */
99
- export type BaselineStanding = 'best' | 'better-than-typical' | 'typical' | 'worse-than-typical' | 'worst'
100
-
101
- export interface MetricBaseline<M extends string = string> {
102
- metric: M
103
- direction: 'higher' | 'lower'
104
- unit: string
105
- /** 지금 창의 값 — 없으면 `undefined`(0 이 아니다). */
106
- current?: number
107
- /** 요청한 과거 창 전부(결측 포함, 가까운 것부터). */
108
- samples: BaselineSample[]
109
- /** 요청한 창 수 / 그중 실제로 측정된 수 — 둘을 함께 봐야 "지난 7일" 을 믿을 수 있다. */
110
- requested: number
111
- measuredCount: number
112
- /** 측정된 표본만의 요약. 표본이 없으면 전부 `undefined`. */
113
- min?: number
114
- median?: number
115
- max?: number
116
- /** 측정 표본을 오름차순으로 놓았을 때 현재 값이 몇 번째인가(1 = 가장 작음) — **방향 없는 사실**. */
117
- rank?: number
118
- /** 그 순위를 셀 때의 표본 수(+현재 1). 순위만 보면 표본이 둘이었는지 열이었는지 알 수 없다. */
119
- rankOf?: number
120
- /** 방향을 적용한 읽기. 말할 수 없으면 없다. */
121
- standing?: BaselineStanding
122
- /** 자리를 말하지 않은 이유. */
123
- noPosition?: BaselineNoPosition
124
- }
125
-
126
- /** 중앙값 — 짝수 개면 가운데 둘의 평균(폴드의 분위수 규약과 달리 여기 표본은 아주 작다). */
127
- function medianOf(sorted: readonly number[]): number | undefined {
128
- if (!sorted.length) return undefined
129
- const mid = sorted.length >> 1
130
- return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2
131
- }
132
-
133
- /**
134
- * 지표별로 분포와 자리를 만든다.
135
- *
136
- * @param specs 지표 성질(방향·단위). 열거된 지표만 낸다 — 모르는 이름을 짐작하지 않는다.
137
- * @param current 지금 창에서 꺼낸 값들(결측은 `undefined`).
138
- * @param inputs 과거 창들에서 꺼낸 값들(가까운 것부터).
139
- */
140
- export function summarizeBaseline<M extends string>(
141
- specs: Readonly<Record<M, MetricSpecLike>>,
142
- current: Partial<Record<M, number | undefined>>,
143
- inputs: readonly BaselineSampleInput<M>[]
144
- ): MetricBaseline<M>[] {
145
- const out: MetricBaseline<M>[] = []
146
-
147
- for (const metric of Object.keys(specs) as M[]) {
148
- const spec = specs[metric]
149
- const samples: BaselineSample[] = inputs.map(s => {
150
- const v = s.values[metric]
151
- const measured = typeof v === 'number' && Number.isFinite(v)
152
- return measured ? { fromMs: s.fromMs, toMs: s.toMs, measured: true, value: v as number } : { fromMs: s.fromMs, toMs: s.toMs, measured: false }
153
- })
154
-
155
- const values = samples.filter(s => s.measured).map(s => s.value as number)
156
- const sorted = [...values].sort((a, b) => a - b)
157
- const cur = current[metric]
158
- const hasCurrent = typeof cur === 'number' && Number.isFinite(cur)
159
-
160
- const row: MetricBaseline<M> = {
161
- metric,
162
- direction: spec.direction,
163
- unit: spec.unit,
164
- ...(hasCurrent ? { current: cur as number } : {}),
165
- samples,
166
- requested: inputs.length,
167
- measuredCount: values.length,
168
- ...(sorted.length ? { min: sorted[0], median: medianOf(sorted), max: sorted[sorted.length - 1] } : {})
169
- }
170
-
171
- /* 자리를 말할 수 없는 두 경우 — 이유를 밝힌다(들어온 것이 없는 빈 값이 "평범함" 으로 읽힌다). */
172
- if (!hasCurrent) row.noPosition = 'no-current'
173
- else if (sorted.length < 2) row.noPosition = 'too-few-samples'
174
- else {
175
- const value = cur as number
176
- const median = medianOf(sorted) as number
177
- /* 오름차순에서 몇 번째인가 — 같은 값은 뒤에 놓는다(동률이면 "더 큰 쪽" 으로 세지 않는다). */
178
- row.rank = sorted.filter(v => v < value).length + 1
179
- row.rankOf = sorted.length + 1
180
-
181
- const higherIsBetter = spec.direction === 'higher'
182
- const beatsAll = higherIsBetter ? value > sorted[sorted.length - 1] : value < sorted[0]
183
- const losesToAll = higherIsBetter ? value < sorted[0] : value > sorted[sorted.length - 1]
184
- /* 중앙값보다 큰 것이 "좋은" 쪽인가 — 방향을 여기 한 번만 적용한다. */
185
- const aboveMedianIsBetter = higherIsBetter === value > median
186
-
187
- row.standing = beatsAll
188
- ? 'best'
189
- : losesToAll
190
- ? 'worst'
191
- : value === median
192
- ? 'typical'
193
- : aboveMedianIsBetter
194
- ? 'better-than-typical'
195
- : 'worse-than-typical'
196
- }
197
-
198
- out.push(row)
199
- }
200
-
201
- return out
202
- }