@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.
- package/package.json +21 -7
- package/dist-server/engine/attention-digest.js.map +0 -1
- package/dist-server/engine/canonical-ingest.js.map +0 -1
- package/dist-server/engine/checkpoint-fold.js.map +0 -1
- package/dist-server/engine/command-routing.js.map +0 -1
- package/dist-server/engine/declared-stimulus.js.map +0 -1
- package/dist-server/engine/energy-topology.js.map +0 -1
- package/dist-server/engine/event-time.js.map +0 -1
- package/dist-server/engine/index.js.map +0 -1
- package/dist-server/engine/ingest-dedupe.js.map +0 -1
- package/dist-server/engine/ingest-health.js.map +0 -1
- package/dist-server/engine/integration-coverage.js.map +0 -1
- package/dist-server/engine/integration-probes.js.map +0 -1
- package/dist-server/engine/integration-runner.js.map +0 -1
- package/dist-server/engine/integration-target-profile.js.map +0 -1
- package/dist-server/engine/kpi-baseline.js.map +0 -1
- package/dist-server/engine/kpi-fold.js.map +0 -1
- package/dist-server/engine/kpi-query.js.map +0 -1
- package/dist-server/engine/kpi-target.js.map +0 -1
- package/dist-server/engine/live-attentions.js.map +0 -1
- package/dist-server/engine/live-feed-registry.js.map +0 -1
- package/dist-server/engine/load-meter.js.map +0 -1
- package/dist-server/engine/local-declarations.js.map +0 -1
- package/dist-server/engine/log.js.map +0 -1
- package/dist-server/engine/loop-lag.js.map +0 -1
- package/dist-server/engine/measured-estimator.js.map +0 -1
- package/dist-server/engine/measured-yield.js.map +0 -1
- package/dist-server/engine/model-basis.js.map +0 -1
- package/dist-server/engine/model-gap.js.map +0 -1
- package/dist-server/engine/model-refusal.js.map +0 -1
- package/dist-server/engine/model-vocabulary.js.map +0 -1
- package/dist-server/engine/oee-accumulator.js.map +0 -1
- package/dist-server/engine/operation-basis.js.map +0 -1
- package/dist-server/engine/producer-guard.js.map +0 -1
- package/dist-server/engine/property-effects.js.map +0 -1
- package/dist-server/engine/read-time.js.map +0 -1
- package/dist-server/engine/restart-policy.js.map +0 -1
- package/dist-server/engine/runtime-key.js.map +0 -1
- package/dist-server/engine/spec-coverage.js.map +0 -1
- package/dist-server/engine/stage-path.js.map +0 -1
- package/dist-server/engine/state-axes.js.map +0 -1
- package/dist-server/engine/structure-diff.js.map +0 -1
- package/dist-server/engine/travel-estimator.js.map +0 -1
- package/dist-server/engine/twin-engine.js.map +0 -1
- package/dist-server/engine/twin-state-channel.js.map +0 -1
- package/dist-server/engine/warm-start.js.map +0 -1
- package/dist-server/index.js.map +0 -1
- package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +0 -1
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +0 -1
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +0 -1
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +0 -1
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +0 -1
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +0 -1
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +0 -1
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +0 -1
- package/dist-server/migrations/1786800000000-CreateTwinReferenceReconciliations.js.map +0 -1
- package/dist-server/migrations/index.js.map +0 -1
- package/dist-server/routes.js.map +0 -1
- package/dist-server/service/actuation/actuation-advisor.js.map +0 -1
- package/dist-server/service/actuation/actuation-outcome.js.map +0 -1
- package/dist-server/service/actuation/actuation-rule-resolver.js.map +0 -1
- package/dist-server/service/actuation/actuation-rule.js.map +0 -1
- package/dist-server/service/actuation/approval-gateway.js.map +0 -1
- package/dist-server/service/actuation/catch-up-effects.js.map +0 -1
- package/dist-server/service/actuation/command-dispatcher.js.map +0 -1
- package/dist-server/service/actuation/command-store.js.map +0 -1
- package/dist-server/service/actuation/dispatch-after-approval.js.map +0 -1
- package/dist-server/service/actuation/effect-match.js.map +0 -1
- package/dist-server/service/actuation/index.js.map +0 -1
- package/dist-server/service/actuation/retry-plan.js.map +0 -1
- package/dist-server/service/actuation/rule-evaluate.js.map +0 -1
- package/dist-server/service/actuation/rule-loop.js.map +0 -1
- package/dist-server/service/actuation/rule-runner.js.map +0 -1
- package/dist-server/service/actuation/rule-wiring.js.map +0 -1
- package/dist-server/service/actuation/settle-effects.js.map +0 -1
- package/dist-server/service/actuation/sweep-dispatch.js.map +0 -1
- package/dist-server/service/actuation/twin-command-resolver.js.map +0 -1
- package/dist-server/service/actuation/twin-command.js.map +0 -1
- package/dist-server/service/actuation/twin-now.js.map +0 -1
- package/dist-server/service/index.js.map +0 -1
- package/dist-server/service/reference/actuation-routing.js.map +0 -1
- package/dist-server/service/reference/actuation-target.js.map +0 -1
- package/dist-server/service/reference/actuation-verification.js.map +0 -1
- package/dist-server/service/reference/attention-lane.js.map +0 -1
- package/dist-server/service/reference/connection-portability-resolver.js.map +0 -1
- package/dist-server/service/reference/connection-portability.js.map +0 -1
- package/dist-server/service/reference/control-routing.js.map +0 -1
- package/dist-server/service/reference/discovery-result.js.map +0 -1
- package/dist-server/service/reference/fill-cadence.js.map +0 -1
- package/dist-server/service/reference/fill-dedupe.js.map +0 -1
- package/dist-server/service/reference/fill-loop.js.map +0 -1
- package/dist-server/service/reference/fill-span.js.map +0 -1
- package/dist-server/service/reference/hook-contract.js.map +0 -1
- package/dist-server/service/reference/hook-rejected.js.map +0 -1
- package/dist-server/service/reference/hook-store.js.map +0 -1
- package/dist-server/service/reference/index.js.map +0 -1
- package/dist-server/service/reference/ingest-space.js.map +0 -1
- package/dist-server/service/reference/knob-defaults.js.map +0 -1
- package/dist-server/service/reference/live-cadence.js.map +0 -1
- package/dist-server/service/reference/live-feed-lease.js.map +0 -1
- package/dist-server/service/reference/live-ingest.js.map +0 -1
- package/dist-server/service/reference/reference-adapter.js.map +0 -1
- package/dist-server/service/reference/reference-assessment.js.map +0 -1
- package/dist-server/service/reference/reference-fill-run.js.map +0 -1
- package/dist-server/service/reference/reference-fill.js.map +0 -1
- package/dist-server/service/reference/reference-hook.js.map +0 -1
- package/dist-server/service/reference/reference-link-groups.js.map +0 -1
- package/dist-server/service/reference/reference-links.js.map +0 -1
- package/dist-server/service/reference/reference-live.js.map +0 -1
- package/dist-server/service/reference/reference-master.js.map +0 -1
- package/dist-server/service/reference/reference-probe.js.map +0 -1
- package/dist-server/service/reference/reference-progress-channel.js.map +0 -1
- package/dist-server/service/reference/reference-progress-subscription.js.map +0 -1
- package/dist-server/service/reference/reference-progress.js.map +0 -1
- package/dist-server/service/reference/reference-reconciliation-query.js.map +0 -1
- package/dist-server/service/reference/reference-reconciliation-writer.js.map +0 -1
- package/dist-server/service/reference/reference-reconciliation.js.map +0 -1
- package/dist-server/service/reference/reference-registry.js.map +0 -1
- package/dist-server/service/reference/reference-resolver.js.map +0 -1
- package/dist-server/service/reference/template-registry.js.map +0 -1
- package/dist-server/service/reference/twin-reference-reconciliation.js.map +0 -1
- package/dist-server/service/reference/twin-reference.js.map +0 -1
- package/dist-server/service/twin-attention/index.js.map +0 -1
- package/dist-server/service/twin-attention/twin-attention-query.js.map +0 -1
- package/dist-server/service/twin-audit/command-audit.js.map +0 -1
- package/dist-server/service/twin-audit/index.js.map +0 -1
- package/dist-server/service/twin-audit/twin-audit-event.js.map +0 -1
- package/dist-server/service/twin-audit/twin-audit-query.js.map +0 -1
- package/dist-server/service/twin-backfill/backfill-period-facts.js.map +0 -1
- package/dist-server/service/twin-backfill/backfill-shape.js.map +0 -1
- package/dist-server/service/twin-backfill/index.js.map +0 -1
- package/dist-server/service/twin-backfill/twin-backfill-resolver.js.map +0 -1
- package/dist-server/service/twin-control/index.js.map +0 -1
- package/dist-server/service/twin-control/twin-control-mutation.js.map +0 -1
- package/dist-server/service/twin-event/index.js.map +0 -1
- package/dist-server/service/twin-event/journal-count.js.map +0 -1
- package/dist-server/service/twin-event/twin-event-keys.js.map +0 -1
- package/dist-server/service/twin-event/twin-event-type.js.map +0 -1
- package/dist-server/service/twin-event/twin-event.js.map +0 -1
- package/dist-server/service/twin-forecast/forecast-metrics.js.map +0 -1
- package/dist-server/service/twin-forecast/forecast-tuning.js.map +0 -1
- package/dist-server/service/twin-forecast/gap-analytics.js.map +0 -1
- package/dist-server/service/twin-forecast/index.js.map +0 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js.map +0 -1
- package/dist-server/service/twin-ingest-window/index.js.map +0 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +0 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +0 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +0 -1
- package/dist-server/service/twin-instance/index.js.map +0 -1
- package/dist-server/service/twin-instance/twin-instance.js.map +0 -1
- package/dist-server/service/twin-journal/event-type-split-shape.js.map +0 -1
- package/dist-server/service/twin-journal/event-type-split.js.map +0 -1
- package/dist-server/service/twin-journal/index.js.map +0 -1
- package/dist-server/service/twin-journal/journal-order.js.map +0 -1
- package/dist-server/service/twin-journal/twin-journal-query.js.map +0 -1
- package/dist-server/service/twin-lifecycle/domain-catalog.js.map +0 -1
- package/dist-server/service/twin-lifecycle/index.js.map +0 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +0 -1
- package/dist-server/service/twin-metrics/index.js.map +0 -1
- package/dist-server/service/twin-metrics/twin-metrics-query.js.map +0 -1
- package/dist-server/service/twin-model/axis-journal-evidence.js.map +0 -1
- package/dist-server/service/twin-model/choose-recipe.js.map +0 -1
- package/dist-server/service/twin-model/epcis-coverage.js.map +0 -1
- package/dist-server/service/twin-model/external-resolver.js.map +0 -1
- package/dist-server/service/twin-model/iec61850-coverage.js.map +0 -1
- package/dist-server/service/twin-model/index.js.map +0 -1
- package/dist-server/service/twin-model/isa95-coverage.js.map +0 -1
- package/dist-server/service/twin-model/item-ref.js.map +0 -1
- package/dist-server/service/twin-model/name-index.js.map +0 -1
- package/dist-server/service/twin-model/project-structure.js.map +0 -1
- package/dist-server/service/twin-model/standard-coverage.js.map +0 -1
- package/dist-server/service/twin-model/status-tally.js.map +0 -1
- package/dist-server/service/twin-model/twin-equipment.js.map +0 -1
- package/dist-server/service/twin-model/twin-lineage-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-location.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-item-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-mutation.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-operation.js.map +0 -1
- package/dist-server/service/twin-readiness/index.js.map +0 -1
- package/dist-server/service/twin-readiness/twin-readiness-query.js.map +0 -1
- package/dist-server/service/twin-space/area-resolver.js.map +0 -1
- package/dist-server/service/twin-space/index.js.map +0 -1
- package/dist-server/service/twin-space/move-space.js.map +0 -1
- package/dist-server/service/twin-space/representation-role.js.map +0 -1
- package/dist-server/service/twin-space/space-integrity.js.map +0 -1
- package/dist-server/service/twin-space/twin-area.js.map +0 -1
- package/dist-server/service/twin-space/twin-space-area.js.map +0 -1
- package/dist-server/service/twin-space/twin-space-representation.js.map +0 -1
- package/dist-server/service/twin-space/twin-space-resolver.js.map +0 -1
- package/dist-server/service/twin-space/twin-space.js.map +0 -1
- package/dist-server/service/twin-state/index.js.map +0 -1
- package/dist-server/service/twin-state/twin-state-subscription.js.map +0 -1
- package/dist-server/service/twin-structure/index.js.map +0 -1
- package/dist-server/service/twin-structure/twin-structure.js.map +0 -1
- package/dist-server/service/twin-subject/event-subjects.js.map +0 -1
- package/dist-server/service/twin-subject/index.js.map +0 -1
- package/dist-server/service/twin-subject/item-resolver.js.map +0 -1
- package/dist-server/service/twin-subject/subject-query-shape.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-backfill.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-event.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-query.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-writer.js.map +0 -1
- package/dist-server/service/twin-target/index.js.map +0 -1
- package/dist-server/service/twin-target/twin-target-resolver.js.map +0 -1
- package/dist-server/service/twin-target/twin-target.js.map +0 -1
- package/dist-shared/axis-read.js.map +0 -1
- package/dist-shared/entity-delta.js.map +0 -1
- package/dist-shared/kpi-broadcast.js.map +0 -1
- package/dist-shared/touched-items.js.map +0 -1
- package/dist-shared/twin-level.js.map +0 -1
- package/server/engine/attention-digest.ts +0 -102
- package/server/engine/canonical-ingest.ts +0 -511
- package/server/engine/checkpoint-fold.ts +0 -12
- package/server/engine/command-routing.ts +0 -67
- package/server/engine/declared-stimulus.ts +0 -66
- package/server/engine/energy-topology.ts +0 -189
- package/server/engine/event-time.ts +0 -96
- package/server/engine/index.ts +0 -51
- package/server/engine/ingest-dedupe.ts +0 -24
- package/server/engine/ingest-health.ts +0 -24
- package/server/engine/integration-coverage.ts +0 -147
- package/server/engine/integration-probes.ts +0 -144
- package/server/engine/integration-runner.ts +0 -95
- package/server/engine/integration-target-profile.ts +0 -103
- package/server/engine/kpi-baseline.ts +0 -202
- package/server/engine/kpi-fold.ts +0 -1516
- package/server/engine/kpi-query.ts +0 -1210
- package/server/engine/kpi-target.ts +0 -248
- package/server/engine/live-attentions.ts +0 -30
- package/server/engine/live-feed-registry.ts +0 -59
- package/server/engine/load-meter.ts +0 -393
- package/server/engine/local-declarations.ts +0 -779
- package/server/engine/log.ts +0 -72
- package/server/engine/loop-lag.ts +0 -120
- package/server/engine/measured-estimator.ts +0 -91
- package/server/engine/measured-yield.ts +0 -89
- package/server/engine/model-basis.ts +0 -162
- package/server/engine/model-gap.ts +0 -168
- package/server/engine/model-refusal.ts +0 -31
- package/server/engine/model-vocabulary.ts +0 -82
- package/server/engine/oee-accumulator.ts +0 -195
- package/server/engine/operation-basis.ts +0 -131
- package/server/engine/producer-guard.ts +0 -64
- package/server/engine/property-effects.ts +0 -216
- package/server/engine/read-time.ts +0 -77
- package/server/engine/restart-policy.ts +0 -55
- package/server/engine/runtime-key.ts +0 -58
- package/server/engine/spec-coverage.ts +0 -105
- package/server/engine/stage-path.ts +0 -172
- package/server/engine/state-axes.ts +0 -60
- package/server/engine/structure-diff.ts +0 -88
- package/server/engine/travel-estimator.ts +0 -138
- package/server/engine/twin-engine.ts +0 -4979
- package/server/engine/twin-state-channel.ts +0 -39
- package/server/engine/warm-start.ts +0 -265
- package/server/index.ts +0 -90
- package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +0 -43
- package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +0 -54
- package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +0 -53
- package/server/migrations/1786300000000-IndexEventTypeByTime.ts +0 -48
- package/server/migrations/1786400000000-IndexEventCreatedAt.ts +0 -38
- package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +0 -93
- package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +0 -66
- package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +0 -82
- package/server/migrations/1786800000000-CreateTwinReferenceReconciliations.ts +0 -39
- package/server/migrations/index.ts +0 -25
- package/server/routes.ts +0 -75
- package/server/service/actuation/actuation-advisor.ts +0 -131
- package/server/service/actuation/actuation-outcome.ts +0 -97
- package/server/service/actuation/actuation-rule-resolver.ts +0 -147
- package/server/service/actuation/actuation-rule.ts +0 -139
- package/server/service/actuation/approval-gateway.ts +0 -44
- package/server/service/actuation/catch-up-effects.ts +0 -152
- package/server/service/actuation/command-dispatcher.ts +0 -474
- package/server/service/actuation/command-store.ts +0 -236
- package/server/service/actuation/dispatch-after-approval.ts +0 -71
- package/server/service/actuation/effect-match.ts +0 -124
- package/server/service/actuation/index.ts +0 -27
- package/server/service/actuation/retry-plan.ts +0 -145
- package/server/service/actuation/rule-evaluate.ts +0 -352
- package/server/service/actuation/rule-loop.ts +0 -160
- package/server/service/actuation/rule-runner.ts +0 -216
- package/server/service/actuation/rule-wiring.ts +0 -84
- package/server/service/actuation/settle-effects.ts +0 -115
- package/server/service/actuation/sweep-dispatch.ts +0 -179
- package/server/service/actuation/twin-command-resolver.ts +0 -387
- package/server/service/actuation/twin-command.ts +0 -232
- package/server/service/actuation/twin-now.ts +0 -97
- package/server/service/index.ts +0 -100
- package/server/service/reference/actuation-routing.ts +0 -192
- package/server/service/reference/actuation-target.ts +0 -163
- package/server/service/reference/actuation-verification.ts +0 -85
- package/server/service/reference/attention-lane.ts +0 -21
- package/server/service/reference/connection-portability-resolver.ts +0 -171
- package/server/service/reference/connection-portability.ts +0 -329
- package/server/service/reference/control-routing.ts +0 -62
- package/server/service/reference/discovery-result.ts +0 -95
- package/server/service/reference/fill-cadence.ts +0 -29
- package/server/service/reference/fill-dedupe.ts +0 -66
- package/server/service/reference/fill-loop.ts +0 -153
- package/server/service/reference/fill-span.ts +0 -31
- package/server/service/reference/hook-contract.ts +0 -364
- package/server/service/reference/hook-rejected.ts +0 -53
- package/server/service/reference/hook-store.ts +0 -28
- package/server/service/reference/index.ts +0 -18
- package/server/service/reference/ingest-space.ts +0 -104
- package/server/service/reference/knob-defaults.ts +0 -59
- package/server/service/reference/live-cadence.ts +0 -129
- package/server/service/reference/live-feed-lease.ts +0 -56
- package/server/service/reference/live-ingest.ts +0 -94
- package/server/service/reference/reference-adapter.ts +0 -985
- package/server/service/reference/reference-assessment.ts +0 -250
- package/server/service/reference/reference-fill-run.ts +0 -179
- package/server/service/reference/reference-fill.ts +0 -223
- package/server/service/reference/reference-hook.ts +0 -479
- package/server/service/reference/reference-link-groups.ts +0 -21
- package/server/service/reference/reference-links.ts +0 -77
- package/server/service/reference/reference-live.ts +0 -420
- package/server/service/reference/reference-master.ts +0 -999
- package/server/service/reference/reference-probe.ts +0 -264
- package/server/service/reference/reference-progress-channel.ts +0 -26
- package/server/service/reference/reference-progress-subscription.ts +0 -78
- package/server/service/reference/reference-progress.ts +0 -95
- package/server/service/reference/reference-reconciliation-query.ts +0 -28
- package/server/service/reference/reference-reconciliation-writer.ts +0 -38
- package/server/service/reference/reference-reconciliation.ts +0 -55
- package/server/service/reference/reference-registry.ts +0 -17
- package/server/service/reference/reference-resolver.ts +0 -969
- package/server/service/reference/template-registry.ts +0 -85
- package/server/service/reference/twin-reference-reconciliation.ts +0 -27
- package/server/service/reference/twin-reference.ts +0 -190
- package/server/service/twin-attention/index.ts +0 -3
- package/server/service/twin-attention/twin-attention-query.ts +0 -70
- package/server/service/twin-audit/command-audit.ts +0 -114
- package/server/service/twin-audit/index.ts +0 -5
- package/server/service/twin-audit/twin-audit-event.ts +0 -158
- package/server/service/twin-audit/twin-audit-query.ts +0 -72
- package/server/service/twin-backfill/backfill-period-facts.ts +0 -168
- package/server/service/twin-backfill/backfill-shape.ts +0 -86
- package/server/service/twin-backfill/index.ts +0 -3
- package/server/service/twin-backfill/twin-backfill-resolver.ts +0 -35
- package/server/service/twin-control/index.ts +0 -3
- package/server/service/twin-control/twin-control-mutation.ts +0 -150
- package/server/service/twin-event/index.ts +0 -3
- package/server/service/twin-event/journal-count.ts +0 -53
- package/server/service/twin-event/twin-event-keys.ts +0 -215
- package/server/service/twin-event/twin-event-type.ts +0 -68
- package/server/service/twin-event/twin-event.ts +0 -250
- package/server/service/twin-forecast/forecast-metrics.ts +0 -106
- package/server/service/twin-forecast/forecast-tuning.ts +0 -40
- package/server/service/twin-forecast/gap-analytics.ts +0 -139
- package/server/service/twin-forecast/index.ts +0 -3
- package/server/service/twin-forecast/twin-forecast-query.ts +0 -486
- package/server/service/twin-ingest-window/index.ts +0 -7
- package/server/service/twin-ingest-window/twin-ingest-window-query.ts +0 -125
- package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +0 -57
- package/server/service/twin-ingest-window/twin-ingest-window.ts +0 -113
- package/server/service/twin-instance/index.ts +0 -3
- package/server/service/twin-instance/twin-instance.ts +0 -199
- package/server/service/twin-journal/event-type-split-shape.ts +0 -112
- package/server/service/twin-journal/event-type-split.ts +0 -144
- package/server/service/twin-journal/index.ts +0 -3
- package/server/service/twin-journal/journal-order.ts +0 -20
- package/server/service/twin-journal/twin-journal-query.ts +0 -615
- package/server/service/twin-lifecycle/domain-catalog.ts +0 -51
- package/server/service/twin-lifecycle/index.ts +0 -3
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +0 -285
- package/server/service/twin-metrics/index.ts +0 -3
- package/server/service/twin-metrics/twin-metrics-query.ts +0 -172
- package/server/service/twin-model/axis-journal-evidence.ts +0 -57
- package/server/service/twin-model/choose-recipe.ts +0 -31
- package/server/service/twin-model/epcis-coverage.ts +0 -251
- package/server/service/twin-model/external-resolver.ts +0 -173
- package/server/service/twin-model/iec61850-coverage.ts +0 -111
- package/server/service/twin-model/index.ts +0 -25
- package/server/service/twin-model/isa95-coverage.ts +0 -320
- package/server/service/twin-model/item-ref.ts +0 -80
- package/server/service/twin-model/name-index.ts +0 -94
- package/server/service/twin-model/project-structure.ts +0 -213
- package/server/service/twin-model/standard-coverage.ts +0 -35
- package/server/service/twin-model/status-tally.ts +0 -37
- package/server/service/twin-model/twin-equipment.ts +0 -191
- package/server/service/twin-model/twin-lineage-query.ts +0 -327
- package/server/service/twin-model/twin-location.ts +0 -147
- package/server/service/twin-model/twin-model-item-query.ts +0 -1029
- package/server/service/twin-model/twin-model-mutation.ts +0 -503
- package/server/service/twin-model/twin-model-query.ts +0 -792
- package/server/service/twin-model/twin-model-tree-query.ts +0 -211
- package/server/service/twin-model/twin-operation.ts +0 -157
- package/server/service/twin-readiness/index.ts +0 -3
- package/server/service/twin-readiness/twin-readiness-query.ts +0 -96
- package/server/service/twin-space/area-resolver.ts +0 -75
- package/server/service/twin-space/index.ts +0 -8
- package/server/service/twin-space/move-space.ts +0 -262
- package/server/service/twin-space/representation-role.ts +0 -15
- package/server/service/twin-space/space-integrity.ts +0 -293
- package/server/service/twin-space/twin-area.ts +0 -63
- package/server/service/twin-space/twin-space-area.ts +0 -66
- package/server/service/twin-space/twin-space-representation.ts +0 -99
- package/server/service/twin-space/twin-space-resolver.ts +0 -582
- package/server/service/twin-space/twin-space.ts +0 -148
- package/server/service/twin-state/index.ts +0 -3
- package/server/service/twin-state/twin-state-subscription.ts +0 -62
- package/server/service/twin-structure/index.ts +0 -3
- package/server/service/twin-structure/twin-structure.ts +0 -96
- package/server/service/twin-subject/event-subjects.ts +0 -162
- package/server/service/twin-subject/index.ts +0 -10
- package/server/service/twin-subject/item-resolver.ts +0 -92
- package/server/service/twin-subject/subject-query-shape.ts +0 -84
- package/server/service/twin-subject/twin-subject-backfill.ts +0 -196
- package/server/service/twin-subject/twin-subject-event.ts +0 -101
- package/server/service/twin-subject/twin-subject-fast-path.ts +0 -346
- package/server/service/twin-subject/twin-subject-query.ts +0 -210
- package/server/service/twin-subject/twin-subject-writer.ts +0 -189
- package/server/service/twin-target/index.ts +0 -5
- package/server/service/twin-target/twin-target-resolver.ts +0 -142
- package/server/service/twin-target/twin-target.ts +0 -97
- package/server/types/global.d.ts +0 -22
- package/shared/axis-read.ts +0 -28
- package/shared/entity-delta.ts +0 -335
- package/shared/kpi-broadcast.ts +0 -13
- package/shared/touched-items.ts +0 -73
- package/shared/twin-level.ts +0 -48
- package/test/ack-shape-alignment.test.ts +0 -97
- package/test/actuation-advisor.test.ts +0 -55
- package/test/actuation-approval-door.test.ts +0 -411
- package/test/actuation-dispatch.test.ts +0 -209
- package/test/actuation-effect.test.ts +0 -162
- package/test/actuation-outcome.test.ts +0 -152
- package/test/actuation-rule-runner.test.ts +0 -281
- package/test/actuation-rule.test.ts +0 -266
- package/test/actuation-seam.test.ts +0 -255
- package/test/actuation-settle.test.ts +0 -164
- package/test/actuation-target.test.ts +0 -145
- package/test/actuation-verification-state.test.ts +0 -139
- package/test/adopt-structure-live.test.ts +0 -133
- package/test/aggregate-not-findone.test.ts +0 -112
- package/test/area-resolver-db.test.ts +0 -110
- package/test/attention-digest.test.ts +0 -161
- package/test/axis-declaration-passthrough-db.test.ts +0 -152
- package/test/axis-journal-evidence.test.ts +0 -71
- package/test/axis-read.test.ts +0 -188
- package/test/backfill-shape.test.ts +0 -89
- package/test/boot-resume.test.ts +0 -287
- package/test/broadcast-cost-baseline.test.ts +0 -201
- package/test/broadcast-period.test.ts +0 -58
- package/test/broadcast-queue-overflow.test.ts +0 -244
- package/test/canonical-ingest-vocabularies.test.ts +0 -451
- package/test/canonical-quantity-door.test.ts +0 -61
- package/test/capability-mapping.test.ts +0 -89
- package/test/checkpoint-refuses-empty.test.ts +0 -103
- package/test/choose-recipe.test.ts +0 -117
- package/test/column-type-portability.test.ts +0 -122
- package/test/command-routing.test.ts +0 -61
- package/test/command-store-writes-columns.test.ts +0 -126
- package/test/connection-portability-doors.test.ts +0 -87
- package/test/connector-capability-declaration.test.ts +0 -195
- package/test/contract-layer-guard.test.ts +0 -48
- package/test/control-capability.test.ts +0 -98
- package/test/cursor-stall-not-read-failure.test.ts +0 -126
- package/test/declaration-reaches-model.test.ts +0 -226
- package/test/declared-location-types.test.ts +0 -89
- package/test/declared-stimulus.test.ts +0 -88
- package/test/dedupe-transformation.test.ts +0 -112
- package/test/discovery-result.test.ts +0 -75
- package/test/dispatch-after-approval-source.test.ts +0 -81
- package/test/duration-estimators.test.ts +0 -144
- package/test/energy-topology.test.ts +0 -113
- package/test/entity-delta.test.ts +0 -352
- package/test/equipment-identity-reaches.test.ts +0 -57
- package/test/event-subjects.test.ts +0 -148
- package/test/event-time-column.test.ts +0 -67
- package/test/event-type-split.test.ts +0 -178
- package/test/external-resolver.test.ts +0 -177
- package/test/fact-scope-wiring.test.ts +0 -96
- package/test/fill-dedupe.test.ts +0 -59
- package/test/fill-loop.test.ts +0 -35
- package/test/first-envelope.test.ts +0 -153
- package/test/fold-gap-speaks.test.ts +0 -53
- package/test/fold-shift-dst.test.ts +0 -110
- package/test/forecast-metrics.test.ts +0 -157
- package/test/forecast-tuning.test.ts +0 -42
- package/test/gap-analytics.test.ts +0 -113
- package/test/generated-not-counted.test.ts +0 -99
- package/test/guard-roots.ts +0 -76
- package/test/home-in-area.test.ts +0 -90
- package/test/hook-address.test.ts +0 -28
- package/test/hook-rejected-shape.test.ts +0 -86
- package/test/hook-response-sum.test.ts +0 -193
- package/test/hook-sequence.test.ts +0 -333
- package/test/ingest-bench.test.ts +0 -70
- package/test/ingest-dedupe.test.ts +0 -56
- package/test/ingest-expected-quiet.test.ts +0 -111
- package/test/ingest-health-engine.test.ts +0 -248
- package/test/ingest-health-wiring.test.ts +0 -120
- package/test/ingest-health.test.ts +0 -306
- package/test/ingest-history.test.ts +0 -247
- package/test/ingest-idempotent.test.ts +0 -211
- package/test/ingest-reconcile-four-ways.test.ts +0 -97
- package/test/ingest-rules-header.test.ts +0 -100
- package/test/ingest-running-guard.test.ts +0 -136
- package/test/ingest-space.test.ts +0 -78
- package/test/ingest-window-rolls-unobserved.test.ts +0 -72
- package/test/ingest-wiring-guard.test.ts +0 -197
- package/test/instance-cache-lifecycle.test.ts +0 -110
- package/test/intake-mapping-parity.test.ts +0 -175
- package/test/integration-probes.test.ts +0 -103
- package/test/integration-runner.test.ts +0 -95
- package/test/item-ref.test.ts +0 -78
- package/test/journal-order-axis.test.ts +0 -80
- package/test/journal-read-discipline.test.ts +0 -186
- package/test/journal-retention.test.ts +0 -275
- package/test/journal-sort-axis.test.ts +0 -142
- package/test/journal-write-door.test.ts +0 -110
- package/test/journal-write-trend.test.ts +0 -115
- package/test/kernel-kind-guard.test.ts +0 -98
- package/test/knob-defaults.test.ts +0 -72
- package/test/kpi-baseline-db.test.ts +0 -216
- package/test/kpi-baseline.test.ts +0 -196
- package/test/kpi-fold.test.ts +0 -1456
- package/test/kpi-query-bench.test.ts +0 -130
- package/test/lens-own-places.test.ts +0 -50
- package/test/lineage-survives-restart.test.ts +0 -234
- package/test/live-cadence.test.ts +0 -170
- package/test/live-cursor-wiring.test.ts +0 -87
- package/test/live-feed-lease.test.ts +0 -63
- package/test/live-feed-registry.test.ts +0 -75
- package/test/live-kernel-facts.test.ts +0 -161
- package/test/live-mirror-parity.test.ts +0 -286
- package/test/load-meter.test.ts +0 -328
- package/test/local-declarations.test.ts +0 -662
- package/test/log-stamp.test.ts +0 -59
- package/test/loop-lag.test.ts +0 -82
- package/test/master-to-twin.test.ts +0 -279
- package/test/measured-yield.test.ts +0 -90
- package/test/merge-streams.test.ts +0 -70
- package/test/mirror-resumes-from-checkpoint.test.ts +0 -192
- package/test/model-basis.test.ts +0 -141
- package/test/model-gap.test.ts +0 -153
- package/test/model-refusal.test.ts +0 -75
- package/test/model-vocabulary.test.ts +0 -114
- package/test/move-space.test.ts +0 -149
- package/test/mutation-gate.test.ts +0 -122
- package/test/oee-accumulator.test.ts +0 -204
- package/test/oee-site-calendar.test.ts +0 -146
- package/test/open-doors.test.ts +0 -197
- package/test/operation-basis.test.ts +0 -127
- package/test/operational-vocabulary.test.ts +0 -108
- package/test/operations-capability-db.test.ts +0 -165
- package/test/order-and-transaction-split.test.ts +0 -107
- package/test/order-fold-host.test.ts +0 -112
- package/test/producer-guard.test.ts +0 -66
- package/test/project-structure-db.test.ts +0 -226
- package/test/projection-reaches-screen.test.ts +0 -277
- package/test/projection-reads-declared.test.ts +0 -109
- package/test/property-effects.test.ts +0 -128
- package/test/provenance-promotion.test.ts +0 -99
- package/test/read-failure-ledger.test.ts +0 -106
- package/test/read-failure-visible.test.ts +0 -145
- package/test/read-time.test.ts +0 -118
- package/test/reference-fill.test.ts +0 -235
- package/test/reference-grounding.test.ts +0 -70
- package/test/reference-hook.test.ts +0 -177
- package/test/reference-links.test.ts +0 -56
- package/test/reference-reconciliation.test.ts +0 -39
- package/test/registry-key-guard.test.ts +0 -80
- package/test/rejection-carries-event-id.test.ts +0 -101
- package/test/rename-twin.test.ts +0 -89
- package/test/resolve-ts-siblings.mjs +0 -52
- package/test/restart-policy.test.ts +0 -111
- package/test/resync-origin-site.test.ts +0 -83
- package/test/retry-plan.test.ts +0 -139
- package/test/revision-axis.test.ts +0 -110
- package/test/runtime-key.test.ts +0 -66
- package/test/save-intake-collision.test.ts +0 -91
- package/test/scale-twin-bench.test.ts +0 -103
- package/test/secrets-at-rest.test.ts +0 -135
- package/test/snapshot-freshness.test.ts +0 -60
- package/test/source-outcome-audit.test.ts +0 -104
- package/test/space-integrity.test.ts +0 -223
- package/test/space-representation.test.ts +0 -66
- package/test/space-scope-includes-stopped.test.ts +0 -55
- package/test/spec-coverage.test.ts +0 -113
- package/test/stage-path.test.ts +0 -95
- package/test/standard-coverage.test.ts +0 -148
- package/test/state-axes.test.ts +0 -74
- package/test/status-tally.test.ts +0 -55
- package/test/streamline-e2e.test.ts +0 -76
- package/test/structure-revision-db.test.ts +0 -315
- package/test/subject-fast-path.test.ts +0 -148
- package/test/subject-read-model.test.ts +0 -175
- package/test/sweep-dispatch.test.ts +0 -191
- package/test/tenant-registry-db.test.ts +0 -149
- package/test/time-range.test.ts +0 -152
- package/test/touched-items.test.ts +0 -61
- package/test/twin-audit.test.ts +0 -83
- package/test/twin-event-keys.test.ts +0 -193
- package/test/twin-model-item-db.test.ts +0 -319
- package/test/twin-model-parent-relation-db.test.ts +0 -125
- package/test/twin-model-tree-db.test.ts +0 -209
- package/test/twin-origin-resync.test.ts +0 -133
- package/test/twin-state-channel.test.ts +0 -111
- package/test/vocabulary-guard.test.ts +0 -43
- package/test/warm-start-seam.test.ts +0 -162
- package/test/warm-start.test.ts +0 -297
- package/test/withheld-door.test.ts +0 -95
- package/test/yield-loop.test.ts +0 -199
- package/tsconfig.json +0 -15
- package/tsconfig.shared.json +0 -23
- package/tsconfig.shared.tsbuildinfo +0 -1
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"twin-event.js","sourceRoot":"","sources":["../../../server/service/twin-event/twin-event.ts"],"names":[],"mappings":"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","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'\nimport { ObjectType, Field, ID, Int } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\n\n/*\n * TwinEvent โ append-only ํธ์ ์ด๋ฒคํธ ์ ๋(EPCIS ์ด๋ฒคํธ + ์ด์ ๋ธํ).\n * ์ปค๋ EventJournal ์ ์์ ๋์ โ ์ํ=์ด๋ฒคํธ์ด์ ํจ์(์ฌ๋ถํ
์ DBโreplay ์ฌ๊ตฌ์ฑ).\n * append-only ์ด๋ฏ๋ก updater/deletedAt ์์(์ด๋ ฅ CRUD ๊ฐ ์๋๋ผ ๋ถ๋ณ ์ด๋ฒคํธ ์คํธ๋ฆผ).\n * payload ๋ simple-json(๋ฉํฐDB ์ด์ โ postgres/mysql/sqlite/mssql/oracle ๊ณตํต, DB-specific JSON ํ์
๊ธ์ง).\n * (CLAUDE.md: ๋ชจ๋ @ObjectType/@Field ๋ ์๋ฌธ description ํ์.)\n */\n/*\n * โโ ์ธ๋ฑ์ค ์ค๊ณ (2026-07-31) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ๋ **์ธ์ ์คํธ ๊ฒฝ๋ก์ ๋จ๊ฑฐ์ด append-only ํ
์ด๋ธ**์ด๋ค. ์ธ๋ฑ์ค ํ๋ํ๋๊ฐ ์ฐ๊ธฐ ์ฆํญ์ด๋ฏ๋ก\n * \"์์ผ๋ฉด ์ข์\" ์ธ๋ฑ์ค๋ฅผ ๋ถ์ด์ง ์๋๋ค. ์ค์ ์ง์ ํจํด์ ๋์ํ๋ ๊ฒ๋ง ๋๋ค.\n *\n * ix_0 (domain, instanceId, revision) ์์ฅ ๊ธฐ๋ณธ ์ ๋ ฌยท์ปค์ ํ์ด์งยทreplay(ASC ์ฃผ์ฌ)\n * ix_1 (domain, instanceId, eventTime) ์๊ฐ ์ปค์(untilTime)ยท์๊ฐ์ฐฝ KPI โ ๊ฑฐ์ ๋ชจ๋ ์กฐํ๊ฐ ํ๋ค\n * ix_2 (domain, instanceId, eventType, revision) ํ์
ํํฐ + ์ ๋ ฌ ๋์ ์ถฉ์กฑ(์ค์ผ์ค ํ๋ฉด task/equipment)\n * ix_3 (domain, instanceId, epc) \"์ด ๋ฌผ๊ฑด์ ์ด๋ ฅ\" โ Entity360 ์ ๋ณธ์ง ์ง๋ฌธ\n * ix_4 (domain, instanceId, orderId) \"์ด ์ค๋๊ฐ ์ด๋๊น์ง ๊ฐ๋\"\n * ix_9 (domain, instanceId, bizTransaction) \"์ด ๊ฑฐ๋์ ๋ฌด์จ ์ผ์ด ์์๋\" โ EPCISโ์ค๋์ ๋ค๋ฆฌ\n *\n * bizStepยทlocationIdยทmoverId ๋ ์ปฌ๋ผ๋ง ๋๊ณ ์ธ๋ฑ์ค๋ ๋์ง ์๋๋ค โ ํ ํธ์ ์์์ ์นด๋๋๋ฆฌํฐ๊ฐ\n * ๋ฎ์(์
๋ฌด๋จ๊ณ ๋ช ๊ฐ, ์์น ์๋ฐฑ, ์ค๋น ์์ญ) (domain,instanceId) ๋ก ์ด๋ฏธ ์ขํ์ง ๋ค์ ์์ฌ ํํฐ๋ก\n * ์ถฉ๋ถํ๊ณ , ๋จ๊ฑฐ์ด ํ์ ์ธ๋ฑ์ค๋ฅผ ๋ ์น์ ๊ฐ์น๊ฐ ์๋ค. ์ ๋ ํ๋๊ฐ ์์ฃผ ์ปค์ ธ์ ์ด ์ถ๋ค์ ์กฐํ๊ฐ\n * ๋๋ ค์ง๋ฉด ๊ทธ๋ ์ธก์ ์ ๊ทผ๊ฑฐ๋ก ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ ์ผ์ด์ง, ์ง๋ ์น์ด ์ฐ๊ธฐ๋ฅผ ๋ฌด๊ฒ๊ฒ ํ ์ผ์ ์๋๋ค.\n */\n@Entity()\n@Index('ix_twin_event_0', (e: TwinEvent) => [e.domain, e.instanceId, e.revision], { unique: false })\n@Index('ix_twin_event_1', (e: TwinEvent) => [e.domain, e.instanceId, e.eventTime], { unique: false })\n@Index('ix_twin_event_2', (e: TwinEvent) => [e.domain, e.instanceId, e.eventType, e.revision], { unique: false })\n@Index('ix_twin_event_3', (e: TwinEvent) => [e.domain, e.instanceId, e.epc], { unique: false })\n@Index('ix_twin_event_4', (e: TwinEvent) => [e.domain, e.instanceId, e.orderId], { unique: false })\n/* ix_5 โ \"์ด ์ง์๊ฐ ๋ฌด์์ ์ผ์ผ์ผฐ๋\". ๊ฐ์ฌ ๊ธฐ๋ก์ commandId ๋ก ์ ๋์ ๋ค์ ๊ณ์ฐํ๋ ์ถ. */\n@Index('ix_twin_event_5', (e: TwinEvent) => [e.domain, e.correlationId], { unique: false })\n/* ix_6 โ \"๋ฐ์ถ์ ํ ๋ฒ์ด๋ผ๋ ๊ณ์ฐํ๋\". ์์ผ๋ฉด ๊ทธ ์ง๋ฌธ์ด ์ธ์คํด์ค ์ ๋ ์ ๋ ์ฃผ์ฌ๊ฐ ๋๋ค. */\n@Index('ix_twin_event_6', (e: TwinEvent) => [e.domain, e.instanceId, e.action], { unique: false })\n/*\n * ix_7 โ **\"์ด ์ข
๋ฅ์ ์ฌ์ค์ ์๊ฐ์์ผ๋ก\"** (2026-08-25 ์ค์ธก์ผ๋ก ์ถ๊ฐ)\n *\n * ์ด ์ถ์ด ์์ด์ ๊ณต์ ํ์๋ผ์ธ์ด 22์ด์๋ค. ์ข
๋ฅ๋ก ๊ฑฐ๋ฅด๊ณ ์๊ฐ์ผ๋ก ์ ๋ ฌํ๋ ์กฐํ๊ฐ ๊ฐ ๊ณณ์ด ์์๋ค:\n *\n * ix_2 (โฆ, eventType, revision) ์ข
๋ฅ๋ ๊ฑธ๋ฌ์ง๊ณ ์ ๋ ฌ์ด **์ ํ ์์**๋ค โ 4์ ์ฌ์ค์ ์ต๊ทผ์ผ๋ก ๊ทธ๋ ธ๋ค\n * ix_1 (โฆ, eventTime) ์ ๋ ฌ์ ๋ง๊ณ **์ข
๋ฅ๋ฅผ ๋ชป ๊ฑฐ๋ฅธ๋ค** โ ํ๋ง๋ค ํ
์ด๋ธ์ ์ด์ด ํ์ธํ๋ค\n *\n * ๋ค์ชฝ์ผ๋ก ๊ฑธ์ผ๋ฉด ๊ทธ ํธ์์์ ์ฐพ๋ ์ข
๋ฅ๊ฐ ๋ฉ์ถ ์์ ๊น์ง์ ๋ชจ๋ ํ์ ์ฝ๊ณ ๋ฒ๋ฆฐ๋ค. ์นํํธ๋์์ ์์
\n * ์ฌ์ค์ 8์ 22์ผ์ ๋ฉ์ถฐ ์๊ณ ๊ทธ ๋ค๋ก ๋ฆฌ๋น์ ์ด 110๋ง ๋์์ผ๋ฏ๋ก, 200๊ฑด์ ๋ฟ๊ธฐ๊น์ง 110๋ง ํ์ ์ด์๋ค.\n *\n * ์ ์ฃผ์์ด ใ์ธก์ ์ ๊ทผ๊ฑฐ๋ก ์ถ๊ฐํ ์ผ์ด์ง ์ง๋ ์น์ ์ผ์ ์๋๋คใ๋ผ๊ณ ์ ์ด ๋์๋ค. ๊ทธ ์ธก์ ์ด ๋์๋ค.\n */\n@Index('ix_twin_event_7', (e: TwinEvent) => [e.domain, e.instanceId, e.eventType, e.eventTime], { unique: false })\n/*\n * ix_8 โ **\"์ด ํธ์์ ์ค๋๋ ๊ธฐ๋ก\"** (2026-08-27 ์ค์ธก์ผ๋ก ์ถ๊ฐ)\n *\n * ๋ณด๊ด ๊ธฐ๊ฐ ์ ๋ฆฌ๊ฐ `created_at` ์ผ๋ก ์๋ฅด๋๋ฐ(๋ณด๊ด์ ์ ์ฅ ๋์ด์ ๋ฌธ์ ๋ค) ๊ทธ ์ถ์ ์ธ๋ฑ์ค๊ฐ ์์๋ค.\n * ๊ทธ๋์ ์ ๋ฆฌ๊ฐ ๋งค ๋ฐฐ์น๋ง๋ค ๊ทธ ํธ์์ ์ ๋์ ์ ๋ ์ฃผ์ฌํ๋ค.\n *\n * hatio-mx2 ์ 7์ผ ๋ฐ ํ์ ์ธ๊ธฐ 208์ด โ 1,029๋ง ํ์ ์ ๋ถ ์ฝ๋๋ค(7์ผ ๋ฐ์ 2,446๊ฑด๋ฟ์ด๋ค)\n * revision ์ผ๋ก ํ ํ ์ง๊ธฐ 0.004์ด\n *\n * ์ ๋ฆฌ๋ ํ ์ฐฝ์ 2์ด๋ง ์ฐ๋๋ก ์์ฐ์ด ๊ฑธ๋ ค ์์ด์, ๊ทธ 2์ด๋ฅผ ์ฃผ์ฌ์ ๋ค ์ฐ๊ณ 44๊ฑด๋ง ์ง์ฐ๊ณ ๋ฉ์ท๋ค.\n */\n@Index('ix_twin_event_8', (e: TwinEvent) => [e.domain, e.instanceId, e.createdAt], { unique: false })\n/* ix_9 โ \"์ด ๊ฑฐ๋์ ๋ฌด์จ ์ผ์ด ์์๋\". EPCIS ์ฌ๊ฑด์์ ์ค๋๋ก ๊ฑด๋๊ฐ๋ ๋ค๋ฆฌ(ยง`bizTransaction`). */\n@Index('ix_twin_event_9', (e: TwinEvent) => [e.domain, e.instanceId, e.bizTransaction], { unique: false })\n@ObjectType({ description: 'Append-only twin event journal record (EPCIS event or operational delta).' })\nexport class TwinEvent {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the event record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })\n domain?: Domain\n\n @RelationId((e: TwinEvent) => e.domain)\n domainId?: string\n\n /*\n * ์ด ์ฌ์ค์ ๋ธ ํธ์. **๋น ์ ์๋ค** โ ์ ๋ ํ์ ๋ง๋๋ ๊ณณ์ `journalRow` ํ๋๋ฟ์ด๊ณ ๊ฑฐ๊ธฐ์\n * ํ์ ์ธ์๋ก ๋ฐ๋๋ค. nullable ๋ก ๋๋ฉด ์ฝ๋ ์ชฝ์ด ๋งค๋ฒ `?? ''` ๋ฅผ ๋ฌ๊ฒ ๋๊ณ , ๊ทธ ๋ฐฉ์ด๊ฐ ์ค์ ๋ก๋\n * ์ผ์ด๋์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ๋๋ผ \"๋น ์ธ์คํด์ค์ ์ด๋ฒคํธ\" ๋ผ๋ ์๋ ๊ฐ๋
์ ์ฝ๋์ ๋จ๊ธด๋ค.\n */\n @Column()\n @Field({ description: 'Twin runtime instance id that emitted the event.' })\n instanceId: string\n\n /* ์ปค๋ ๋ดํฌ์ ํ์ ํ๋(`CanonicalEnvelope.eventType`)๋ผ ๋น ์ ์๋ค โ ๊ณ์ฝ์ ๊ทธ๋๋ก ์ฎ๊ธด๋ค. */\n @Column()\n @Field({ description: 'Event type: epcis.* | task.status | equipment.status | order.status.' })\n eventType: string\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'Monotonic state revision at which the event was emitted.' })\n revision?: number\n\n /**\n * ์ด ์ฌ์ค์ด **์ด๋ ๊ณต์ฅ์์** ์ผ์ด๋ฌ๋ โ `TwinStructure.rev`.\n *\n * ์ด๊ฒ์ด ์๋ ์์ ์๋ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ฉด ์ ๋์ ํต์งธ๋ก ์ง์ฐ๋ ๊ฒ์ด ์ ์ผํ ๊ธธ์ด์๋ค(์ ์ง์ฐ๋ฉด ์\n * ์ด๋ฒคํธ๋ฅผ ์ ๊ณต์ฅ์ ๋๊ณ ๊ณ์ฐํด ์ด๋ ฅ์ด ๊ฑฐ์ง๋ง์ ํ๋ค). ์ด ํ ์นธ์ด ์
์งธ ๊ธธ์ ์ฐ๋ค โ ์ฌ์์ด\n * ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ ์ง์ ์์ ์ ํํ ๋ค ์ด์ด์ ๊ณ์ฐํ๋ค.\n *\n * **๋น์ด ์์ ์ ์๋ค**: ์ปฌ๋ผ์ด ์๊ธฐ๊ธฐ ์ ์ ์ฐ์ธ ํ์ด๋ค. ๊ทธ ํ๋ค์ **๊ฐ์ฅ ์ค๋๋ ๋ฆฌ๋น์ **์\n * ์ํ๋ค(0 ์ ์ฑ์ ๋ฃ์ง ์๋๋ค โ 0 ์ \"๋ชจ๋ฆ\" ์ด ์๋๋ผ ์ ํจํ ๋ฒํธ์ฒ๋ผ ๋ณด์ธ๋ค).\n */\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'Structure revision (TwinStructure.rev) in force when this event happened. Absent on rows written before structure revisions existed; those belong to the oldest revision.' })\n structureRev?: number\n\n /*\n * ์ด ์ฌ์ค์ด ์ผ์ด๋ ์๊ฐ(ํธ์์ ์๊ณ). **๋ ์ง ํ์
์ด๋ค.**\n *\n * ์์ ์๋ ๋ฌธ์์ด์ด์๋ค. ์ฝ์ ๋๋ง๋ค `Date.parse` ํ๊ณ , ์ ๋ ฌ์ UTC ISO ๋ง ๋ค์ด์จ๋ค๋ ์ ์ ์์์\n * ์ฌ์ ์ ๋น๊ต๊ฐ ์ฐ์ฐํ ๋ง์๋ค โ `+09:00` ์คํ์
ํ๊ธฐ๊ฐ ํ๋ ์์ด๋ฉด ์๋ฆฌ์ง ์๊ณ ์์๊ฐ ํ๋ฆฐ๋ค.\n * ๊ทธ ์ ์ ๋ ์ปฌ๋ผ ์ด๋์๋ ์ ํ ์์ง ์์๋ค.\n *\n * **ํ์
์ด๋ฆ์ ์ ์ง ์๋๋ค** (2026-08-19 Postgres ๋ถํ
์คํจ๋ก ๊ณ ์นจ).\n *\n * `datetime` ์ ์ ์๋๋ Postgres ๊ฐ ๋ถํ
์ค์ ๊ฑฐ์ ํ๋ค(`DataTypeNotSupportedError`) โ ๊ทธ ์ด๋ฆ์\n * sqliteยทMySQL ์ ๊ฒ์ด๊ณ Postgres ๋ `timestamp` ๋ง ์๋ค. ๊ฑฐ๊พธ๋ก `timestamp` ๋ sqlite ๊ฐ ๋ชจ๋ฅธ๋ค:\n * **๋ค์ฏ ๋๋ผ์ด๋ฒ์ ๋ค ํตํ๋ ์ด๋ฆ์ด ์์ ์๋ค.**\n *\n * ๊ทธ๋์ ์ด๋ฆ์ ๊ณ ๋ฅด๋ ์ผ์ TypeORM ์ ๋งก๊ธด๋ค. `emitDecoratorMetadata` ๊ฐ ์ผ์ ธ ์์ผ๋ฏ๋ก ์ด ์์ฑ์\n * TS ํ์
(`Date`)์์ ๋๋ผ์ด๋ฒ๋ณ ํ์
์ ์ค์ค๋ก ๊ณ ๋ฅธ๋ค(Postgres `timestamp` ยท sqliteยทMySQL `datetime`).\n * ์ด ๋ ํฌ์ ๋ค์ค DB ๊ท์ฝ์ด ์๊ตฌํ๋ ๊ฒ์ด ๋ฐ๋ก ๊ทธ๊ฒ์ด๋ค โ ๋๋ผ์ด๋ฒ ๋ฐฉ์ธ์ ์ฝ๋์ ์ ์ง ์๋๋ค.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Time at which the fact happened on the twin clock.' })\n eventTime?: Date\n\n /*\n * โโ ์น๊ฒฉ๋ ๊ฒ์ ์ถ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * payload ์์ ์๋ ๊ฐ์ ์ธ์ ์คํธ ์์ ์ ๊บผ๋ด ์ค์ปฌ๋ผ์ผ๋ก ๋๋ค(`twin-event-keys.ts` ๊ฐ ๋จ๋
์์ ).\n * payload ๊ฐ ์ฌ์ ํ ์ ๋ณธ์ด๊ณ ์ด๊ฒ๋ค์ **ํ์ ์์ธ**์ด๋ค โ ์๋ก์ด ์ง์ค์ด ์๋๋ผ ์ฐพ์ ์ ์๊ฒ ํ๋ ์ฅ์น.\n * simple-json(TEXT) ์์ ๊ฐ์ 5๊ฐ DB ๋๋ผ์ด๋ฒ ๊ณตํต์ผ๋ก ๊ฑฐ๋ฅผ ๋ฐฉ๋ฒ์ด ์์ด์(๋ฉํฐDB ํธํ ๊ท์น์\n * DB๋ณ JSON ์ฐ์ฐ์ ๊ธ์ง) ์น๊ฒฉ ์ธ์ ์ ํ์ง๊ฐ ์๋ค.\n * ๊ธธ์ด ์ํ 255 ๋ GS1 ์๋ณ์ ๊ท๊ฒฉ ๋๋น ์ถฉ๋ถํ๋ฉฐ, ๋์น๋ ๊ฐ์ ์๋ฆฌ์ง ์๊ณ ์๋ฆฌ์ง ์๊ณ ๊ฒฝ๊ณ ๋ฅผ ๋จ๊ธด๋ค.\n *\n * โโ ์ถ์ ์๋ก ์ถ๊ฐํ ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ์น๊ฒฉ ์ปฌ๋ผ์ ๋ง๋ค๋ฉด **์ด๋ฏธ ์์ธ ํ์ ๋น์ด ์๋ค.** ๊ทธ ํ๋ค์ ์ ์ถ์ผ๋ก ๊ฒ์๋์ง ์๊ณ ,\n * ์ฌ์ฉ์์๊ฒ๋ \"๊ณผ๊ฑฐ๊ฐ ์๋ ๊ฒ\" ์ผ๋ก ๋ณด์ธ๋ค(์๋ฆฌ์ง ์๊ณ ๋น ์ง ๋ฐ์ดํฐ).\n *\n * ์์ ์๋ ๊ธฐ๋ ํ
์ด ๋งค๋ฒ ํ
์ด๋ธ์ ์ดํด ์ฑ์ ๋ค. ๊ทธ๊ฑด ๋ ๊ฐ์ง๋ก ํ๋ ธ๋ค โ ์ ๋์ด ์ปค์ง์๋ก ๋ถํ
์ด\n * ๋๋ ค์ง๊ณ , \"bizStep ์ด ๋น์์ผ๋ฉด ์ ํ\" ์ด๋ผ๋ ์ ์ ๋ฅผ ์ฝ๋์ ๊ณ ์ ํด ๊ทธ ์ ์ ๊ฐ ๊นจ์ง๋ ์๊ฐ\n * (๊ฐ์ฌ ํ์ฒ๋ผ ์
๋ฌด ๋จ๊ณ๊ฐ ์๋ ํ) ๋งค ๋ถํ
๋ง๋ค ํ๋์๋ค. ๊ทธ๋์ ๊ฑท์ด๋๋ค(git: backfill-keys.ts).\n *\n * ์ฑ์ฐ๋ ์ผ์ **๋ง์ด๊ทธ๋ ์ด์
ํ ๋ฒ**์ด ๋ง๋ค(`yarn migration`). ๊ทธ ์ปฌ๋ผ์ ๋ง๋ ๊ฒ์ ๊ทธ๋ ์ด๋ค โ\n * ๋ฒ์ฉ ์ค์บ๋๋ฅผ ๋์ด๋ฆฌ์ง ๋ง ๊ฒ. ๊ฐ๋ฐ ๋ฐ์ดํ๋ผ๋ฉด ๊ทธ๋ฅ ๋ฒ๋ฆฌ๋ ๊ฒ๋ ๋ต์ด๋ค.\n */\n /**\n * ์ด ์ฌ์ค์ ์ผ์ผํจ **์ง์** โ ์ปค๋์ด ์ปค๋งจ๋์์ ์ด์ด ์ค ์๊ด๊ฐ(๊ธฐ๋ณธ์ commandId).\n *\n * ์ด๊ฒ์ด ๊ฐ์ฌ ๊ธฐ๋ก(TwinAuditEvent.commandId)๊ณผ ์ ๋์ ์๋ ์ ์ผํ ๋ค๋ฆฌ๋ค. ์์ผ๋ฉด ์น์ธ ๊ธฐ๋ก์\n * \"์ฌ๋์ด ํ๋ฝํ๋ค\" ๊น์ง์ด๊ณ , ๊ทธ ๋ค ๊ณต์ฅ์ด ์ค์ ๋ก ์ด๋ป๊ฒ ์์ง์๋์ง์ ์ด์ด์ง์ง ์๋๋ค.\n *\n * **๋๋ถ๋ถ์ ํ์ ๋น์ด ์๋ค** โ ์ปค๋งจ๋๊ฐ ์๋๋ผ ์๋ฎฌ ์๊ฐ์ด ๋ณ์ ์ฌ์ค์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๊ฒ์ด ์ ์์ด๊ณ ,\n * ๋น์ด ์๋ค๊ณ \"๋ ์ฑ์์ง ์ ํ\" ์ผ๋ก ๋ณด๋ฉด ์ ๋๋ค(๊ฐ์ ์คํด๋ฅผ bizStep ์์ ์ด๋ฏธ ํ ๋ฒ ํ๋ค).\n */\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Id of the command that caused this fact (kernel correlation id; defaults to the commandId). Empty for facts that simulation time produced rather than a command.' })\n correlationId?: string\n\n /* ์ ํ์ ๋น์ด ์๋ค โ ์น๊ฒฉ ์ ์ ๊ธฐ๋ก๋ ๊ฒ์ด๋ผ **๋ชจ๋ฅธ๋ค**(0 ์ด๋ OBSERVE ๋ก ์์ฅํ์ง ์๋๋ค). */\n @Column({ length: 16, nullable: true })\n @Field({ nullable: true, description: 'EPCIS action (ADD / OBSERVE / DELETE), promoted from the payload. Empty for operational deltas, and for rows journaled before this column existed.' })\n action?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Business step (CBV bizStep tail), promoted from the payload for indexed filtering.' })\n bizStep?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Item identifier (EPC / EPC class / parent id), promoted from the payload for indexed lookup of one item history.' })\n epc?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Internal order identifier, promoted from the payload for indexed lookup of one order history.' })\n orderId?: string\n\n /*\n * **๊ฑฐ๋ ์๋ณ์๋ ์ค๋ ์๋ณ์์ ๋ค๋ฅธ ๊ฒ์ด๋ค.**\n *\n * ์ ์๋ ๋์ด ํ ์นธ(`orderId`)์ ๋ค์ด๊ฐ๋ค. ๊ทธ๋์ ํ ์ค๋์ ์ด๋ ฅ์ด ์์ธ ์์์ ๋ ์ชฝ์ผ๋ก\n * ๊ฐ๋ผ์ก๋ค โ ์ด์ ๋ธํ๋ `order-1`, EPCIS ์ฌ๊ฑด์ `urn:epc:id:gdti:โฆ` ๋ก ์ ํ ์ด๋ ์ด๋ฆ์ผ๋ก\n * ๋ฌผ์ด๋ ์ ๋ฐ๋ง ๋์๋ค(์ค์ธก 2026-09-05: ์ดํ๊ฐ ์์ธ ํ 10,004๊ฐ, ์ค๋ฅ๋ ๋์ง ์์).\n *\n * ์ค๋ ์ฌ๊ฑด์ ๋ ๊ฐ์ ๋ค ๋ค๊ณ ์๋ค. ๊ทธ๋์ ์ด ์นธ์ด **EPCIS ์ฌ๊ฑด์์ ์ค๋๋ก ๊ฑด๋๊ฐ๋ ๋ค๋ฆฌ**๊ฐ\n * ๋๋ค โ ใ์ด ๊ฐ์ฒด๋ฅผ ์ด๋ ๋ ์ํผ๋ก ๋ง๋ค์๋ใ๊ฐ ๊ทธ ๋ค๋ฆฌ๋ก ๋ตํด์ง๋ค.\n */\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Business transaction identifier (PO / SO / production order), promoted from the payload for indexed lookup of one transaction.' })\n bizTransaction?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Location identifier (read point, business location, or the plain location an operational delta carries), promoted from the payload for indexed filtering.' })\n locationId?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Equipment identifier carried by operational deltas, promoted from the payload so one machine history can be asked for on the server. The column keeps the legacy name `moverId`: the journal is append-only history and mixing two names for the same fact across time is worse than an outdated name. Renaming belongs with event-schema versioning.' })\n moverId?: string\n\n /**\n * **Whether the sender declared this fact as having actually happened** โ the envelope's\n * `provenance`, promoted here.\n *\n * โโ Why a column (measured 2026-09-09) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * This table held 1,134 rows, all of them generator output, and **there was nowhere to ask\n * about it**:\n *\n * ```\n * select count(*) from twin_events 1134\n * select count(*) where payload like '%SIM-%' 1134\n * select count(*) where order_id like 'WO-SIM-%' 558 <- half of them\n * ```\n *\n * The only signal was the sender's naming convention (`SIM-`), and the column that convention\n * reaches was empty on half the rows. While it sits inside `payload`, none of the five drivers\n * can answer \"count these without the invented ones\" โ the same reason `action` was promoted.\n *\n * โโ Three states, kept apart โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ```\n * 'simulated' the sender said it was invented\n * 'actual' the sender said it happened\n * null **not declared** โ which is not `actual`\n * ```\n *\n * Folding the last two together means a generator that omits the declaration has its output\n * counted as production, and nothing says so. Hence no default: an absent declaration is not\n * disguised as a valid-looking value (the discipline of `structureRev` and `lastWarningCount`).\n *\n * โโ No index โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * Three possible values is low cardinality within one twin โ the judgement already made for\n * `bizStep` and `locationId`. Performance folds arrive already narrowed by domain, instance and\n * time, so filtering after that is cheap.\n */\n @Column({ length: 16, nullable: true })\n @Field({ nullable: true, description: 'Whether the sending side declared this fact as actually having happened. Either \"actual\" or \"simulated\"; null means it was not declared, which is not the same as actual โ a generator that omits it must not be counted as production.' })\n provenance?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'Raw canonical envelope (EPCIS event or operational delta) as JSON.' })\n payload?: any\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Wall-clock timestamp when the record was persisted.' })\n createdAt?: Date\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"forecast-metrics.js","sourceRoot":"","sources":["../../../server/service/twin-forecast/forecast-metrics.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ์์ธก ์งํ โ **์ค๋
์ท์์ ์ ํ๋๋ฅผ ๋ฝ๋ ๊ท์น.**\n *\n * โโ ์ ์์ ๋ชจ๋์ธ๊ฐ (2026-08-15) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ๊ฐ ๋ฆฌ์กธ๋ฒ ์์ ์์ด์ ์ํ์ด ๋ถ๋ฌ์ฌ ์ ์์๋ค(type-graphqlยทshell ์ ๋ฌผ๊ณ ์๋ค). ๊ทธ๋ฐ๋ฐ ์ฌ๊ธฐ์\n * ํ๋ฆฌ๋ฉด ์์ธก ๊ทธ๋ํ ์ ์ฒด๊ฐ ์๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ๊ฒ์ ๊ทธ๋ฆฐ๋ค โ ์ค๋ฅ ์์ด. ๊ท์น์ ์ํ์ด ๋ฟ๋ ์๋ฆฌ์ ๋๋ค.\n *\n * โโ ์๋์ง ์งํ๋ฅผ ๋ํ ์ด์ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์์ธก ํ๋ฉด์ ์งํ๊ฐ ๋ฌผ๋ฅ ์ฌ์ฏ(์ฌ๊ณ ยท์ ์ ยท์์
ยท์ค๋ยท์ถ๊ณ ยท๋ฐฑ๋ก๊ทธ)์ผ๋ก ๊ณ ์ ๋ผ ์์ด์, ์๋์ง ํธ์์\n * ๊ณ ๋ฅด๋ฉด **๋จ์ ์ง๋ฌธ์ ๋ตํ๋ ๊ทธ๋ํ**๊ฐ ๋ด๋ค. ์๋์ง ํธ์์๋ ์ฌ๊ณ ๋ ์ค๋๋ ์์ผ๋ฏ๋ก ๊ทธ ๊ฐ๋ค์\n * ์ ๋ถ 0 ์ด๊ณ , 0 ์ ใ์๋คใ๊ฐ ์๋๋ผ ใ์ด ํธ์์ ์ง๋ฌธ์ด ์๋๋คใ์ด๋ค.\n *\n * ์ฌ๊ธฐ ๋ํ ์
์ **์ปค๋์ด ์ด๋ฏธ ์ํ๋ก ๋ค๊ณ ์๋ ๊ฒ**์ด๋ค โ ์ ๊ณ์ฐ์ ๋ง๋ค์ง ์์๋ค. ํนํ ๋ถํ ํฉ์\n * ์ปค๋์ด ๋ฟ๋ฆฌ ๊ณ๋๊ธฐ๋ก๋ง ์ธ๋๋ฐ(๊ณ์ธต ๊ณ๋์ ์ด์ค ๊ณ์ ๋ฐฉ์ง), ๊ทธ ๊ท์น์ ์ฌ๊ธฐ์ ๋ค์ ์ฐ๋ฉด ๋ ๋ฒ์ด ๋๋ค.\n * ๊ทธ๋์ ์ง์ ์ ์ง์ ๋ํ์ง ์๊ณ **๊ตฌ๊ฐ ๊ฐ**์ ์ฝ๋๋ค.\n */\n\nimport { isFlowOrder, isOrderTerminal } from '@operato/ops-contract'\n\n/*\n * โโ Folded orders are counted too (ADR-0092 decision 3, ruling 2026-09-24) โโโโโโโโโโโโโ\n *\n * A twin folds finished orders out of its hot list at checkpoint time and keeps only their counts\n * (`foldedOrders.counts`, kind ร terminal status, never trimmed). Counting the hot list alone would drop\n * `orders` and `shipped` the moment a fold happens โ and \"the increase since the fork\" alone would still\n * break `twinForecastGapTrend`, whose actual at T+h is read from recovered state: a fold between T and\n * T+h makes the actual increase negative. So both metrics are cumulative including the folded side, and\n * an increase is the difference of the same number. Which folded kinds are flow orders is asked of the\n * contract's `isFlowOrder`, the same as the hot list; `shipped` uses the same word on both sides.\n */\nfunction foldedFlowOrders(s: any, status?: string): number {\n let n = 0\n for (const [kind, byStatus] of Object.entries((s?.foldedOrders?.counts ?? {}) as Record<string, Record<string, number>>)) {\n if (!isFlowOrder({ kind })) continue\n if (status) n += Number(byStatus?.[status]) || 0\n else for (const c of Object.values(byStatus ?? {})) n += Number(c) || 0\n }\n return n\n}\n\n/** ์ค๋
์ท โ ์ ํ๋. ๊ฐ์ด ์์ผ๋ฉด 0 ์ด ์๋๋ผ **๊ทธ ์งํ๋ฅผ ๊ทธ๋ฆด ์ ์๋ค**๋ ๋ป์ด์ง๋ง, ๊ทธ๋ํ ๊ณ์ฝ์ด\n * ์๋ฅผ ์๊ตฌํ๋ฏ๋ก 0 ์ ๋ธ๋ค โ ๊ทธ๋์ ์๋์ง ์งํ๋ ใ์์ใ์ด 0 ๊ณผ ํท๊ฐ๋ฆฌ์ง ์๋ ๊ฒ๋ง ๊ณจ๋๋ค. */\nexport type MetricFn = (s: any) => number\n\nexport const FORECAST_METRICS: Record<string, MetricFn> = {\n items: s => (s?.items || []).length,\n occupancy: s => (s?.locations || []).reduce((a: number, n: any) => a + (n.occupancy || 0), 0),\n tasks: s => (s?.tasks || []).length,\n /*\n * โโ ์ธ๋ ๊ฒ์ **ํ๋ฆ ์ค๋**๋ค (2026-09-19, ADR-0076 ๋ณดํฌ โฅ) โโโโโโโโโโโโโโโโ\n *\n * ๋ฐ๋ ์ค๋(์
๊ณ ยท ๋ฐํ ์
๊ณ )๋ ๋์ฐฉ์ด ์ธ์ฐ๊ณ ๋์ฐฉ์ด ์ดํํ๋ค. ๊ทธ๋๋ก ์ธ๋ฉด ใ๋๊ฐ ๊ฒใ์ด ๋ฐ์ ๋๋ง๋ค\n * ํ ๊ฑด์ฉ ๋๊ณ ๋ฐฑ๋ก๊ทธ๋ ์์ ์ ์ค์ด๋ ๋ค โ ์์ธก ๊ทธ๋ํ๊ฐ ์์ง๋ ์์ ์ผ์ ๊ทธ๋ฆฐ๋ค. ๋ฌด์์ด ํ๋ฆ\n * ์ค๋์ธ์ง๋ ๊ณ์ฝ์ `isFlowOrder` ํ ๊ณณ์ด ์ ํ๋ค(์ฌ๊ธฐ์ `kind` ๋ฅผ ๋ค์ ์ ์ง ์๋๋ค).\n */\n orders: s => (s?.orders || []).filter(isFlowOrder).length + foldedFlowOrders(s),\n // ์ดํ ์งํ โ ๋ผ์ด๋ธ ์์ธก์ ํต์ฌ ์ง๋ฌธ(\"์ธ์ ๋ค ๋๊ฐ๋ยท๋ฐฑ๋ก๊ทธ ์ธ์ ํ๋ฆฌ๋\").\n shipped: s => (s?.orders || []).filter(isFlowOrder).filter((o: any) => o.status === 'shipped').length + foldedFlowOrders(s, 'shipped'),\n /*\n * โโ ๋ฐฑ๋ก๊ทธ๋ **ใ์ข
๊ฒฐ์ธ๊ฐใ**๋ก ๋ฌป๋๋ค (2026-09-19) โโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ๋ฑ๋ง ๋(`shipped`ยท`cancelled`)๋ก ๋ฌผ์ผ๋ฉด **์๋ณธ์ด ๋ค๋ฅธ ๋ฑ๋ง์ ์ฐ๋ ๋ฏธ๋ฌ์์ ๋๋ ์ค๋๊ฐ ์์\n * ๋ฐฑ๋ก๊ทธ์ ๋จ๋๋ค.** `status` ๋ ์ด๋ฆฐ ์ถ์ด๊ณ (ํ์ค๋ `RequestState` ๋ฅผ ์ด๊ฑฐํ์ง ์๋๋ค) ์ค ์์คํ
์\n * `completed`ยท`FINISHED` ๋ฅผ ์ด๋ค โ ๊ทธ ํธ์์ ๋ฐฑ๋ก๊ทธ ๊ณก์ ์ ๋ด๋ ค๊ฐ์ง ์๋๋ค. ์ข
๊ฒฐ ํ์ ์ ์ปค๋์ด\n * ํ ๊ณณ์์ ํ๋ค(`isOrderTerminal` โ ๋ฑ๋ง์ด ์๋๋ผ **์**์ 1์ฐจ ๊ทผ๊ฑฐ๋ก ๋ณธ๋ค).\n *\n * `shipped` ํ ๋ฑ๋ง์ ๋จ๋๋ค. ๊ทธ๊ฒ์ ์ด ์ปค๋์ด **์๊ธฐ๊ฐ ์ฐ๋ ๋ง**์ด๊ณ (WMS ์ ์ถํ ์๋ฃ), ๊ณ์ฝ์\n * ์ข
๊ฒฐ ๋ชฉ๋ก(`completed` ยท `cancelled`)์๋ ์๋ค. ์์ ๋งํ์ง ์๋ ์ค๋
์ท์์ ๊ทธ ์ค๋๊ฐ ๋ฐฑ๋ก๊ทธ๋ก\n * ๋๋์์ค์ง ์๊ฒ ๋์ ํจ๊ป ๋ณธ๋ค โ ๋นผ๋ ์ชฝ์ด๋ผ ์ด ์
์ด ์ ๋ณด๋ค ์ปค์ง๋ ์ผ์ ์๋ค. ์ปค๋์ ๋ฑ๋ง์ด\n * ๊ณ์ฝ์ ์ข
๊ฒฐ ๋ชฉ๋ก์ ๋ค์ด์ค๋ ๋ ์ด ์ค์ด ์ง์์ง๋ค(์ํคํ
ํธ์๊ฒ ์ฌ๋ฆผ).\n */\n backlog: s =>\n (s?.orders || [])\n .filter(isFlowOrder)\n .filter((o: any) => !isOrderTerminal(o) && o.status !== 'shipped').length,\n\n /*\n * โโ ์๋์ง โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * `peakKW` ๋ **๋ง๊ฐ๋ ๊ตฌ๊ฐ์ ์ต๋**๋ค โ ๋จ์กฐ ์ฆ๊ฐ๋ผ ์งํ์ ์์์ ใ์ต๋์์๊ฐ ์ด๋๊น์ง ์ค๋ฅด๋ใ๋ก\n * ์ฝํ๋ค. ์ด๋ฆฐ ๊ตฌ๊ฐ์ ๋ฃ์ง ์๋๋ค(์์ง ํ์ ์ด ์๋๋ค โ ์ปค๋์ด ์งํค๋ ๊ท์จ์ ์ฌ๊ธฐ์๋ ์งํจ๋ค).\n */\n peakKW: s => Number(s?.energy?.peakSince?.kW) || 0,\n /*\n * ์ด๋ฒ ๊ตฌ๊ฐ์ด ์ด๋๋ก ๊ฐ๋ฉด ์ผ๋ง๋ก ๋ง๊ฐ๋๋ โ ์ปค๋์ด ๋ธ ํฌ์(`mean-so-far`)์ ๊ทธ๋๋ก ์ฝ๋๋ค.\n * ์ฐ๋ฆฌ๊ฐ ๋ค์ ๊ณ์ฐํ์ง ์๋๋ค: ํฌ์ ๊ท์น์ด ๋ ๋ฒ์ด ๋๋ฉด ํ๋ฉด๊ณผ ํ์ ์ด ๋ค๋ฅธ ๋ง์ ํ๋ค.\n */\n projectedKW: s => Number(s?.energy?.open?.projectedKW ?? s?.energy?.open?.meanKW) || 0,\n /*\n * ๊ณ์ฝ์ ๋๊ธด ๊ตฌ๊ฐ ์ โ ใ๋ช ๋ฒ ๋๋ใ๋ ์๊ธ์ด ๊ฑธ๋ฆฐ ์ง๋ฌธ์ด๋ผ ์ต๋์น์ ๋ฐ๋ก ๋ณธ๋ค.\n * ๊ณ์ฝ์ ๋ชจ๋ฅด๋ ํธ์์์๋ ๋ 0 ์ด๋ค(๋๊น์ ํ์ ํ ๊ทผ๊ฑฐ๊ฐ ์๋ค โ ์ง์ด๋ด์ง ์๋๋ค).\n */\n overWindows: s => (s?.energy?.closed || []).filter((w: any) => w?.overContract === true).length\n}\n\n/** ์ด ์งํ๊ฐ ๊ทธ ์ข
๋ฅ์ ํธ์์์ ๋ป์ด ์๋ โ ํ๋ฉด์ด ๋ชฉ๋ก์ ๊ณ ๋ฅผ ๋ ์ด๋ค. */\nexport const ENERGY_METRICS = ['projectedKW', 'peakKW', 'overWindows'] as const\nexport const FLOW_METRICS = ['items', 'occupancy', 'tasks', 'orders', 'shipped', 'backlog'] as const\n\n/**\n * ํธ์ ์ข
๋ฅ์ ๋ง๋ ์งํ ๋ชฉ๋ก โ **ํ ๊ณณ์์ ์ ํ๋ค.**\n *\n * ํ๋ฉด์ด ๊ฐ์ ๋ชฉ๋ก์ ๋ค๊ณ ์์ผ๋ฉด ์ข
๋ฅ๊ฐ ๋ ๋ ์ด๋ ํ๋ฉด์ด ๋ค์ฒ์ก๋์ง ์ ์ ์๋ค.\n */\nexport function metricsForKind(kind?: string): string[] {\n return kind === 'ems' ? [...ENERGY_METRICS] : [...FLOW_METRICS]\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"forecast-tuning.js","sourceRoot":"","sources":["../../../server/service/twin-forecast/forecast-tuning.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAcH,wCAKC;AAjBD,uDAAuD;AAC1C,QAAA,oBAAoB,GAAG,EAAE,CAAA;AACtC,uDAAuD;AAC1C,QAAA,WAAW,GAAG,MAAM,CAAA;AACjC,oCAAoC;AACvB,QAAA,WAAW,GAAG,KAAK,CAAA;AAEhC;;;;GAIG;AACH,SAAgB,cAAc,CAAC,SAAiB;IAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,mBAAW,CAAA;IACrE,MAAM,GAAG,GAAG,SAAS,GAAG,4BAAoB,CAAA;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,mBAAW,CAAC,GAAG,mBAAW,CAAA;IAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,mBAAW,EAAE,IAAI,CAAC,GAAG,CAAC,mBAAW,EAAE,OAAO,CAAC,CAAC,CAAA;AAC9D,CAAC","sourcesContent":["/*\n * ์์ธก์ ์ผ๋ง๋ ์๊ฒ ๊ตด๋ฆด ๊ฒ์ธ๊ฐ โ **ํ ํ์ฐจ์ ํฑ ์๋ฅผ ๋ฌถ๋๋ค.**\n *\n * โโ ์ ํ์ํ๊ฐ (2026-08-17 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์์ธก ๋น์ฉ์ ๊ฑฐ์ ์ ๋ถ๊ฐ ํฑ์ด๋ค. ํธ์ ํ๋์ ์์ธก ํ ๋ฒ์ด 30ํ์ฐจ ร 300ํฑ = 9,000ํฑ, ํ ํฑ 3.2ms โ\n * 28.5์ด์๋ค. ๊ทธ๋ฐ๋ฐ ๋ชฌํ
์นด๋ฅผ๋ก๋ ์งํ์ **๋์์** ์งํ๋ฅผ ํ ๋ฒ ์ฝ๋๋ค โ ์ค๊ฐ์ 1์ด ๋จ์๋ก ๋ณผ ์ด์ ๊ฐ\n * ์๋ค๋ฉด ์ฑ๊ธ๊ฒ ๊ตด๋ ค๋ ๋ต์ด ๊ฐ๋ค.\n *\n * ์ ๋ง ๊ฐ์์ง๋ ์ฌ์ ํ์ธํ๋ค(`operato-twin/test/fork-cost.test.ts`, 10ํ์ฐจยท์งํ์ 5๋ถ):\n *\n * step 1s โ 3,048ms ยท ์ฌ๊ณ p50 325 ยท ์๋ฃ์์
8 ยท ์๋ฃ์ค๋ 0\n * step 5s โ 628ms ยท ์ฌ๊ณ p50 325 ยท ์๋ฃ์์
8 ยท ์๋ฃ์ค๋ 0 โ ๋ต์ด ๊ฐ๊ณ 5๋ฐฐ ์ธ๋ค\n * step 10s โ 286ms ยท ์ฌ๊ณ p50 326 ยท โฆ โ ์ฌ๊ธฐ์๋ถํฐ ํ๋ค๋ฆฐ๋ค\n *\n * โโ ์ ๊ณ ์ step ์ด ์๋๋ผ ํฑ ์ ์ํ์ธ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * step ์ 5์ด๋ก ๋ชป ๋ฐ์ผ๋ฉด 1๋ถ์ง๋ฆฌ ์งํ์ ์ 12ํฑ์ด ๋์ด ๋๋ฌด ์ฑ๊ธ๊ณ , 2์๊ฐ์ง๋ฆฌ๋ 1,440ํฑ์ด๋ผ ์ฌ์ ํ\n * ๋น์ธ๋ค. ๋ฌถ์ด์ผ ํ๋ ๊ฒ์ step ์ด ์๋๋ผ **ํ ํ์ฐจ๊ฐ ๋๋ ํ์**๋ค.\n *\n * ์ํ(10์ด)์ ๋ฐ๋ก ๋๋ ์ด์ : ์งํ์ ์ด ๊ธธ๋ค๊ณ ๋ฌดํ์ ์ฑ๊ธ๊ฒ ๊ตด๋ฆฌ๋ฉด ์งง์ ์์
(์ด ๋จ์ ํผํน)์ด ํต์งธ๋ก\n * ํ ํฑ์ ์ผ์ผ์ง๋ค. ๊ทธ ์ง์ ์ ๋์ง ์๋๋ค.\n */\n\n/** ํ ํ์ฐจ๊ฐ ๋๋ ํฑ ์์ ๋ชฉํ โ ์ด๋ณด๋ค ์๊ฒ ๊ตด๋ ค์ผ ํ ์ด์ ๊ฐ ์๊ธฐ๋ฉด ์ฌ๊ธฐ๋ฅผ ๊ณ ์น๋ค. */\nexport const TARGET_TICKS_PER_RUN = 60\n/** ์๋ฌด๋ฆฌ ์งํ์ ์ด ๊ธธ์ด๋ ์ด๋ณด๋ค ์ฑ๊ธ๊ฒ ๊ตด๋ฆฌ์ง ์๋๋ค โ ์งง์ ์์
์ด ํ ํฑ์ ์ผ์ผ์ง๋ค. */\nexport const MAX_STEP_MS = 10_000\n/** ์ปค๋์ ์๊ฐ ๋จ์ โ ์ด๋ณด๋ค ์๊ฒ ๊ตด๋ฆด ์ด์ ๋ ์๋ค. */\nexport const MIN_STEP_MS = 1_000\n\n/**\n * ์ด ์งํ์ ์ ๊ตด๋ฆด ํฑ ํฌ๊ธฐ.\n *\n * ์ด ๋จ์๋ก ๋จ์ด๋จ๋ฆฐ๋ค โ 3,333ms ๊ฐ์ ๊ฐ์ ์ฌ๋์ด ์ฝ์ ์๋, ํ๋ฉด์ด ์ค๋ช
ํ ์๋ ์๋ค.\n */\nexport function forecastStepMs(horizonMs: number): number {\n if (!Number.isFinite(horizonMs) || horizonMs <= 0) return MIN_STEP_MS\n const raw = horizonMs / TARGET_TICKS_PER_RUN\n const rounded = Math.round(raw / MIN_STEP_MS) * MIN_STEP_MS\n return Math.min(MAX_STEP_MS, Math.max(MIN_STEP_MS, rounded))\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gap-analytics.js","sourceRoot":"","sources":["../../../server/service/twin-forecast/gap-analytics.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ์์ธก ์ ํ๋ ์ง๋จ โ SPCยท์ ํ๋ยทํธํฅยท๋ณด์ ๊ณ์ฐ์ canonical ๊ตฌํ(์๋ฒ ์์ ).\n * ํ๋ ์ ํ
์ด์
(ํด๋ผ)์ด ์๋๋ผ ์ฌ๊ธฐ์์ ํ ๋ฒ ๊ณ์ฐํด twinForecastGapTrend ๊ฐ ๋๋ ค์ค๋ค โ APIยทtwin-aiยท๊ฒฝ๋ณดยท๋ค๋ฅธ UI ์ฌ์ฌ์ฉ, ์๋ฒ ํ
์คํธ ๊ฐ๋ฅ.\n *\n * ๋ ์ถ(๋
๋ฆฝ):\n * ์์ ์ฑ(stability) โ ์ค์ฐจ ํญ์ด ์ผ์ ํ๊ฐ(SPC I-chart: ๊ด๋ฆฌํ๊ณ ์ดํ=shift, ๋จ์กฐ ์ถ์ธ=drift).\n * ํธํฅ(bias) โ ํ๊ท ์ค์ฐจ(CL)๊ฐ ๋ชฉํ 0 ์์ ๋ฒ์ด๋ฌ๋(CL ์ด ๊ด๋ฆฌํญ ์ ๋ฐ ์ด์ ์ดํ ๋๋ ์ถ์ ์ ํธ ํผ).\n * ๊ด๋ฆฌ๋๋ ์๊ธฐ ํ๊ท (CL)์ ์ค์ฌ์ผ๋ก ์ก์ผ๋ฏ๋ก \"์์ ์ \"์ด \"๋ฌดํธํฅ\"์ ๋ปํ์ง ์๋๋ค โ ๊ทธ๋์ ๋ณ๋ ์ถ.\n */\n\n/** SPC I-chart ํ๋ณธ ์ โ ์ ๋ขฐํ ๋งํ ๊ด๋ฆฌํ๊ณ์ ํต์ค ์ต์(20~25) ํํ. ์๋ฒ๊ฐ ๊ด์ฅ(ํํ ๊ณ์ธต ์๋). */\nexport const GAP_SAMPLES = 24\n\nexport interface GapPoint {\n t: number\n p50: number\n min: number\n max: number\n actual: number\n error: number // ์ค์ โ ์์ธก(p50). ์์ = ๊ณผ์์์ธก(์์ธก์ด ๋ฎ์).\n inBand: boolean\n naiveAbsError: number\n modelAbsError: number\n}\n\n/** ํฉ์ฐ ๊ฒฐ๊ณผ + **๋ฌด์์ ๋ชป ๋ฃ์๋์ง.** ์๋ฆฌ์ง ์๊ณ ์ค์ด์ง ์๋๋ค. */\nexport interface AggregateResult {\n points: GapPoint[]\n /** ํ ํธ์์ด๋ผ๋ ์ฌ์ง ๋ชปํด ํต์งธ๋ก ๋บ vantage ์. */\n droppedVantages: number\n}\n\n/**\n * ๊ณต๋๋ฐฐ์น(co-located) ํธ์๋ค์ ์ ๋ฐฐ์ด์ ๊ณต์ฅ ๋จ์ ํ ์๊ณ์ด๋ก ํฉ์ฐ.\n *\n * โโ ์์ ์ ๋ฌด์์ด ์ด๊ธ๋ ์์๋ (2026-08-08) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * \"๋์ผ ๋ถํ
โ vantage ์ ๋ ฌ\" ์ **๊ฐ์ **ํ๊ณ ๋ฐฐ์ด ์ธ๋ฑ์ค๋ผ๋ฆฌ ๋ํ๋ค. ๊ทธ ๊ฐ์ ์ ์ธ ๊ณณ์์ ๊นจ์ก๋ค:\n *\n * โ ๊ฒฉ์๋ฅผ ํธ์๋ง๋ค ์๊ธฐ ์ ๋์ ์ฒซยท๋ง์ง๋ง ์ด๋ฒคํธ๋ก ๋ง๋ค์๋ค. ์ ๋ ๊ตฌ๊ฐ์ด ๋ค๋ฅด๋ฉด ๊ฐ์ ์ธ๋ฑ์ค๊ฐ\n * ์๋ก ๋ค๋ฅธ ์๊ฐ์ด๋ค. **๋ถํ
์ด ๊ฐ์๋** ์ด๊ธ๋๋ค.\n * โก ํ vantage ๋ฅผ ๋ชป ์ฌ๋ฉด `continue` ๋ก ๊ฑด๋๋ฐ๊ณ ๋ฐ์ด ๋ด์๋ค. ๊ทธ ์๊ฐ๋ถํฐ ์ธ๋ฑ์ค๊ฐ ํ ์นธ์ฉ ๋ฐ๋ฆฐ๋ค.\n * โข ๊ธธ์ด๋ฅผ `max` ๋ก ์ก์, ๋ค์ชฝ ์ธ๋ฑ์ค๋ ๋จ์ ํธ์๋ง ๋ํด์ก๋ค โ ๊ณต์ฅ ํฉ๊ณ ๊ณก์ ์ด ๊ผฌ๋ฆฌ์์\n * ์๋๋ก ๊บพ์ธ๋ค. ๊ณต์ฅ๊ณผ ์๋ฌด ์๊ด ์๋ ์ด์ ๋ก.\n *\n * ์
๋ค ์ค๋ฅ๋ฅผ ๋ด์ง ์์๋ค. ๊ทธ๋ด๋ฏํ ๊ณก์ ์ด ๋์ค๊ณ , ๊ทธ ๊ณก์ ์ผ๋ก ์์ธก ์ ํ๋๋ฅผ ํ์ ํ๋ค.\n *\n * โโ ์ง๊ธ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ฒฉ์๋ ๋ฐ์์ ํ๋๋ฅผ ๋ง๋ค์ด ๋ชจ๋์๊ฒ ๊ฐ์ ๊ฒ์ ์ฃผ๊ณ (`sharedGrid`), ๋ชป ์ฐ ์๋ฆฌ๋ `null` ๋ก\n * ๋จ๊ธด๋ค. ์ฌ๊ธฐ์๋ **๋ชจ๋ ํธ์์ด ๊ฐ์ ๊ฐ์ง vantage ๋ง** ๋ํ๋ค. ํ๋๋ผ๋ ๋น๋ฉด ๊ทธ ์๊ฐ์\n * ๊ณต์ฅ ์ด๋์ ์ ์ ์๋ ๊ฒ์ด์ง, ๊ทธ ํธ์์ด 0 ์ ๋ธ ๊ฒ์ด ์๋๋ค.\n *\n * ๋บ ๊ฐ์๋ ๋๋ ค์ค๋ค โ ํ๋ฉด์ด \"24์ ์ค 18์ \" ์ด๋ผ๊ณ ๋งํ ์ ์์ด์ผ ํ๋ค.\n */\nexport function aggregatePoints(per: (GapPoint | null)[][]): AggregateResult {\n if (!per.length) return { points: [], droppedVantages: 0 }\n const n = Math.max(0, ...per.map(pts => pts.length))\n const out: GapPoint[] = []\n let droppedVantages = 0\n for (let i = 0; i < n; i++) {\n const slot = per.map(pts => pts[i])\n if (slot.some(pt => !pt)) { droppedVantages++; continue }\n const pts = slot as GapPoint[]\n const sum = (f: (p: GapPoint) => number) => pts.reduce((a, p) => a + f(p), 0)\n const p50 = sum(p => p.p50)\n const min = sum(p => p.min)\n const max = sum(p => p.max)\n const actual = sum(p => p.actual)\n out.push({\n t: pts[0].t, // ๊ฒฉ์๊ฐ ํ๋์ด๋ฏ๋ก ์ด๋ ํธ์์์ ์ฝ์ด๋ ๊ฐ๋ค.\n p50, min, max, actual,\n error: actual - p50,\n inBand: actual >= min && actual <= max,\n naiveAbsError: sum(p => p.naiveAbsError),\n modelAbsError: sum(p => p.modelAbsError)\n })\n }\n return { points: out, droppedVantages }\n}\n\n/** ์์ ์ฑ ์ถ + ํธํฅ ์ถ ํ์ (๊ด๋ฆฌ๋). errors = ์ค์ โ์์ธก ์๊ณ์ด. */\nexport function computeSpc(errors: number[]): any {\n const n = errors.length\n if (n < 4) return { insufficient: true }\n const cl = errors.reduce((a, b) => a + b, 0) / n\n const mr: number[] = []\n for (let i = 1; i < n; i++) mr.push(Math.abs(errors[i] - errors[i - 1]))\n const mrBar = mr.reduce((a, b) => a + b, 0) / mr.length\n const sigma = mrBar / 1.128 || Math.max(1e-6, Math.abs(cl) * 0.01) // d2(n=2)=1.128\n const ucl = cl + 3 * sigma, lcl = cl - 3 * sigma\n // ์ถ1 ์์ ์ฑ โ ๊ด๋ฆฌํ๊ณ ์ดํ(shift) ๋๋ ๋จ์กฐ ์ถ์ธ(drift).\n const ooc = errors.map((e, i) => (e > ucl || e < lcl ? i : -1)).filter(i => i >= 0)\n let up = 1, down = 1, trend = false\n for (let i = 1; i < n; i++) { up = errors[i] > errors[i - 1] ? up + 1 : 1; down = errors[i] < errors[i - 1] ? down + 1 : 1; if (up >= 6 || down >= 6) trend = true }\n const instability = ooc.length ? 'shift' : trend ? 'drift' : null\n // ์ถ2 ํธํฅ โ ํ๊ท ์ค์ฐจ๊ฐ 0 ์์ ์ดํ. |CL| > 0.5ฯ ๋๋ ์ถ์ ์ ํธ(๋์ ์ค์ฐจ/ํ๊ท ์ ๋์ค์ฐจ) > 4.\n const mad = errors.reduce((s, e) => s + Math.abs(e), 0) / n || 1\n const trackingSignal = errors.reduce((a, b) => a + b, 0) / mad\n const biased = Math.abs(cl) > 0.5 * sigma || Math.abs(trackingSignal) > 4\n return { cl, ucl, lcl, sigma, n, ooc, instability, stable: !instability, biased, biasSign: cl >= 0 ? 'under' : 'over', trackingSignal }\n}\n\n/**\n * ์ง๊ณ ์งํ โ ์ ํ๋(1โWMAPE)ยทํธํฅ(MPE)ยท์์ธก๊ตฌ๊ฐ ์ ์คยทFVA(์์ธก ๊ฐ์น).\n *\n * A percentage whose denominator is zero is **not measured**, and says so with `null` (2026-09-24).\n * When every actual in the window is 0 โ the line stood still, or the metric was not observed โ WMAPE\n * is undefined. It used to become 0, so the card read \"100% accurate\" beside \"0 of 6 in band, mean\n * error โ20\". Likewise `fvaPct` when the naive error is 0: 0 read as \"the forecast adds nothing\".\n * The absolute measures (mean error, in-band count, fva) are real in that window and stay. The two\n * neighbours below already refuse on thin evidence (`computeSpc` ยท `learnedCalibration`).\n */\nexport function gapMetrics(pts: GapPoint[]): any {\n const sumAbsErr = pts.reduce((s, x) => s + Math.abs(x.error), 0)\n const sumActual = pts.reduce((s, x) => s + Math.abs(x.actual), 0)\n const accuracy = sumActual > 0 ? Math.max(0, Math.round((1 - sumAbsErr / sumActual) * 100)) : null\n const mpe = pts.length ? pts.reduce((s, x) => s + x.error, 0) / pts.length : 0\n const coverage = pts.length ? pts.filter(x => x.inBand).length / pts.length : 0\n // ์์ธก ๊ฐ์น(FVA) โ \"ํ์ฌ๊ฐ ๊ทธ๋๋ก\"(naive) ๋๋น ์ค์ฐจ ๊ฐ์. fva=๊ฐ์ ์ด๋, fvaPct=naive ์ค์ฐจ๋ฅผ ๋ช % ์ค์๋(๊ฐ์น์ ํฌ๊ธฐ).\n const sumNaive = pts.reduce((s, x) => s + x.naiveAbsError, 0)\n const sumModel = pts.reduce((s, x) => s + x.modelAbsError, 0)\n const fva = sumNaive - sumModel\n const fvaPct = sumNaive > 0 ? Math.round((1 - sumModel / sumNaive) * 100) : null\n return { accuracy, mpe, coverage, inBandCount: pts.filter(x => x.inBand).length, total: pts.length, fva, fvaPct }\n}\n\n/** ํ์ต(์๊ธฐ๋ณด์ ) ์์ โ ํ๊ท ์ค์ฐจ(ํธํฅ)๋ฅผ ๊ฑท์ด๋์ ๋ ๊ธฐ๋๋๋ ์ ํ๋ยท์ปค๋ฒ๋ฆฌ์ง. accBefore/covBefore ๋ ์๋ณธ ์งํ์์. */\nexport function learnedCalibration(pts: GapPoint[], metrics: any): any {\n if (pts.length < 3) return null\n const errs = pts.map(p => p.error)\n const biasShift = errs.reduce((a, b) => a + b, 0) / errs.length // ํ์ต๋ ํธํฅ(์ด๋งํผ ์์ธก์ ์ฌ๋ฆผ/๋ด๋ฆผ)\n const corrected = errs.map(e => e - biasShift) // ํธํฅ ์ ๊ฑฐ ํ ์์ฐจ\n const absC = corrected.map(Math.abs).sort((a, b) => a - b)\n const halfWidth = absC[Math.floor(absC.length * 0.8)] ?? (absC[absC.length - 1] || 1) // 80% ์ปค๋ฒ๋ฆฌ์ง ๋ฐด๋\n /* The bias is learnable with every actual at 0; the accuracy before and after is not (see gapMetrics). */\n const sumActual = pts.reduce((s, p) => s + Math.abs(p.actual), 0)\n const accAfter = sumActual > 0 ? Math.max(0, Math.round((1 - corrected.reduce((s, e) => s + Math.abs(e), 0) / sumActual) * 100)) : null\n const covAfter = corrected.filter(e => Math.abs(e) <= halfWidth).length\n return { biasShift: Math.round(biasShift), halfWidth: Math.round(halfWidth), accBefore: metrics.accuracy, accAfter, covBefore: metrics.inBandCount, covAfter, n: pts.length }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/twin-forecast/index.ts"],"names":[],"mappings":";;;AAAA,qEAA4D;AAE/C,QAAA,SAAS,GAAG,CAAC,0CAAiB,CAAC,CAAA","sourcesContent":["import { TwinForecastQuery } from './twin-forecast-query.js'\n\nexport const resolvers = [TwinForecastQuery]\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"twin-forecast-query.js","sourceRoot":"","sources":["../../../server/service/twin-forecast/twin-forecast-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { twinLog } from '../../engine/log.js'\nimport { hydratedDate } from '../../engine/read-time.js'\nimport { Arg, Ctx, Int, Mutation, Query, Resolver, Directive, UseMiddleware } from 'type-graphql'\n\nimport { getRepository, ScalarObject, SpeakRefusals } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { readSpecCoverage } from '../../engine/spec-coverage.js'\nimport { describeModelBasis, modelBasisChanged, type ModelBasis } from '../../engine/model-basis.js'\nimport { TwinEvent } from '../twin-event/twin-event.js'\nimport { GAP_SAMPLES, aggregatePoints, computeSpc, gapMetrics, learnedCalibration, type GapPoint } from './gap-analytics.js'\nimport { FORECAST_METRICS, type MetricFn } from './forecast-metrics.js'\nimport { forecastStepMs } from './forecast-tuning.js'\n\n/* ์ปค๋ ์์ธก ํจ์ โ CJS require(twin-engine ๊ณผ ๋์ผ ๋ฐฉ์). */\nconst { monteCarloForecastAsync } = require('@operato/twin-kernel')\n\n/**\n * ์ด๋ฒคํธ ๋ฃจํ์ ์๋ฆฌ๋ฅผ ๋ด์ฃผ๋ ๋ฐฉ๋ฒ โ **์ปค๋์ด ์๋๋ผ ์ฌ๊ธฐ๊ฐ ์๋ค.**\n *\n * `setImmediate` ๋ ๋๊ธฐ ์ค์ธ I/O ๋ค์ ์ฐจ๋ก์ ๋์์จ๋ค. ๋ง์ดํฌ๋กํ์คํฌ(`Promise.resolve()`)๋ก๋\n * ์๋ฆฌ๊ฐ ๊ฐ์ง ์๋๋ค โ ๊ทธ๋ฌ๋ฉด ์์ธก์ด ๋๋ ๋์ ๋ผ์ด๋ธ ํฑ๋ HTTP ๋ ์ฌ์ ํ ๋ฉ์ถ๋ค.\n *\n * โโ ๋ด์ค ์๊ฐ์ **๋ถํ๊ฐ ์๋๋ค** โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ถํ ๊ณ๊ธฐ๋ ใ์ด ํธ์์ด ๋ฃจํ๋ฅผ ์ผ๋ง๋ ๋ถ์ก์๋ใ๋ฅผ ์ฌ๋ ์๋ค. ์๋ณด๋ฅผ ๋ฃ์ ๋ค๋ก ๋ฒฝ์๊ณ ์๊ฐ์๋\n * ๋จ์๊ฒ ๋๊ธด ์๊ฐ์ด ์์ด๋๋ฐ, ๊ทธ๊ฒ๊น์ง ๋ถํ๋ก ์ ์ผ๋ฉด ๊ณ๊ธฐ๊ฐ ๊ฑฐ์ง๋ง์ ํ๋ค โ ํํ ์ด ๋ฌธ์ ๋ฅผ ์ง์ด๋ธ\n * ๊ทธ ๊ณ๊ธฐ๋ค. ๊ทธ๋์ ๋ด์ค ์๊ฐ์ ๋ฐ๋ก ์ธ์ด ๋นผ๊ณ ์ ๋๋ค.\n */\nfunction breather() {\n let yieldedMs = 0\n return {\n fn: () =>\n new Promise<void>(resolve => {\n const t = performance.now()\n setImmediate(() => {\n yieldedMs += performance.now() - t\n resolve()\n })\n }),\n get ms() {\n return yieldedMs\n }\n }\n}\n\n/*\n * ํธ์ ์์ธก ์ฑ๋ โ ์ํฅ query. ํธ์์ \"์์ธก(predict)\" ๋ฉด(์ค๊ณ ยง3.5, ADR-0009).\n * ์ปค๋ monteCarloForecast(ํ์ฌ์์ N fork โ ์งํ ๋ถํฌ) + ๋จ์ผ fork ์์ธก ๊ถค์ . ์๋ณธ live ๋ฌด๊ฐ์ญ(fork ๊ฒฉ๋ฆฌ).\n * metric ์ ๋๋ฉ์ธ-์ผ๋ฐ(์ค๋
์ท ํ์), scenario ๋ ๋ฏธ๋ ์๊ทน(๊ธฐ๋ณธ=๊ณ์ ์
๊ณ , ์ค ์์คํ
์ ์ธ์คํด์ค/์ค์ ํ์).\n */\nconst GTIN = 'urn:epc:idpat:sgtin:0614141.012345.*'\nconst DEFAULT_SCENARIO = {\n seed: 7,\n generators: [\n { kind: 'inbound-arrival', rate: { distribution: 'poisson', meanPerHour: 60 }, content: { skuMix: [{ gtin: GTIN, weight: 1 }], qtyPerLine: { min: 4, max: 12 } } }\n ]\n}\n/*\n * ์งํ ํ๋ `forecast-metrics.ts` ๊ฐ ์์ ํ๋ค โ ์ฌ๊ธฐ ์๋ ๊ฒ์ ์ฎ๊ฒผ๋ค(์ํ์ด ์ด ํ์ผ์ ๋ถ๋ฌ์ฌ ์ ์๋ค).\n *\n * **๋ชจ๋ฅด๋ ์งํ๋ฅผ `items` ๋ก ๊ฐ์ํ์ง ์๋๋ค.** ์์ ์๋ `METRICS[metric] ?? METRICS.items` ์๋ค.\n * ์๋์ง ํธ์์์ `peakKW` ๋ฅผ ๋ฌผ์ผ๋ฉด ์ฌ๊ณ ๊ณก์ ์ด ๊ทธ๋ ค์ง๊ณ , ์ฌ๊ณ ๊ฐ ์์ผ๋ **0 ์ด ํํํ๊ฒ** ๋์๋ค โ\n * ํ๋ฉด์ ๊ทธ๊ฒ์ ใํผํฌ๊ฐ 0ใ์ผ๋ก ์ฝ๋๋ค. ์ง์ด๋ธ ๋ต๋ณด๋ค ๋ชจ๋ฅธ๋ค๊ณ ๋งํ๋ ํธ์ด ๋ซ๋ค.\n */\nfunction metricFn(metric?: string): MetricFn | null {\n if (!metric) return FORECAST_METRICS.items\n return FORECAST_METRICS[metric] ?? null\n}\n\n/* ํ์ต๋ ๋ณด์ ์ ์ฅ(P3.2, ์ธ๋ฉ๋ชจ๋ฆฌ) โ key=domain:instance:metric:horizon โ {biasShift, halfWidth, โฆ}.\n twinLearnCalibration ์ด ๊ฐญ์์ ํ์ตํด ์ ์ฅํ๊ณ , twinForecast ๊ฐ ์์ผ๋ฉด ์์ธก์ ์์ ์ ์ฉ(๋ผ์ด๋ธ ๋ณด์ ).\n ๋ฐ๋ชจ ํธ์์ ์ฌ๋ถํ
์ ์ ๋ ๋ฆฌ์
์ด๋ผ ์ธ์
์ค์ฝํ๋ก ์ถฉ๋ถ โ DB ์์(TwinForecastScore)์ ํ์. */\nconst CALIBRATION = new Map<\n string,\n { biasShift: number; halfWidth: number; at: string; samples: number; accBefore: number | null; accAfter: number | null; basis?: ModelBasis }\n>()\nconst calKey = (d: string, i: string, m: string, h: number) => `${d}:${i}:${m}:${h}`\n\n/**\n * ์ด ํธ์์ด ๋ฐฑํ
์คํธํ ์ ์๋ ๊ตฌ๊ฐ โ [์ฒซ ์ด๋ฒคํธ, ๋ง์ง๋ง ์ด๋ฒคํธ โ H].\n * ์งํ H ๋งํผ ์์ ๋ด์ผ \"๊ทธ๋ ์์ธกํ ๊ฒ\"๊ณผ \"์ค์ ๋ก ๋ฒ์ด์ง ๊ฒ\"์ ๋ง๋ ๋ณผ ์ ์์ผ๋ฏ๋ก ๋์์ H ๋ฅผ ๋บ๋ค.\n */\nasync function gapWindow(domainId: string, instanceId: string, H: number): Promise<{ t0: number; lastVantage: number } | null> {\n /*\n * โโ **์ ๋์ ์ง๊ณ๋ก ๋ฌป๋๋ค** (2026-08-28) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์์ ์๋ `findOne({ where: { domain: { id } }, order: { eventTime } })` ๋ ๋ฒ์ด์๋ค. ๊ด๊ณ๋ฅผ ๊ฐ์ง\n * ์ํฐํฐ์์ `findOne` ์ ๋ ๋จ๊ณ ์ง์๊ฐ ๋๊ณ **์์ชฝ์ ์ํ์ด ์๋ค** โ ๊ทธ ํธ์์ ์ ๋์ ์ ๋ถ ๋ง๋ ๋ค\n * ํ ์ค์ ๊ณ ๋ฅธ๋ค. ์นํํธ๋๋ 337๋ง ํ์ด๊ณ , ๊ทธ๊ฒ์ ๋ ๋ฒ ํ๋ค.\n *\n * `MIN`/`MAX` ๋ `(domain, instance, event_time)` ์์ธ์ ์ ๋์ ์ง์ผ๋ฏ๋ก ๊ฐ๊ฐ ํ ์ค์ด๋ค.\n * ์ด ํ์ผ์ ๋ค๋ฅธ ์๋ฆฌ์ ๊ฐ์ ๊ท์จ์ด๋ค(ยง`twin-engine` ์ `tipOf`).\n */\n const repo = getRepository(TwinEvent)\n const edge = (agg: 'MIN' | 'MAX') =>\n repo\n .createQueryBuilder('e')\n .select(`${agg}(e.eventTime)`, 'at')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n .getRawOne<{ at: unknown }>()\n const [firstRow, lastRow] = await Promise.all([edge('MIN'), edge('MAX')])\n /* ๋๋ผ์ด๋ฒ๊ฐ ์ค ๊ฐ์ ์๊ฐ๋๊ฐ ์์ ์ ์๋ค โ ์ปฌ๋ผ ๋ณํ์ ์ง๋๊ฒ ํ๋ค(ยง`hydratedDate`). */\n const first = hydratedDate(repo, 'eventTime', firstRow?.at)\n const last = hydratedDate(repo, 'eventTime', lastRow?.at)\n if (!first || !last) return null\n const t0 = first.getTime()\n const lastVantage = last.getTime() - H\n return lastVantage > t0 ? { t0, lastVantage } : null\n}\n\n/**\n * ๊ฐญ point ๊ณ์ฐ(๊ณต์ฉ) โ ์ฃผ์ด์ง vantage ๊ฐ๊ฐ์์ forecast-at-T vs actual-at-T+H(๊ฒฐ์ ์ ๋ฐฑํ
์คํธ).\n *\n * **vantage ๋ ๋ฐ์์ ์ค๋ค.** ์์ ์๋ ์ด ํจ์๊ฐ ์๊ธฐ ์ ๋์ ์ฒซยท๋ง์ง๋ง ์ด๋ฒคํธ๋ก ๊ฒฉ์๋ฅผ ์ค์ค๋ก ๋ง๋ค์๋ค.\n * ๊ทธ๋ฌ๋ฉด ํธ์๋ง๋ค ๊ฒฉ์๊ฐ ๋ฌ๋ผ์ ธ, ๊ณต๋๋ฐฐ์น ํฉ์ฐ์์ `points[3]` ๋ผ๋ฆฌ ๋ํ ๋ **์๋ก ๋ค๋ฅธ ์๊ฐ์ ๊ฐ**์ด\n * ๋ํด์ก๋ค(์์ธํ ์ฌ์ฐ์ `aggregatePoints` ์ฃผ์).\n *\n * ๋ฐํ ๋ฐฐ์ด์ ๊ฒฉ์์ **๊ฐ์ ๊ธธ์ด**์ด๊ณ , ๊ทธ vantage ๋ฅผ ์ฌ์ง ๋ชปํ์ผ๋ฉด ๊ทธ ์๋ฆฌ์ `null` ์ ๋๋ค.\n * ๊ฑด๋๋ฐ๊ณ ๋ฐ์ด ๋ด์ผ๋ฉด ๋ฐฐ์ด ์ธ๋ฑ์ค๊ฐ ์๊ฐ์ถ์ด๊ธฐ๋ฅผ ๊ทธ๋ง๋๋ค.\n */\nasync function gapPoints(domainId: string, instanceId: string, m: (s: any) => number, H: number, grid: number[], scen: any): Promise<(any | null)[]> {\n const points: (any | null)[] = []\n for (const T of grid) {\n const k = await TwinEngine.buildForecastKernelAt(domainId, instanceId, new Date(T).toISOString()).catch(() => null)\n if (!k) { points.push(null); continue }\n const dist = await monteCarloForecastAsync(k, { runs: 12, horizonMs: H, scenario: scen, tickMs: forecastStepMs(H), metric: m, yieldFn: breather().fn })\n const naive = m(k.getSnapshot())\n const st = await TwinEngine.recover(domainId, instanceId, undefined, new Date(T + H).toISOString()).catch(() => null)\n if (!st) { points.push(null); continue }\n const a = m(st)\n const p50 = dist?.p50 ?? naive\n points.push({ t: T, p50, min: dist?.min ?? p50, max: dist?.max ?? p50, actual: a, error: a - p50, inBand: a >= (dist?.min ?? -Infinity) && a <= (dist?.max ?? Infinity), naiveAbsError: Math.abs(a - naive), modelAbsError: Math.abs(a - p50) })\n }\n return points\n}\n\n/**\n * ์ฌ๋ฌ ํธ์์ด **ํจ๊ป** ๋ฐฑํ
์คํธํ ์ ์๋ ๊ตฌ๊ฐ๊ณผ ๊ทธ ์์ vantage ๊ฒฉ์.\n *\n * ๊ฒน์น๋ ๊ตฌ๊ฐ์ ๊ฐ์์ ๊ตฌ๊ฐ์ ๊ต์งํฉํ ๊ฒ โ ์์์ ๊ฐ์ฅ ๋ฆ์ t0, ๋์ ๊ฐ์ฅ ์ด๋ฅธ lastVantage.\n * ํ ํธ์์ด๋ผ๋ ๊ทธ ์๊ฐ์ ์ ๋์ด ์์ผ๋ฉด ๊ณต์ฅ ์ด๋์ ๋งํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.\n * ๊ฒน์น๋ ๊ตฌ๊ฐ์ด ์์ผ๋ฉด `null` โ \"0\" ์ด ์๋๋ผ \"์ด ์ ์์\" ์ด๋ค.\n */\nfunction sharedGrid(windows: { t0: number; lastVantage: number }[], N: number): number[] | null {\n if (!windows.length || N < 2) return null\n const t0 = Math.max(...windows.map(w => w.t0))\n const lastVantage = Math.min(...windows.map(w => w.lastVantage))\n if (!(lastVantage > t0)) return null\n return Array.from({ length: N }, (_, i) => t0 + ((lastVantage - t0) * i) / (N - 1))\n}\n\n@Resolver()\n@UseMiddleware(SpeakRefusals)\nexport class TwinForecastQuery {\n @Query(returns => ScalarObject, {\n nullable: true,\n description: 'Monte-Carlo forecast of a metric over a horizon (twin prediction faculty) + a single-fork predicted trajectory. Live instance is untouched (forks are isolated).'\n })\n async twinForecast(\n @Arg('instanceId') instanceId: string,\n @Arg('metric', { nullable: true }) metric: string,\n @Arg('runs', type => Int, { nullable: true }) runs: number,\n @Arg('horizonMs', type => Int, { nullable: true }) horizonMs: number,\n @Arg('scenario', type => ScalarObject, { nullable: true }) scenario: any,\n @Arg('at', { nullable: true }) at: string,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n /* vantage(at) ๊ธฐ์ค ์์ธก โ ํ์คํ ๋ฆฌ ๋
ธ๋ธ๊ฐ ๊ณผ๊ฑฐ T ๋ฉด \"๊ทธ๋ ์์ ๋ณธ ๋ฏธ๋\"(๋ฐฑํ
์คํธ).\n at ์์ผ๋ฉด T ์์ ์ปค๋์ ์ ๋๋ก ์ฌ๊ตฌ์ฑํ๋ค(๊ทธ๊ฑด ์ฐํ๊ฐ ์๋๋ผ ์๊ฐ์ฌํ์ ๋ณธ์ง).\n ์์ผ๋ฉด **์ง๊ธ ๊ทธ ์ปค๋**์ ์ด๋ค โ sim ์ด๋ live ๋ ์ธ์คํด์ค๊ฐ ์ปค๋์ด๋ค(ํตํฉ P2). */\n const domainId = context.state.domain.id\n const k = at\n ? await TwinEngine.buildForecastKernelAt(domainId, instanceId, at)\n : TwinEngine.owns(domainId, instanceId)\n ? TwinEngine.kernel(domainId, instanceId)\n : undefined\n if (!k) return null\n\n const m = metricFn(metric)\n /* ์ด ํธ์์ด ๋ชป ์ธ๋ ์งํ โ ๋น ์์ธก์ด ์๋๋ผ ใ๊ทธ ์งํ๋ ์ฌ๊ธฐ ์๋คใ๊ณ ๋งํ๋ค. */\n if (!m) return { metric, unsupportedMetric: true, distribution: null, trajectory: [] }\n const H = horizonMs ?? 300000\n const R = runs ?? 30\n /*\n * ํฑ ํฌ๊ธฐ๋ **์งํ์ ์ด ์ ํ๋ค**(`forecast-tuning`). 1์ด ๊ณ ์ ์ด๋ ์์ 5๋ถ ์งํ์ ์ด ํ์ฐจ๋ง๋ค\n * 300ํฑ์ด์๊ณ , 30ํ์ฐจ๋ฉด 9,000ํฑยท28.5์ด์๋ค โ ์ค์ธก์ผ๋ก 5์ด ๋จ์์ ๋ต์ด ๊ฐ๋ค.\n */\n const step = forecastStepMs(H)\n const scen = scenario ?? DEFAULT_SCENARIO\n\n /*\n * ๋ถํฌ: N๊ฐ ํ๋ฅ ์ ๋ฏธ๋ ํ๋ณธ(fork ๋ง๋ค seed ๋ณ์ฃผ, ์๋ณธ ๋ณด์กด).\n *\n * **์ด๊ฒ์ด ์์ฒญ ์ฒ๋ฆฌ ์ค ๋ฉ์ธ ์ด๋ฒคํธ ๋ฃจํ์์ ๋๊ธฐ๋ก ์ํ๋๋ค.** ๊ธฐ๋ณธ๊ฐ์ผ๋ก fork 30๊ฐ ร 300ํฑ = 9,000ํฑ.\n * ๊ณ๊ธฐํ์ ๋จ๊ฒจ ๋์ง ์์ผ๋ฉด \"์ ์๋ฒ๊ฐ ๊ตณ์๋\" ๋ฅผ ๋์ค์ ์ง์ ์ ์๋ค(์ค์ ๋ก ํ ๋ฒ ๊ฒช์๋ค).\n */\n const tMc = performance.now()\n const mcBreath = breather()\n const distribution = await monteCarloForecastAsync(k, { runs: R, horizonMs: H, scenario: scen, tickMs: step, metric: m, yieldFn: mcBreath.fn })\n TwinEngine.recordLoad(domainId, instanceId, 'forecast', performance.now() - tMc - mcBreath.ms)\n TwinEngine.countForks(domainId, instanceId, R)\n\n /* ํ์ต๋ ๋ณด์ ์์ ์ ์ฉ(P3.2) โ twinLearnCalibration ์ด ์ ์ฅํ ํธํฅยท๋ฐด๋๊ฐ ์์ผ๋ฉด ์์ธก์ ํ์ค๋ก ๋ณด์ (๋ผ์ด๋ธ๊ฐ ์ค์ ๋ก ๋์์ง).\n ๊ฐญํธ๋ ๋(gapPoints)๋ raw ๋ชจ๋ธ์ ๊ทธ๋๋ก ์ธก์ (ํ์ต ์ ํธ ๋ณด์กด) โ ๋ณด์ ์ ํ์์ฉ forecast ์๋ง. */\n const stored = CALIBRATION.get(calKey(domainId, instanceId, metric ?? 'items', H))\n /*\n * **๋ฐฐ์ด ๋ชจ๋ธ์๋ง ์ ์ฉํ๋ค.** ๋ณด์ ์ \"๊ทธ๋ ๋ชจ๋ธ์ด ์ด๋งํผ ์น์ฐ์ณ ์๋ค\" ๋ฅผ ๋ฐฐ์ด ๊ฒ์ด๋ค. ์์์๊ฐ\n * ์ถ์ ๊ธฐ(์ค์ธกยท๊ฑฐ๋ฆฌ)๋ ๊ณต์ ๋ช
์ธ๊ฐ ๋ฐ๋์ด ๋ชจ๋ธ์ด ๋ฌ๋ผ์ง๋ฉด ๊ทธ ํธํฅ์ ๋ ์ด์ ์ฌ์ค์ด ์๋๊ณ , ๊ทธ๋๋ก\n * ๋ฐ์ด ์ฃผ๋ฉด ์ด์ค ๋ณด์ ์ด ๋๋ค. ๊ทธ๋์ ์ง๋ฌธ์ ๋น๊ตํ๊ณ , ๋ค๋ฅด๋ฉด ์ ์ฉํ์ง ์๋ **๊ทธ ์ฌ์ค์ ์๋ต์\n * ์ฃ๋๋ค** โ ์ค๋ฅ ์์ด ์ฌ๋ผ์ง๋ฉด ์ฌ์ฉ์๋ ํ์ต์ด ์ ์ ๋ฃ๋์ง ์ ์ ์๋ค(๋ค์ ๋ฐฐ์ฐ๋ฉด ๋๋ค).\n * ์ง๋ฌธ์ ์ ์ ์์ ๋๋ ๋น๊ตํ์ง ์๋๋ค(๋ชจ๋ฅด๋ ๊ฒ์ ๊ทผ๊ฑฐ๋ก ๋ณด์ ์ ๋์ง ์๋๋ค).\n */\n const basis = await TwinEngine.modelBasis(domainId, instanceId)\n const stale = !!stored && modelBasisChanged(stored.basis, basis)\n if (stale) {\n twinLog(\n `[twin-forecast] \"${instanceId}\": calibration not applied โ model changed since it was learned.` +\n ` learned on: ${describeModelBasis(stored!.basis)} / now: ${describeModelBasis(basis)}`\n )\n }\n /*\n * ๋ถ์์ โ ํ๋ณธ์์ ์ง์ ๋ฝ๋๋ค.\n *\n * ์ปค๋์ด ํ๋ณธ ๋ฐฐ์ด์ ๊ทธ๋๋ก ๋๋ ค์ฃผ๋ฏ๋ก(forecast.ts) ์ฌ๊ธฐ์ ์ ๋ ฌํด p05ยทp95 ๋ฅผ ๋ธ๋ค. ์ด๊ฒ์ด ์์ผ๋ฉด\n * ํ๋ฉด์ด ๋ณด์ฌ ์ค ์ ์๋ ํญ์ ๊ด์ธก **์ต์ยท์ต๋** ๋ฟ์ธ๋ฐ, ๊ทธ๊ฑด ์ ๋ขฐ๊ตฌ๊ฐ์ด ์๋๋ผ ๊ทน๋จ๊ฐ ๋ ๊ฐ๋ค.\n * \"์ด์ด ๋์ 5% ์์๋ ์ด๋งํผ\" ์ด๋ผ๊ณ ๋งํ๋ ค๋ฉด ๋ถ์์์ฌ์ผ ํ๋ค. ํ๋ณธ์ด ์ ์ผ๋ฉด(runs ๊ฐ ์์ผ๋ฉด)\n * ๋ถ์์๋ ๊ฑฐ์น ๋ค โ ๊ทธ๋์ ํ๋ณธ ์๋ฅผ ํจ๊ป ์ฃ๋๋ค(sampleCount). ์ซ์๋ง ์ฃผ๊ณ ๊ทผ๊ฑฐ๋ฅผ ๊ฐ์ถ์ง ์๋๋ค.\n */\n if (distribution) {\n const samples: number[] = Array.isArray(distribution.samples) ? distribution.samples : []\n if (samples.length) {\n const sorted = [...samples].sort((a, b) => a - b)\n const pct = (p: number) => sorted[Math.min(sorted.length - 1, Math.floor(p * sorted.length))]\n distribution.p05 = pct(0.05)\n distribution.p95 = pct(0.95)\n }\n distribution.sampleCount = samples.length\n }\n\n const cal = stored && !stale ? stored : undefined\n if (cal && distribution) {\n /*\n * `p50` ์ ์ปค๋ ๊ณ์ฝ์ ํญ์ ์๋ค(`MonteCarloResult.p50: number`). ๊ทธ๋๋ ๋ฉ์ฐ์ง ์๋๋ค โ\n * ์์ ์๋ `?? 0` ์ด์๋๋ฐ, ๋ง์ฝ ๋น๋ฉด ๋ณด์ ๋ p50 ์ด **ํธํฅ๊ฐ ๊ทธ ์์ฒด**๊ฐ ๋๊ณ minยทmax ๋\n * ๊ทธ ๋๋ ๋ก ๊ทธ๋ ค์ง๋ค. ์์ธก์ด ์๋ ์ซ์๊ฐ ์์ธก์ ์๋ฆฌ์ ์๋๋ฐ ์๋ฌด ์ ํธ๊ฐ ์๋ค.\n */\n if (typeof distribution.p50 !== 'number') throw new Error('forecast distribution has no p50 โ kernel contract broken')\n const p50c = distribution.p50 + cal.biasShift\n distribution.p50 = Math.round(p50c)\n distribution.min = Math.round(p50c - cal.halfWidth)\n distribution.max = Math.round(p50c + cal.halfWidth)\n /*\n * ๋ถ์์๋ **์ฎ๊ธฐ๊ธฐ๋ง** ํ๋ค. ๋ณด์ ์ด ๋ฐฐ์ด ๊ฒ์ \"๋ชจ๋ธ์ด ์ด๋งํผ ์น์ฐ์ณ ์๋ค\"(์์น)์ด์ง ๋ถํฌ์\n * ๋ชจ์์ด ์๋๋ค. p50 ์ฒ๋ผ ๋ฐ์ด ๋์ด์ผ p05~p95 ํญ์ด ํ๋ณธ์ด ๋งํ ๊ทธ๋๋ก ๋จ๋๋ค.\n * (minยทmax ๋ ์์์ ํ์ต ๋ฐด๋๋ก ๋์ฒด๋๋ค โ ๋ณด์ ์ด ๊ฑธ๋ฆฌ๋ฉด ๊ทธ ๋์ ๋ป์ด '๊ด์ธก ๊ทน๋จ' ์์\n * 'ํ์ต ๋ฐด๋' ๋ก ๋ฐ๋๋ค๋ ๋ป์ด๋ค. ํ๋ฉด์ด ๋์ ๊ฐ์ ๊ฒ์ผ๋ก ๊ทธ๋ฆฌ๋ฉด ์ ๋๋ค.)\n */\n if (distribution.p05 !== undefined) distribution.p05 = Math.round(distribution.p05 + cal.biasShift)\n if (distribution.p95 !== undefined) distribution.p95 = Math.round(distribution.p95 + cal.biasShift)\n if (distribution.p90 !== undefined) distribution.p90 = Math.round(distribution.p90 + cal.biasShift)\n distribution.calibrated = true\n }\n\n /*\n * ์์ธก ๊ถค์ (์์ธก์ ): ๋จ์ผ fork ๋ฅผ horizon ๊น์ง ์คํํ๋ฉฐ ์งํ ๊ธฐ๋ก. ์ด๊ฒ๋ ์ฐ๋ค.\n *\n * ์ฌ๊ธฐ๋ ์๋ฆฌ๋ฅผ ๋ด์ค๋ค โ ์ค์ธก์ผ๋ก ์ด ํ ํ์ฐจ๊ฐ 1.3์ด์๋ค(300ํฑ + ์ค๋
์ท 300๋ฒ). ๋ถํฌ๋งํผ์\n * ์๋์ง๋ง, ๋ผ์ด๋ธ ํฑ ๊ฐ๊ฒฉ(1์ด)๋ณด๋ค ๊ธธ๊ฒ ๋ถ์ก์ผ๋ฉด ๊ทธ ์ฌ์ด ํธ์๋ค์ด ํ ๋ฐ์์ฉ ๋ฐ๋ฆฐ๋ค.\n */\n const tTraj = performance.now()\n const trajBreath = breather()\n const fc = k.fork()\n fc.scenario.load({ ...scen, seed: 1 })\n fc.scenario.start()\n const trajectory: { t: number; value: number }[] = []\n for (let t = 0; t < H; t += step) {\n fc.tick(step)\n trajectory.push({ t: t + step, value: m(fc.getSnapshot()) })\n /* ํฑ๋ง๋ค ๋ด์ฃผ๋ฉด ์๋ณด ์์ฒด๊ฐ ๋น์ฉ์ด ๋๋ค โ ๋ผ์ด๋ธ ํฑ ๊ฐ๊ฒฉ๋ณด๋ค ํจ์ฌ ์งง์ ๋จ์๋ก ๋๋๋ค. */\n if (trajectory.length % 25 === 0) await trajBreath.fn()\n }\n\n TwinEngine.recordLoad(domainId, instanceId, 'forkTick', performance.now() - tTraj - trajBreath.ms)\n TwinEngine.countForks(domainId, instanceId, 1)\n\n const current = m(k.getSnapshot()) // vantage T ์ ์ค์ ๊ฐ(= naive '๊ทธ๋๋ก ์ ์ง' ์์ธก์ ๊ธฐ์ค)\n\n /* ์ค์ธก ์ค๋ฒ๋ ์ด + ์ฑ์ (P1) โ vantage ๊ฐ ๊ณผ๊ฑฐ(at)์ผ ๋๋ง: T ์ดํ ์ค์ ๋ก ์ผ์ด๋ metric ์ Tโmin(now,T+H) ๋ก ์ํ.\n ํ์ฌ ์ดํ๋ ์ค์ธก์ด ์์(๋ฏธ๋). recover(T+t) ๋ก ๊ฐ ์ํ ์ํ ์ฌ๊ตฌ์ฑํด metric ์ถ์ถ. ๋น์ฉ=์ํ ์ ๋งํผ replay. */\n const actual: { t: number; value: number }[] = []\n let scored: any = null\n if (at) {\n const T = Date.parse(at)\n const endMs = Math.min(Date.now(), T + H)\n const span = endMs - T\n if (Number.isFinite(T) && span > 0) {\n const SAMPLES = 8\n const dt = span / SAMPLES\n for (let i = 1; i <= SAMPLES; i++) {\n const st = await TwinEngine.recover(domainId, instanceId, undefined, new Date(T + i * dt).toISOString()).catch(() => null)\n if (st) actual.push({ t: i * dt, value: m(st) })\n }\n /* ์งํ์ ์ด ์ง๋ฌ์ผ๋ฉด(T+H โค now) ๊ทธ ์ง์ ์ค์ธก vs ์์ธก ์ฑ์ (๋จ์ผ vantage). p50 ๋๋น ์ค์ฐจยท๋ฐด๋ ์ ์คยทFVA(naive=ํ์ฌ๊ฐ ์ ์ง ๋๋น). */\n if (T + H <= Date.now() && actual.length) {\n const a = actual[actual.length - 1].value\n const p50 = distribution?.p50 ?? current\n scored = {\n actual: a,\n p50,\n error: a - p50, // ๋ถํธ = ํธํฅ ๋ฐฉํฅ(+ ์ค์ ๊ฐ ๋ ๋ง์)\n inBand: a >= (distribution?.min ?? -Infinity) && a <= (distribution?.max ?? Infinity),\n modelAbsError: Math.abs(a - p50),\n naiveAbsError: Math.abs(a - current) // naive = \"๊ทธ๋๋ก ์ ์ง\"(ํ์ฌ๊ฐ). FVA = naive - model\n }\n }\n }\n }\n\n /*\n * ์๋ฎฌ ๋ช
์ธ ์๊ธฐ๋ณด๊ณ ๋ฅผ ํจ๊ป ๋ธ๋ค โ **์์๋ก ๊ณ์ฐํ ์์ธก๊ณผ ํ์ฅ ๋ช
์ธ๋ก ๊ณ์ฐํ ์์ธก์ด ํ๋ฉด์์ ๊ฐ์\n * ๋ณด์ด์ง ์๊ฒ.** ์ฝ๋ยท์์น๋ง ์ฃ๊ณ ์ฌ๋์ด ์ฝ๋ ๋ฌธ์ฅ์ ํด๋ผ๊ฐ ๋ง๋ ๋ค(์ธ์ด ์ค๋ฆฝ).\n * ์ปค๋์ด ์ด API ๋ฅผ ๊ฐ์ง ์์ ๋ฒ์ ์ด๋ฉด ํค๋ฅผ ๋ง๋ค์ง ์๋๋ค(๋ชจ๋ฅด๋ ๊ฒ์ \"์ ๋ถ ๊ธฐ๋ณธ๊ฐ\" ์ด๋ผ ๋จ์ ๊ธ์ง).\n */\n /* ๋ณด๊ณ ๋ **์ค์ ๋ก ์คํํ fork** ์์ ์ฝ๋๋ค โ ๋ถ๋ชจ ์ปค๋(k)์ tick ํ์ง ์์ผ๋ฏ๋ก(์์ธก์ fork ์์\n * ์ํ๋๋ค) ๋ถ๋ชจ์์ ์ฝ์ผ๋ฉด ์จ์์ผ๋ก ์ธ์ด ์์ธก์์๋ ๋ ๋น์ด ์๋ค. ์ซ์๋ฅผ ๋ธ ์ฃผ์ฒด๊ฐ ๋ณด๊ณ ํด์ผ ํ๋ค. */\n const specCoverage = readSpecCoverage(fc) ?? readSpecCoverage(k)\n return {\n metric: metric ?? 'items', horizonMs: H, runs: R, current, distribution, trajectory, actual, scored,\n /* ์ผ๋ง๋ ์๊ฒ ๊ตด๋ ธ๋ โ ์ซ์๋ง ์ฃผ๊ณ ๊ทผ๊ฑฐ๋ฅผ ๊ฐ์ถ์ง ์๋๋ค(๊ฐ์ ๊ท์จ๋ก `specCoverage` ๋ ์ฃ๋๋ค). */\n tickMs: step,\n /*\n * **๊ฐ์ ์ด ์ด๋ป๊ฒ ๋๋** โ ๊ฑธ๋ฆฐ ๊ฐ์
ยท๊ฑฐ์ ๋ ๊ฐ์
ยท๋ฎ์ด์ด ์ ์ธ.\n *\n * ์ด๊ฒ์ ๊ฐ์ถ๋ฉด ๋ ๊ฐ์ง๊ฐ ๋ค์ด์จ ๊ฒ์ด ์์ด์ง๋ค: ๊ฑธ๋ฆฌ์ง ์์ ๊ฐ์ (ใ๊ฑธ์๋๋ฐ ์ ์ ๋ฐ๋๋ใ)๊ณผ, ๋ฎ์ด์ด\n * ์ ์ธ(์ฌ์ฉ์๊ฐ what-if ๊ฒฐ๊ณผ๋ฅผ ํธ์์ ํ์ฌ ์ํ๋ก ์ฝ๋๋ค). ์ค์ ๋ก ์คํํ fork(`fc`)์์ ์ฝ๋๋ค โ\n * ๊ฐ์ ์ ๊ฒช์ ๊ฒ์ ๊ทธ์ชฝ์ด๋ค.\n */\n ...(typeof (fc as any).interventionOutcomes === 'function'\n ? (() => {\n const outcomes = (fc as any).interventionOutcomes()\n return outcomes.length ? { interventions: outcomes } : {}\n })()\n : {}),\n ...(typeof (fc as any).declarationOverrides === 'function'\n ? (() => {\n const overrides = (fc as any).declarationOverrides()\n return overrides.length ? { overrides } : {}\n })()\n : {}),\n calibrated: !!cal,\n /* ํ์ตํด ๋์ง๋ง ๋ชจ๋ธ์ด ๋ฐ๋์ด ์ ์ฉํ์ง ์์๋ค โ ์ฌ์ฉ์๊ฐ ๋ค์ ๋ฐฐ์ธ ์ ์๊ฒ ์๋ฆฐ๋ค. */\n ...(stale ? { calibrationStale: true } : {}),\n ...(specCoverage ? { specCoverage } : {}),\n /*\n * **๊ณ๋ณด์ ๊ตฌ๋ฉ์ด ๋ช ์นธ ์๊ฒผ๋** โ ๊ฐ์ฒด๋ฅผ ์์ง ๋ชปํ ์ฑ ๋์ด๊ฐ ๊ณต์ ์.\n *\n * โโ ์ ์ด ๊ฐ์ ์์ธก ์๋ต์ ์ฃ๋ (2026-08-24) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ฏธ๋ฌ์ ์ค๋๋ ํ๋ณด๋ถ์ ๊ฐ์ง ์๋๋ค(์๋ณธ์ด ใ์ด๋ ๊ฐ์ฒด๊ฐ ์กํ ์๋ใ๋ฅผ ๋งํ์ง ์๋ ๊ฒ์ด ๊ทธ\n * ์์คํ
์ ์ ์์ด๋ค). ์ปค๋์ ๊ทธ ์๋ฆฌ์์ **๋์ง์ง ์๊ณ ๋๊ธด๋ค** โ ๋จ๊ณ๋ฅผ ๋๋ ๊ฒ์ ๊ณต์ ์\n * ์งํ์ด๊ณ ๊ฐ์ฒด ๋ฒํธ๊ฐ ํ์ ์๋ค. ๋์ ๋๊ธด ํ์๋ฅผ ์ผ๋ค.\n *\n * ๊ทธ๋ฐ๋ฐ ๊ทธ ์นด์ดํฐ๋ **fork ์์** ์๊ณ fork ๋ ๋ฒ๋ ค์ง๋ค. ์ฌ๊ธฐ์ ์ฃ์ง ์์ผ๋ฉด ์๋ฌด์๊ฒ๋ ๋ฟ์ง\n * ์๋๋ค โ ๋ฆฌ๋์๊ฐ ์ค๋ ์ธ์ด ์จ ๊ฐ์ ์ค๋
์ท์ด ๋จ์ด๋จ๋ ค ๊ทธ๊ฒ์ ์ฝ๋๋ก ์ฐ์ธ ๊ฒ์ฌ๊ฐ ์์ํ\n * ์๋ฌด ์ ํธ๋ ๋ด์ง ์์๋ ๊ฒ๊ณผ **๊ฐ์ ์ค์**๋ค. ์ธ์ด ๋๊ณ ๋ด๋ณด๋ด์ง ์์ผ๋ฉด ์ ์ผ ๊ฒ๊ณผ ๊ฐ๋ค.\n *\n * ์ ํ๋ฉด์ด ์ด๊ฒ์ ์์์ผ ํ๋: ๊ณ๋ณด๋ **ํ์ ๋ฒ์**๋ฅผ ์ ํ๋ ์ฌ์ฌ์ด๋ค. ๊ตฌ๋ฉ์ด ์๋๋ฐ ์จ์ ํ\n * ๊ฒ์ฒ๋ผ ๋ณด์ด๋ฉด ํ์๊ฐ ์๋ฆฌ์ง ์๊ณ ์ข์์ง๋ค. ์ํ์์ ๊ทธ๊ฒ์ ๋๋๋ฆด ์ ์๋ค.\n *\n * ๋ ๊ณณ์์ ์ฝ์ด **ํฐ ๊ฐ**์ ๋ธ๋ค โ ๋ถํฌ(ํ์ฐจ R๊ฐ์ ์ต๋)์ ๊ถค์ fork ๋ **๋ ๋ค ์ค์ ๋ก ์คํ๋๋ค**.\n * ํ์ชฝ๋ง ๋ณด๋ฉด ๋ค๋ฅธ ์ชฝ์ด ๊ฒช์ ๊ตฌ๋ฉ์ ์๋๋ค.\n */\n ...(() => {\n const gaps = Math.max(\n (distribution as any)?.stepsWithoutMaterial ?? 0,\n (fc as any)?.getSnapshot?.()?.stepsWithoutMaterial ?? 0\n )\n /* 0 ์ ์ฃ์ง ์๋๋ค โ ใ๊ตฌ๋ฉ์ด ์๋คใ์ ใ์ด ์ถ์ ๋ชจ๋ฅธ๋คใ๋ฅผ ํ๋ฉด์ด ๊ตฌ๋ณํ ์ ์๊ฒ. */\n return gaps > 0 ? { stepsWithoutMaterial: gaps } : {}\n })()\n }\n }\n\n /*\n * ๊ฐญ ํธ๋ ๋(P2) โ N๊ฐ ๊ณผ๊ฑฐ vantage ๊ฐ๊ฐ์์ \"๊ทธ๋ ์์ธก vs ๊ทธ ์งํ์ ์ ์ค์ \"๋ฅผ ์ฌ๊ณ์ฐ(๊ฒฐ์ ์ ๋ฐฑํ
์คํธ).\n * ์งํ์ ์ด ์ด๋ฏธ ์ง๋ vantage ๋ง([t0, tLastโH]) โ actual ํ์ . ์จ๋๋งจ๋ ์ฌ๊ณ์ฐ(๋์ /์์์ ๊ธด ๊ธฐ๊ฐ์ฉ ํ์ ์ต์ ํ).\n * ๋น์ฉ = N ร (buildForecastKernelAt replay + monteCarlo + recover replay). Nยทruns ๋ฅผ ๋ฎ๊ฒ bound. per-instance(ํด๋ผ๊ฐ co-located ํฉ์ฐ).\n */\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'Forecast-accuracy gap diagnosis (canonical, server-computed): for N past vantages recompute forecast-at-T vs actual-at-T+h (deterministic backtest), aggregate co-located instances, and return points + SPC verdict (stability/bias) + metrics (accuracy/coverage/FVA) + learned-calibration projection. Client only renders.'\n })\n async twinForecastGapTrend(\n @Arg('instanceId') instanceId: string,\n @Arg('metric', { nullable: true }) metric: string,\n @Arg('horizonMs', type => Int, { nullable: true }) horizonMs: number,\n @Arg('samples', type => Int, { nullable: true }) samples: number,\n @Arg('scenario', type => ScalarObject, { nullable: true }) scenario: any,\n @Ctx() context: ResolverContext,\n @Arg('instanceIds', type => [String], { nullable: true }) instanceIds?: string[]\n ): Promise<any> {\n const domainId = context.state.domain.id\n const m = metricFn(metric)\n const H = horizonMs ?? 300000\n if (!m) return { metric, unsupportedMetric: true, horizonMs: H, samples: 0, points: [], spc: computeSpc([]), metrics: null, learn: null }\n const N = Math.min(30, Math.max(2, samples ?? GAP_SAMPLES)) // ํ๋ณธ์ ์๋ฒ๊ฐ ๊ด์ฅ(SPC ์ ๋ขฐ ํํ ~20).\n const scen = scenario ?? DEFAULT_SCENARIO\n // ๊ณต๋๋ฐฐ์น(co-located) ์ง๊ณ๋ ์๋ฒ์์ โ ๊ณต์ฅ ๋จ์ ์ง๋จ์ด canonical. ๋ฏธ์ง์ ์ ๋จ๊ฑด.\n const ids = instanceIds?.length ? instanceIds : [instanceId]\n\n /*\n * ๊ฒฉ์๋ฅผ **๋จผ์ ํ๋** ๋ง๋ ๋ค. ํธ์๋ง๋ค ์๊ธฐ ์ ๋๋ก ๊ฒฉ์๋ฅผ ๋ง๋ค๋ฉด ๊ฐ์ ์ธ๋ฑ์ค๊ฐ ์๋ก ๋ค๋ฅธ\n * ์๊ฐ์ด ๋์ด, ํฉ์ฐ์ด ๋ค๋ฅธ ์์ ์ ๊ฐ์ ๋ํ๋ค(`aggregatePoints` ์ฃผ์ ์ฐธ์กฐ).\n *\n * ์ ๋์ด ์๊ฑฐ๋ ์งํ H ๋ฅผ ๋ด์ ๋งํผ ๊ธธ์ง ์์ ํธ์์ **๋ฐฑํ
์คํธ์ ์ฐธ์ฌํ ์ ์๋ค.** ๊ทธ๋ฐ ํธ์์\n * ๋นผ๋ ๋๊ตฌ๋ฅผ ๋บ๋์ง ๋๋ ค์ค๋ค โ ์๋ฆฌ์ง ์๊ณ ๋นผ๋ฉด ํ๋ฉด์ ๊ทธ ํธ์๊น์ง ํฌํจํ ๊ณต์ฅ ์ด๋์ผ๋ก ์ฝ๋๋ค.\n */\n const windows = await Promise.all(ids.map(async id => ({ id, w: await gapWindow(domainId, id, H) })))\n const usable = windows.filter(x => x.w)\n const excluded = windows.filter(x => !x.w).map(x => x.id)\n const grid = sharedGrid(usable.map(x => x.w!), N)\n if (!grid) {\n /* ๊ฒน์น๋ ๊ตฌ๊ฐ์ด ์๋ค โ ์ด ์ ์๋ ๊ฒ์ด์ง ์ ํ๋๊ฐ 0 ์ธ ๊ฒ์ด ์๋๋ค. */\n return { metric: metric ?? 'items', horizonMs: H, samples: N, points: [], spc: computeSpc([]), metrics: null, learn: null,\n coverage: { instances: ids.length, measured: 0, excluded, vantages: N, used: 0, dropped: 0, reason: 'no-common-window' } }\n }\n\n const per = await Promise.all(usable.map(x => gapPoints(domainId, x.id, m, H, grid, scen)))\n const { points, droppedVantages } = aggregatePoints(per as (GapPoint | null)[][])\n const metrics = points.length ? gapMetrics(points) : null\n const spc = computeSpc(points.map(p => p.error))\n const learn = metrics ? learnedCalibration(points, metrics) : null\n return { metric: metric ?? 'items', horizonMs: H, samples: N, points, spc, metrics, learn,\n /* ์ด ์ซ์๊ฐ **๋ฌด์์ผ๋ก ๊ณ์ฐ๋๋์ง**. 24์ ์ค 18์ ์ด๋ฉด ํ๋ฉด์ด ๊ทธ๋ ๊ฒ ๋งํด์ผ ํ๋ค. */\n coverage: { instances: ids.length, measured: usable.length, excluded, vantages: N, used: points.length, dropped: droppedVantages } }\n }\n\n /*\n * ํ์ต(P3.2) โ ๊ฐญ์์ ํธํฅยท๋ฐด๋๋ฅผ ํ์ตํด ์ ์ฅํ๋ฉด, ์ดํ twinForecast ๊ฐ ์์ ์ ์ฉ(๋ผ์ด๋ธ ์์ธก์ด ์ค์ ๋ก ๋ณด์ ๋จ).\n * assimilation-lite: ์์ฐจ(innovation)๋ฅผ ๋๋จน์ฌ ์ถ์ ์น๋ฅผ ํ์ค๋ก. per-instance(ํด๋ผ๊ฐ co-located ํฉ์ฐ).\n * ๋ฐํ: ํ์ต๋ ๋ณด์ + before/after ์ ํ๋(ํจ๊ณผ ์ ๋ํ). ์ ์ฅ์ ์ธ๋ฉ๋ชจ๋ฆฌ(์ธ์
) โ DB ์์์ ํ์.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Learn a forecast calibration (bias + band) from the gap trend and persist it so future forecasts apply it. Returns the calibration + before/after accuracy.' })\n async twinLearnCalibration(\n @Arg('instanceId') instanceId: string,\n @Arg('metric', { nullable: true }) metric: string,\n @Arg('horizonMs', type => Int, { nullable: true }) horizonMs: number,\n @Ctx() context: ResolverContext,\n @Arg('clear', type => Boolean, { nullable: true }) clear?: boolean\n ): Promise<any> {\n const domainId = context.state.domain.id\n if (!TwinEngine.owns(domainId, instanceId)) return { ok: false } // ํ
๋ํธ ๊ฒฉ๋ฆฌ\n const m = metricFn(metric)\n if (!m) return { ok: false, reason: 'unsupported-metric', metric }\n const H = horizonMs ?? 300000\n // ๋ณด์ ํด์ โ ์ ์ฅ๋ calibration ์ ๊ฑฐ(์ดํ ์์ธก์ raw ๋ก ๋ณต๊ท). ํ์ต์ ๋๋๋ฆฌ๋ ์ ์งํ off ์ค์์น.\n if (clear) {\n CALIBRATION.delete(calKey(domainId, instanceId, metric ?? 'items', H))\n return { ok: true, cleared: true, metric: metric ?? 'items', horizonMs: H }\n }\n // ํ๋ณธยท๊ณ์ฐ์ gap-analytics ๋ก ์ผ์ํ(gapTrend ์ง๋จ๊ณผ ๋์ผ Nยท๋์ผ ์์ โ ์นด๋ ์์์น์ ์ค์ ๋ณด์ ์ผ์น).\n /* ํ์ต์ ๋จ๊ฑด์ด๋ผ ๊ฒฉ์๋ ์ด ํธ์์ ๊ตฌ๊ฐ ํ๋๋ค. ์ ๋์ด ์งํ H ๋ฅผ ๋ด์ ๋งํผ ๊ธธ์ง ์์ผ๋ฉด ๋ฐฐ์ธ ๊ฒ์ด ์๋ค. */\n const w = await gapWindow(domainId, instanceId, H)\n const grid = w ? sharedGrid([w], GAP_SAMPLES) : null\n if (!grid) return { ok: false, reason: 'insufficient-history' }\n /* ๋ชป ์ฐ vantage ๋ `null` ๋ก ์จ๋ค โ 0 ์ผ๋ก ์ธ๋ฉด ํธํฅ ํ์ต์ด ๊ทธ๋งํผ ๋๋ ค๊ฐ๋ค. */\n const pts = (await gapPoints(domainId, instanceId, m, H, grid, DEFAULT_SCENARIO)).filter(Boolean) as GapPoint[]\n if (pts.length < 3) return { ok: false, reason: 'insufficient-history' }\n const learn = learnedCalibration(pts, gapMetrics(pts))\n /* ํ์ตํ ๋ชจ๋ธ์ ์ง๋ฌธ์ ํจ๊ป ๋จ๊ธด๋ค โ ์ดํ ๋ชจ๋ธ์ด ๋ฐ๋๋ฉด ์ด ๋ณด์ ์ ์ ์ฉ๋์ง ์๋๋ค. */\n const basis = await TwinEngine.modelBasis(domainId, instanceId)\n const cal = {\n biasShift: learn.biasShift,\n halfWidth: learn.halfWidth,\n at: '',\n samples: pts.length,\n accBefore: learn.accBefore,\n accAfter: learn.accAfter,\n ...(basis ? { basis } : {})\n }\n CALIBRATION.set(calKey(domainId, instanceId, metric ?? 'items', H), cal)\n return { ok: true, metric: metric ?? 'items', horizonMs: H, biasShift: cal.biasShift, halfWidth: cal.halfWidth, samples: pts.length, accBefore: cal.accBefore, accAfter: cal.accAfter }\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/twin-ingest-window/index.ts"],"names":[],"mappings":";;;AAAA,mEAA0D;AAC1D,+EAAqE;AAExD,QAAA,QAAQ,GAAG,CAAC,wCAAgB,CAAC,CAAA;AAC7B,QAAA,SAAS,GAAG,CAAC,mDAAqB,CAAC,CAAA;AAEhD,+EAA0E;AAAjE,yIAAA,yBAAyB,OAAA","sourcesContent":["import { TwinIngestWindow } from './twin-ingest-window.js'\nimport { TwinIngestWindowQuery } from './twin-ingest-window-query.js'\n\nexport const entities = [TwinIngestWindow]\nexport const resolvers = [TwinIngestWindowQuery]\n\nexport { installIngestWindowWriter } from './twin-ingest-window-writer.js'\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"twin-ingest-window-query.js","sourceRoot":"","sources":["../../../server/service/twin-ingest-window/twin-ingest-window-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Int, Query, Resolver } from 'type-graphql'\nimport { Between } from 'typeorm'\n\nimport { ScalarObject, getRepository } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { TwinIngestWindow } from './twin-ingest-window.js'\n\n/*\n * ์ธ์ ์คํธ ์ฐฝ **์ด๋ ฅ** โ ์ฌ๊ธฐ๋ ๋ค์๋ ์ถ์ด๋ฅผ ์ด์ด ๋ณธ๋ค.\n *\n * โโ ์ ๋ฐ๋ก ์๋ (2026-08-20) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฐฝ์ ํ๋ก ๋จ๊ธฐ๊ธฐ ์์ํ๋๋ฐ **์ฝ๋ ์ฝ๋๊ฐ ์์๋ค.** 21ํ์ด ์์ฌ ์๊ณ ์๋ฌด๋ ๋ณด์ง ์์๋ค โ ์ด\n * ํ๋ก์ ํธ๊ฐ ๊ฒฐํจ์ผ๋ก ๋ณด๋ ์ํ๋ค(ใํ๋๋ง ๋ง๋ค๊ณ ์๋ฌด๋ ์ฝ์ง ์๋๋คใ). ํ๋ฅผ ๋ง๋ ์ด์ ๊ฐ ใ๋ฉ๋ชจ๋ฆฌ\n * ์ฅ๋ถ๋ ์ฌ๊ธฐ๋์ ์ฌ๋ผ์ง๊ณ 6์๊ฐ๊น์ง์ธ๋ฐ ์ถ์ด๋ ๊ทธ๋ณด๋ค ์ค๋ ๋ด์ผ ํ๋คใ์์ผ๋, ๋ชฉ์ ์ด ๋ฏธ์์ด์๋ค.\n *\n * โโ ์ `twinIngestHealth` ์ ํฉ์น์ง ์๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ทธ ์กฐํ๋ **ํ๋ฉด์ด ์์ฃผ ๋ฌป๋๋ค**(์์ธ๋ฅผ ์ด ๋๋ง๋ค, ๋ชฉ๋ก์ ์๋ต์ ์์ฝ์ด ํจ๊ป ์จ๋ค). ๊ฑฐ๊ธฐ์ DB ์ฃผ์ฌ๋ฅผ\n * ์น์ผ๋ฉด ์ด ์ธ์
์์ ์์ค ๊ฒ๊ณผ ๊ฐ์ ์ข
๋ฅ์ ๋น์ฉ์ด ๋์์จ๋ค โ ์์ฃผ ๋ฌป๋ ์กฐํ๊ฐ ์๋ผ๋ ํ๋ฅผ ์ฝ๋ ๊ฒ.\n * ์ด๋ ฅ์ **๋ค๋ฅธ ์ง๋ฌธ**์ด๊ณ ๋ ์์ฃผ ๋ฌป๋๋ค: ใ๋ ๋ค๊น์ง ๋ณด์ฌ ๋ฌ๋ผใ.\n *\n * โโ ์ด์ด ๋ถ์ด๊ธฐ๋ ์๋ฒ๊ฐ ํ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ํ์ ๋ฉ๋ชจ๋ฆฌ๋ ๊ฒน์น๋ค(ํ๋ก์ธ์ค๊ฐ ์ด์ ์๋ ๋์ ๋ซํ ์ฐฝ์ ๋ ๋ค์ ์๋ค). ๊ฒน์นจ์ ํ๋ฉด์ด ์ ๋ฆฌํ๊ฒ ๋๋ฉด\n * ํ๋ฉด๋ง๋ค ๊ท์น์ด ๊ฐ๋ฆฌ๊ณ , ๊ฐ์ ๊ตฌ๊ฐ์ด ๋ ๋ฒ ๊ทธ๋ ค์ง๊ฑฐ๋ ์ฌ๋ผ์ง๋ค. ๊ทธ๋์ ์ฌ๊ธฐ์ ํ ๋ฒ๋ก ์ด์ด ๋ถ์ด๊ณ \n * **์ด๋์๋ถํฐ ๋ฉ๋ชจ๋ฆฌ์ธ์ง**(`liveFrom`)๋ฅผ ํจ๊ป ๋ธ๋ค โ ํ๋ฉด์ด ๊ทผ๊ฑฐ๋ฅผ ๋งํ ์ ์๊ฒ.\n */\n\n/**\n * ํ ๋ฒ์ ๋๋ ค์ฃผ๋ ์ฐฝ ์ ์ํ โ 144์ฐฝ ร 10๋ถ = 24์๊ฐ.\n *\n * ์ํ์ด ํ์ํ ์ด์ ๋ ์ด ํ๊ฐ **์๋๋ค**๋ ๊ฒ์ด๋ค(ํธ์ 1,000๊ฐ์ ํ๋ฃจ 14.4๋ง ํ). ์ํ์์ ๋ฐ๋ ค๋\n * ์๋ **์ธ์ด์ ๋ธ๋ค** โ ์๋ฆฌ์ง ์๊ณ ์๋ฅด๋ฉด ํ๋ฉด์ด ใ๊ทธ ์์๋ ์๋ฌด ์ผ๋ ์์๋คใ๋ก ์ฝ๋๋ค.\n */\nexport const HISTORY_WINDOW_LIMIT = 144\n\n/** ๋ฌผ์ ์ ์๋ ๊ธฐ๊ฐ์ ์ํ(์๊ฐ). ๋๊ฒจ๋ ์ฌ๊ธฐ์ ์๋ฅด๊ณ , ์๋ฅธ ์ฌ์ค์ ๋ธ๋ค. */\nexport const HISTORY_HOURS_MAX = 168\n\n@Resolver()\nexport class TwinIngestWindowQuery {\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'Ingest windows for one twin over a past span, stitched from two sources so the trend survives a restart: closed windows persisted in the table (older) and the in-memory ledger (recent, roughly the last 6 hours). Overlap is resolved here rather than on screen โ a window present in both is reported once, from memory, and `liveFrom` says where memory takes over so a screen can state its basis. Each window carries offered / accepted / rejected / undelivered plus the journal rows written and the write round-trips behind them; `acceptedRatio` is null when nothing was offered, because an empty window is not a perfect one. Deliberately separate from twinIngestHealth: that query is polled whenever a screen opens, and making it scan a growing table would reintroduce the cost this codebase just removed elsewhere. Counts that could not be returned are reported rather than dropped โ `storedDropped` when the row cap was hit and `hoursClamped` when the requested span was longer than allowed. Null if the instance is not in the current domain.'\n })\n async twinIngestHistory(\n @Arg('instanceId') instanceId: string,\n @Arg('hours', type => Int, { nullable: true, description: 'How far back to read, in hours. Defaults to 24 and is clamped to 168.' })\n hours: number | undefined,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n /* ํ
๋ํธ ๊ฒฉ๋ฆฌ โ ๋ฉ์ถ ํธ์์ ์ด๋ ฅ๋ ๋ณผ ์ ์์ด์ผ ํ๋ค(๊ทธ๋๊ฐ ๊ฐ์ฅ ๋ณด๊ณ ์ถ์ ๋๋ค). */\n if (!TwinEngine.owns(domainId, instanceId) && !(await TwinEngine.ownsRegistered(domainId, instanceId))) return null\n\n const asked = Number.isFinite(Number(hours)) && Number(hours) > 0 ? Math.floor(Number(hours)) : 24\n const span = Math.min(asked, HISTORY_HOURS_MAX)\n const now = Date.now()\n const fromMs = now - span * 3_600_000\n\n /*\n * ํ์์ ๊ทธ ๊ตฌ๊ฐ์ ๋ซํ ์ฐฝ์ ์ฝ๋๋ค. **์ํ์ ๋๋ค** โ ์๋ผ๋ ํ์ด๊ณ , ์ด ์กฐํ๊ฐ ํ๋ฉด์์ ์ด๋ฆฐ๋ค.\n * ์ต์ ์ชฝ์ด ์ค์ํ๋ฏ๋ก ๋ด๋ ค์ ์ ๋ ฌํด ๊ฐ์ ธ์ค๊ณ , ๋ผ ๋ ๋ค์ ์ฌ๋ฆฐ๋ค.\n */\n const repo = getRepository(TwinIngestWindow)\n const where = {\n domain: { id: domainId } as any,\n instanceId,\n closedAt: Between(new Date(fromMs), new Date(now))\n }\n const rows = await repo.find({ where, order: { closedAt: 'DESC' }, take: HISTORY_WINDOW_LIMIT })\n\n /*\n * ์ํ์ ๋ฟ์์ผ๋ฉด **๋ช ๊ฐ๊ฐ ๋ฐ๋ ธ๋์ง ์ผ๋ค.** ใ๋ ์์ใ๋ง ๋งํ๋ฉด ํ๋ฉด์ด ๊ทธ ์์ ์ง์ํ๊ฒ ๋๋ค.\n * ์ํ์ ๋ฟ์ง ์์์ผ๋ฉด ์
ํ์๊ฐ ์๋ค(์๋ณต์ ์๋๋ค).\n */\n const storedDropped = rows.length === HISTORY_WINDOW_LIMIT ? Math.max(0, (await repo.count({ where })) - rows.length) : 0\n\n const stored = rows.reverse().map(r => ({\n from: r.openedAt?.toISOString?.() ?? new Date(r.openedAt as any).toISOString(),\n to: r.closedAt?.toISOString?.() ?? new Date(r.closedAt as any).toISOString(),\n offered: r.offered,\n /* ํต๊ณผ๋ **ํธ์์ ๋ฟ์** ๊ฒ๋ง. ํ์ ๊ฐ์ ๊ทธ๋๋ก ์ด๋ค โ ์ฝ๋ ์ชฝ์์ ๋ค์ ๋๋๋ฉด ๋ฐ์ฌ๋ฆผ์ด ๊ฐ๋ฆฐ๋ค. */\n accepted: r.offered - r.rejected - (r.undelivered ?? 0),\n rejected: r.rejected,\n undelivered: r.undelivered ?? 0,\n acceptedRatio: typeof r.acceptedRatio === 'number' ? r.acceptedRatio : null,\n rows: r.journaledRows ?? 0,\n flushes: r.journalFlushes ?? 0,\n source: 'stored' as const\n }))\n\n /* ๋ฉ๋ชจ๋ฆฌ ์ฅ๋ถ์ ๋ซํ ์ฐฝ โ ์ด์ชฝ์ด ์ต์ ์ด๊ณ , ๊ฒน์น๋ ๊ตฌ๊ฐ์ ์ด์ชฝ์ ์ด๋ค(๊ฐ์ ์ฌ์ค์ ์๋ณธ์ด๋ค). */\n const live = (TwinEngine.ingestHealthOf(domainId, instanceId).trend ?? []).map((w: any) => ({\n ...w,\n source: 'live' as const\n }))\n\n /*\n * ๊ฒน์นจ ์ ๋ฆฌ โ ์ฐฝ์ **์ฌ๋ ์๊ฐ**์ด ํค๋ค. ๊ฐ์ ์ฐฝ์ด ํ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ ๋ค ์์ผ๋ฉด ํ๋๋ง ๋ธ๋ค.\n * ์๊ฐ ๋ฌธ์์ด์ ๊ทธ๋๋ก ํค๋ก ์ฐ์ง ์๋๋ค: ๋๋ผ์ด๋ฒ๊ฐ ๋ฐ๋ฆฌ์ด๋ฅผ ์๋ฅด๊ฑฐ๋ ํ์์ ๋ฐ๊ฟ ์ ์์ด\n * ๊ฐ์ ์ฐฝ์ด ๋ค๋ฅธ ํค๊ฐ ๋๋ค. epoch ๋ก ๊ฒฌ์ค๋ค.\n */\n const liveStarts = new Set(live.map((w: any) => Date.parse(w.from)))\n const windows = [...stored.filter(w => !liveStarts.has(Date.parse(w.from))), ...live]\n\n return {\n windows,\n hours: span,\n /* ๋ฌผ์ ๊ฒ๋ณด๋ค ์งง๊ฒ ์๋ ธ์ผ๋ฉด ๋ฐํ๋ค. */\n ...(span < asked ? { hoursClamped: asked } : {}),\n from: new Date(fromMs).toISOString(),\n to: new Date(now).toISOString(),\n /** ํ์์ ์ฝ์ ์ฐฝ ์ ยท ์ํ์์ ๋ฐ๋ ค๋ ์. */\n storedCount: stored.length,\n storedDropped,\n /**\n * ์ด๋์๋ถํฐ ๋ฉ๋ชจ๋ฆฌ์ธ๊ฐ โ ํ๋ฉด์ด ๊ทผ๊ฑฐ๋ฅผ ๋งํ ์ ์๊ฒ. ๋ฉ๋ชจ๋ฆฌ์ ๋ซํ ์ฐฝ์ด ์์ผ๋ฉด `null` ์ด๋ค\n * (์ฌ๊ธฐ๋ ์งํ๊ฐ ๊ทธ๋ ๋ค: ๊ทธ๋ ๋ณด์ด๋ ๊ฒ์ ์ ๋ถ ํ์์ ์จ ๊ฒ์ด๋ค).\n */\n liveFrom: live.length ? live[0].from : null,\n liveCount: live.length\n }\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"twin-ingest-window-writer.js","sourceRoot":"","sources":["../../../server/service/twin-ingest-window/twin-ingest-window-writer.ts"],"names":[],"mappings":";;AAoBA,8DAiCC;AArDD,gDAA8C;AAC9C,iDAAqD;AAErD,oDAAkD;AAClD,mEAA0D;AAE1D;;;;;;;;;;;;;GAaG;AACH,SAAgB,yBAAyB;IACvC,qBAAU,CAAC,oBAAoB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,wCAAgB,CAAC,CAAA;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAA;QAC9B,IAAI;aACD,IAAI,CACH,IAAI,CAAC,MAAM,CAAC;YACV,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,QAAQ,EAAS;YAClC,UAAU,EAAE,EAAE,CAAC,UAAU;YACzB,QAAQ,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YAClC,QAAQ,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YAChC,OAAO;YACP,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,kDAAkD;YAClD,aAAa,EAAE,MAAM,CAAC,IAAI;YAC1B,cAAc,EAAE,MAAM,CAAC,OAAO;YAC9B;;;eAGG;YACH,GAAG,CAAC,OAAO,GAAG,CAAC;gBACb,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,EAAE;gBACvF,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CACH;aACA,KAAK,CAAC,GAAG,CAAC,EAAE,CACX,IAAA,iBAAQ,EACN,yBAAyB,EAAE,CAAC,UAAU,sDAAsD,EAC5F,GAAG,EAAE,OAAO,IAAI,GAAG,CACpB,CACF,CAAA;IACL,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAA","sourcesContent":["import { twinWarn } from '../../engine/log.js'\nimport { getRepository } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { TwinIngestWindow } from './twin-ingest-window.js'\n\n/*\n * ๋ซํ ์ฐฝ์ ํ๋ก ์ฎ๊ธด๋ค โ **์์์ด ๋ถ๋ ์ ์ผํ ์๋ฆฌ.**\n *\n * ์ปค๋ ์ธต(`engine/ingest-health.ts`)์ ์ ์ฅ ๊ณ์ธต์ ๋ชจ๋ฅธ๋ค. ์ฐฝ์ด ๋ซํ ๋ ๋ถ๋ฅผ ๊ณณ์ ์์ง์ด ๋ฌธ์ผ๋ก ์ด์ด\n * ๋์๊ณ (`onIngestWindowClosed`), ์ด ํ์ผ์ด ๋ถํ
์์ ํ ๋ฒ ๋ฑ๋กํ๋ค. ๊ทธ๋์ ๊ธฐ๋ก ๊ฒฝ๋ก๊ฐ ๊ฐ๋ฆฌ์ง ์๋๋ค.\n *\n * โโ ์คํจ๋ฅผ ์ผํค์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฐ๊ธฐ๊ฐ ํฐ์ ธ๋ ๋ฉ๋ชจ๋ฆฌ ์ฅ๋ถ๋ ๊ณ์ ๊ตด๋ฌ๊ฐ๋ค(`rollIngestWindow` ๊ฐ ํ
์ ๊ฐ์ผ๋ค). ๋ค๋ง **์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง๋\n * ์๋๋ค** โ ์คํจ๋ฅผ ๋ก๊ทธ๋ก ๋จ๊ธด๋ค. ๊ทธ๋ฌ์ง ์์ผ๋ฉด ์ถ์ด ํ์ ๊ตฌ๋ฉ์ด ์๊ธด ์ด์ ๋ฅผ ๋์ค์ ์ ์ ์๋ค.\n *\n * โโ ์ await ํ์ง ์๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ
์ ์ธ์ ์คํธ ๊ฒฝ๋ก์์ ๋ถ๋ฆฐ๋ค(๋ผ์ด๋ธ ํผ๋์ ์ฝ๋ฐฑ ์). ์ฌ๊ธฐ์ DB ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด **์ ์
์ด DB ์๋์\n * ๋ฌถ์ธ๋ค** โ ์ด ๊ธฐ๋ฅ์ด ๋ง์ผ๋ ค๋ ๋ถํ๊ฐ ๊ทธ ๋ชจ์์ผ๋ก ๋์์จ๋ค. ๊ทธ๋์ ๋์ ๋ณด๋ด๊ณ ๊ฒฐ๊ณผ๋ง ๋ก๊ทธ๋ก ๋ฐ๋๋ค.\n */\nexport function installIngestWindowWriter(): void {\n TwinEngine.onIngestWindowClosed((at, closed) => {\n const repo = getRepository(TwinIngestWindow)\n const offered = closed.offered\n repo\n .save(\n repo.create({\n domain: { id: at.domainId } as any,\n instanceId: at.instanceId,\n openedAt: new Date(closed.startMs),\n closedAt: new Date(closed.endMs),\n offered,\n rejected: closed.rejected,\n undelivered: closed.undelivered,\n /* ์ ํ ๊ฒ๋ ๊ฐ์ ํ์ โ ์ฐฝ์ด ์ ์
์์ด ๋ซํ์ด๋(์๋ฎฌ) ์ด ๋ ์๋ ์ฌ์ค์ด๋ค. */\n journaledRows: closed.rows,\n journalFlushes: closed.flushes,\n /*\n * ์ ์๊ฐ 0 ์ด๋ฉด ๋น์ ๋๋ค โ 1 ๋ก ์ฑ์ฐ๋ฉด ใ์ ๋ถ ํต๊ณผใ๋ก ์ฝํ๋ค.\n * ํต๊ณผ๋ **ํธ์์ ๋ฟ์** ๊ฒ๋ง์ด๋ค: ๋ฒ๋ ค์ง ๊ฒ์ ๋นผ์ง ์์ผ๋ฉด ๋ฉ์ถ ํธ์์ ์ฐฝ์ด 100% ๋ก ๋จ๋๋ค.\n */\n ...(offered > 0\n ? { acceptedRatio: round4((offered - closed.rejected - closed.undelivered) / offered) }\n : {})\n })\n )\n .catch(err =>\n twinWarn(\n `[twin-ingest-window] \"${at.instanceId}\" window not persisted (trend will have a gap here):`,\n err?.message ?? err\n )\n )\n })\n}\n\n/** 0.999 ๊ฐ 1 ๋ก ๋ฐ์ฌ๋ฆผ๋๋ฉด ใ์ ๋ถ ํต๊ณผใ๋ก ์ฝํ๋ค โ ์๋ฆฟ์๋ฅผ ๋๋ํ ์ค๋ค(๋ฉ๋ชจ๋ฆฌ ์ฅ๋ถ์ ๊ฐ์ ๊ท์น). */\nconst round4 = (v: number) => Math.round(v * 10000) / 10000\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"twin-ingest-window.js","sourceRoot":"","sources":["../../../server/service/twin-ingest-window/twin-ingest-window.ts"],"names":[],"mappings":"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","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'\nimport { ObjectType, Field, ID, Int, Float } from 'type-graphql'\n\nimport { Domain } from '@things-factory/shell'\n\n/*\n * ์ธ์ ์คํธ ์ฐฝ ํ๋ โ **๋๊ธฐํ ์ถ์ด๋ฅผ ์ฌ๊ธฐ๋ ๋ค์๋ ์ด์ด ๋ณด๊ธฐ ์ํ ํ.**\n *\n * โโ ์ ์ฐฝ๋ง๋ค์ด๊ณ ๊ฑด๋ง๋ค๊ฐ ์๋๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ฑฐ๋ถ๋ง๋ค ํ์ ์ฐ๋ฉด ๋ผ์ด๋ธ ๊ณ์ธก ๊ท๋ชจ์์ ์ด๋น 1๋ง ํ์ด๊ณ , ๊ทธ ๋ถํ๊ฐ ์ด๋ฒคํธ ๋ฃจํ๋ก ๋์์จ๋ค. ์ฐฝ๋ง๋ค๋ฉด\n * ํธ์ 1,000๊ฐ์ ํ๋ฃจ 14.4๋ง ํ(์ฝ 14MB)์ด๋ค. ๊ทธ๋์ **๋ซํ ์ฐฝ ํ๋๊ฐ ์์์ ๋จ์**๋ค.\n *\n * ๊ฑด๋ง๋ค ๋จ๊ธฐ๋ ์๋ฆฌ๋ ์ด๋ฏธ ๋ฐ๋ก ์๋ค: ์๋๋ฆฌ์ค ๊ฒฝ๋ก๊ฐ `PayloadLog` ๋ก dead-letter ๋ฅผ ๋จ๊ธด๋ค(๋ฐฐ์น์ฑ\n * ์ ์
์ด๋ผ ๊ฑด์๊ฐ ๊ฐ๋น๋๋ค). ์ด ํ๋ ๊ทธ๊ฒ์ ๋์ ํ์ง ์๊ณ **์ถ์ด**๋ฅผ ๋ตํ๋ค.\n *\n * โโ ์ ์ฌ์ ยทํ๋ณธ์ ์ฌ๊ธฐ ์๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฌ์ ๋ฌธ๊ตฌ๋ ๊ธธ๊ณ ํ๋ณธ์๋ **๊ณ ๊ฐ์ ๋ ์ฝ๋ ์๋ฌธ**์ด ๋ค์ด ์๋ค. ๊ทธ๊ฒ์ ์ฐฝ๋ง๋ค ์์ํ๋ฉด ํ๊ฐ ์ปค์ง๊ณ \n * ๊ณ ๊ฐ ๋ฐ์ดํฐ๊ฐ ์ค๋ ๋จ๋๋ค. ์ฌ์ ์ ํ๋ณธ์ ๋ฉ๋ชจ๋ฆฌ ์ฅ๋ถ๊ฐ ๋ตํ๊ณ (์ต๊ทผ 6์๊ฐ), ์ด ํ๋ ์ซ์๋ง ๋ ๋ค.\n *\n * โโ ๊ณ ์น์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ซํ ์ฐฝ์ ์ง๋๊ฐ ์ฌ์ค์ด๋ค. ๊ทธ๋์ `updatedAt`ยท`deletedAt` ์ ๋์ง ์๋๋ค(์ ๋๊ณผ ๊ฐ์ ๊ท์จ).\n */\n@Entity()\n@Index('ix_twin_ingest_window_0', (e: TwinIngestWindow) => [e.domain, e.instanceId, e.closedAt], { unique: false })\n@ObjectType({\n description:\n 'One closed ingest window for a twin: how many records were offered, accepted and rejected between two times. Written when a window closes (about every 10 minutes per twin) so the sync trend survives a restart and reaches further back than the in-memory ledger. Reasons and rejected-record samples are deliberately not stored here โ they live in the in-memory ledger, which covers roughly the last 6 hours.'\n})\nexport class TwinIngestWindow {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the window record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })\n domain?: Domain\n\n @RelationId((e: TwinIngestWindow) => e.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Twin runtime instance this window belongs to.' })\n instanceId: string\n\n @Column()\n @Field({ description: 'When the window opened.' })\n openedAt: Date\n\n @Column()\n @Field({ description: 'When the window closed. Windows close on the next ingest after the window length elapses, so a feed that stops leaves its last window open and unwritten.' })\n closedAt: Date\n\n @Column({ type: 'int' })\n @Field(type => Int, { description: 'Records offered in this window, whether or not they were accepted.' })\n offered: number\n\n @Column({ type: 'int' })\n @Field(type => Int, { description: 'Records the kernel refused in this window because they did not map โ the fix is in the mapping.' })\n rejected: number\n\n /*\n * ๊ฑฐ๋ถ์ ๋ฐ๋ก ์ผ๋ค โ **์ฒ๋ฐฉ์ด ๋ค๋ฅด๋ค.**\n *\n * ํธ์์ด ๋ผ์ด๋ธ๋ก ๋์ง ์์ผ๋ฉด ์ปค๋์ด ๋ ์ฝ๋๋ฅผ ๋ฒ๋ฆฐ๋ค. ๊ทธ๊ฒ์ ๊ฑฐ๋ถ์ ํฉ์น๋ฉด ใ๋งคํ์ ๊ณ ์ณ๋ผใ๋ก ์ฝํ๊ณ ,\n * ํต๊ณผ์ ํฉ์น๋ฉด ๋ฉ์ถ ํธ์์ด 100% ๋ก ๋ณด์ธ๋ค(์ค์ ๋ก ๊ทธ๋ ๊ฒ ๋ด๋ค). ๊ทธ๋์ ์ 3์ ์๋ก ๋จ๊ธด๋ค.\n */\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, {\n description:\n 'Records that mapped fine but never reached the twin, because the twin was not running live while the feed kept delivering. Distinct from rejected: the fix here is to start the twin or disconnect the feed, not to change the mapping. Offered minus rejected minus undelivered is what actually reached the twin.'\n })\n undelivered: number\n\n /*\n * ํต๊ณผ์จ์ **ํจ๊ป ์ ๋๋ค.** ์ฝ๋ ์ชฝ์์ ๋๋๊ฒ ํ๋ฉด ์๋น์ฒ๋ง๋ค ๋ฐ์ฌ๋ฆผ์ด ๊ฐ๋ฆฌ๊ณ (0.999 ๋ฅผ 1 ๋ก ์ฐ๋\n * ๊ณณ์ด ์๊ธด๋ค), ์ ์๊ฐ 0 ์ธ ์ฐฝ์์ 0์ผ๋ก ๋๋๋ ์ค์๊ฐ ๊ฐ์ ์๊ธด๋ค. ์ ์๊ฐ 0 ์ด๋ฉด **๋น์ด ๋๋ค** โ\n * 1 ๋ก ์ฑ์ฐ๋ฉด ใ์ ๋ถ ํต๊ณผใ๋ก ์ฝํ๋ค.\n */\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, {\n nullable: true,\n description:\n 'Share of offered records that reached the twin (0โ1), rounded to four places. Null when nothing was offered in this window โ an empty window is not a perfect one, and writing 1 there would read as \"everything passed\".'\n })\n acceptedRatio?: number\n\n /*\n * โโ ์ ํ ๊ฒ๋ ๊ฐ์ ์ฐฝ์ ๋ ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ์
๊ณผ **๋ค๋ฅธ ์ถ**์ด๋ค. ์๋ฎฌ ํธ์์ ๋ฐ๋ ๊ฒ ์์ด ์๊ธฐ๊ฐ ๋ธ ์ฌ์ค์ ์ ์ผ๋ฏ๋ก `offered` ๊ฐ 0 ์ด๊ณ \n * `journaledRows` ๋ 0 ์ด ์๋๋ค. ์ด ์นธ์ด ์์ผ๋ฉด ๋๋ ํธ์ ๋๋ถ๋ถ์ด ์๋ฎฌ์ธ ์๋ฒ์ ํ๋์ด ์ด๋ ์ถ์ด์๋\n * ๋จ์ง ์๋๋ค(๊ณ๊ธฐ๋ ์ง๊ธ๋ง ๋ตํ๊ณ ์ฌ๊ธฐ๋์ 0 ์ผ๋ก ๋์๊ฐ๋ค).\n *\n * ๋ ์๋ฅผ ๋ฐ๋ก ์ธ๋ ์ด์ : 2026-08-20 ์ ๊ณ ์น ๊ฒ์ด **ํ๋น ์๋ณต**์ด๋ค(๋ธํ๋ง๋ค ํ ๋ฒ โ ์ฐฝ๋น ํ ๋ฒ).\n * ํ๋ง ์ธ๋ฉด ๊ทธ ๊ฐ์ ๋, ๋๋์๊ฐ๋ ๊ฒ๋ ๋ณด์ด์ง ์๋๋ค.\n */\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, {\n description:\n 'Journal rows written for this twin during this window. This is a different axis from ingest: a twin driven by a simulator source receives nothing (offered = 0) yet writes what it produces, so without this column its activity appears in no trend at all.'\n })\n journaledRows: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, {\n description:\n 'Number of journal write round-trips (flushes) behind those rows. Counted separately from the rows themselves so that a regression back to per-delta writes โ the defect fixed on 2026-08-20, where each kernel delta cost one insert โ is visible as rows-per-flush falling back towards 1.'\n })\n journalFlushes: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When this record was written.' })\n createdAt?: Date\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/twin-instance/index.ts"],"names":[],"mappings":";;;AAAA,yDAAiD;AAEpC,QAAA,QAAQ,GAAG,CAAC,+BAAY,CAAC,CAAA","sourcesContent":["import { TwinInstance } from './twin-instance.js'\n\nexport const entities = [TwinInstance]\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"twin-instance.js","sourceRoot":"","sources":["../../../server/service/twin-instance/twin-instance.ts"],"names":[],"mappings":"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","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'\nimport { ObjectType, Field, ID } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { modelColumnTransformer } from '../../engine/model-vocabulary.js'\n\n/*\n * TwinInstance โ ํธ์ ์ธ์คํด์ค ๋ ์ง์คํธ๋ฆฌ(์ฌ๋ถํ
๋ณต๊ตฌ์ ์ต์ปค).\n * ๋ณต๊ตฌ(DBโreplay)๋ model(๋ง์คํฐ ์ฒญ์ฌ์ง)๊ฐ ์์ด์ผ ์ด๋ฒคํธ๋ฅผ ์ํ๋ก ๋ค์ ๊ณ์ฐํ ์ ์๋ค โ modelยทkind ๋ฅผ ์์.\n * ์ด๋ฒคํธ(TwinEvent)์ ๋ฌ๋ฆฌ ๊ฐ๋ณ(status ๊ฐฑ์ ) โ ์ธ์คํด์ค์ \"ํ์ฌ ๋ฑ๋ก ์ํ\".\n * model ๋ simple-json(๋ฉํฐDB ์ด์ โ postgres/mysql/sqlite/mssql/oracle ๊ณตํต).\n * (CLAUDE.md: ๋ชจ๋ @ObjectType/@Field ๋ ์๋ฌธ description ํ์.)\n */\n@Entity()\n@Index('ix_twin_instance_0', (e: TwinInstance) => [e.domain, e.instanceId], { unique: true })\n@Index('ix_twin_instance_1', (e: TwinInstance) => [e.domain, e.spaceId]) // ๊ณต๊ฐโ์ธ์คํด์ค 1๊ธ ์ง์(๊ณต๊ฐ ์ค์ฌ ์กด์ฌ๋ก )\n@ObjectType({ description: 'Registry of a hosted twin runtime instance โ anchors reboot recovery (model + kind).' })\nexport class TwinInstance {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the registry record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })\n domain?: Domain\n\n @RelationId((e: TwinInstance) => e.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Twin runtime instance id (unique within a domain).' })\n instanceId: string\n\n /**\n * **์ฌ๋์ด ๋ถ๋ฅด๋ ์ด๋ฆ** โ ์
๋ฌดํค(`instanceId`)์ ๋๋ํ ๋๋ ํ์๋ช
(ํ๋ ์์ํฌ ์ํฐํฐ ๊ท์ฝ).\n *\n * โโ ์ ์
๋ฌดํค์ ์ด๋ฆ์ ๋๋ ๋๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * `instanceId` ๋ URLยท์ ๋ยท๊ตฌ๋
์ด ์ ๋ถ ์ฐ๋ **๊ณ์ฝ**์ด๋ผ ๋ฐ๊ฟ ์ ์๋ค. ๋ฐ๋๋ก ์ด๋ฆ์ ๋ฐ๋๊ณ ,\n * ์ค๋ณต๋๊ณ (์ฌ์ดํธ ๋์ \"๋์ฅ\" ์ด ์๋ ๊ฒ์ด ์ ์), ์ธ์ด๋ง๋ค ๋ค๋ฅด๋ค. ๋์ ํ ์ปฌ๋ผ์ ๋ด์ผ๋ฉด ๊ฐ๋ช
์ด\n * ๊ณง ๋ค๋ฅธ ํธ์์ด ๋๊ณ ์ฌ๋๊ธฐ๊ฐ ๋๊ธด๋ค โ ๊ทธ๋์ ๋๋๋ค(์ด ์ ์ฅ์์์ ์๋ณ์๊ฐ ๋ฐ์์ ์ค๋ ๊ฒ์\n * ์ ๋ถ ์ด ๊ท์ฝ์ ์ด๋ค: `spaceId`ยท`locationId`ยท`equipmentId`ยท`operationKey`).\n *\n * ๋๋ด์ผ๋ฉด **์ด๋ฆ์ ๋ฐ๋์ ํจ๊ป ๋ฌ์ผ ํ๋ค.** ์ด ์๋ฆฌ๊ฐ ์๋ ๋์ ์ฌ์ดํธ ์ด๋ฆ์ model ์์๋ง ์์ด์\n * ๋ชฉ๋ก์ด `crew-two` ๋ง ๋ณด์๋ค โ ๋๋๊ธฐ๋ง ํ๊ณ ์ ๋ฐ์ ๋นผ๋จน์ผ๋ฉด ํ๋ฉด์๋ id ๋ง ๋จ๋๋ค.\n *\n * ์๋ณธ์ด ์ด๋ฆ์ ๋งํ์ง ์์ผ๋ฉด ๋น์ด๋ค(id ๋ฅผ ๋ฒ ๋ผ์ง ์๋๋ค).\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Human name of this twin (the site name from its master). Empty when the source does not name it โ never copied from instanceId.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Longer description when the source provides one.' })\n description?: string\n\n /* ์ด๋ ๋๋ฉ์ธ ์ปค๋์ด ์ด ํธ์์ ์ด์ํ๋๊ฐ. ์ปค๋ ์๋ ํธ์์ ์์ผ๋ฏ๋ก ๋น์ด ์์ ์ ์๋ค\n (`TwinEngine.start`ยท`register` ๋ชจ๋ ํ์ ์ธ์๋ก ๋ฐ๋๋ค). */\n @Column()\n @Field({ description: 'Domain kernel kind: wms | yms | mes.' })\n kind: string\n\n /*\n * **์ฌ๊ธฐ๋ ์ ์ฑ
** โ ์ด ํธ์์ ๋ค์ ์ธ์์ง ๋ ์๊ธฐ ๊ณผ๊ฑฐ๋ฅผ ์ด๋ป๊ฒ ๋ํ๋(ADR-0029 ยง2).\n *\n * 'resync' = ์ธ๋ถ ์ค๋ฌผ์์ ๋ค์ ์ฝ๋๋ค(์๋ณธ์ด ์ง์ค์ด๋ฏ๋ก ์ฐ๋ฆฌ ๊ณผ๊ฑฐ๋ฅผ ์ด์ด ๋ถ์ด์ง ์๋๋ค โ startLive).\n * 'resume' = ์ ๋์ ์ด์ด ์ธ์ด๋ค(์ด ํธ์์ด ๋ณ์ ํ์๋ผ์ธ์ด ๊ณง ์ฌ์ค์ด๋ค).\n * 'reset' = ์ ๋์ ๋น์ฐ๊ณ ์จ์๋ถํฐ ๋ค์ ๋๋ฆฐ๋ค(์ฌํ ๊ฐ๋ฅํ ์คํ โ ๋ฐฑ์ง ์์์ด ์ ์ธ๋ ๊ฑฐ๋์ด๋ค).\n *\n * โโ ์ ํธ์์ ๋จ์๋ (์ ์ด๋ฆ `realityMode`) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ใํ์ค์ด ์ด๋์ ์ค๋ใ๋ ADR-0029 ๊ฐ **์๋ณธ์ ์ข
๋ฅ**๋ก ์ฎ๊ธด ๋ฌผ์์ด๋ค(`TwinReference.adapterType`) โ\n * ํธ์์ ํ ์ข
๋ฅ์ด๊ณ ์ธ์ ๋ ์๋ณธ์ ๋ฐ์ํ๋ค. ๊ทธ๋ฐ๋ฐ ์ฝ๋๊ฐ ์ด ์ถ์ผ๋ก ์ค์ ๋ก ๊ฐ๋ฅธ ๊ฒ์ **์ฌ๊ธฐ๋ ๊ฑฐ๋\n * ํ๋**์๊ณ , ๊ทธ๊ฒ์ ์๋ณธ์ ์ฑ์ง์ด ์๋๋ผ **ํธ์๊ณผ ์๊ธฐ ๊ณผ๊ฑฐ์ ๊ด๊ณ**๋ค: ๊ฐ์ ์๋ฎฌ๋ ์ดํฐ ์๋ณธ์ ๋ณด๋ ๋\n * ํธ์์ด ํ๋๋ ์ด์ด๊ฐ๊ณ ํ๋๋ ๋งค๋ฒ ์ฒ์๋ถํฐ ์ฌํํ ์ ์๋ค. ๊ทธ๋์ ์ถ์ ๋จ๊ณ ์ด๋ฆ๋ง ๋ฐ๋์๋ค.\n *\n * **๋น์ด ์์ ์ ์๊ณ , ๊ธฐ๋ณธ๊ฐ๋ ์๋ค.** ์์ ์๋ ๋ฏธ์ ์ธ์ด ์๋ฆฌ์ง ์๊ณ `sim-experiment`(=์ ๋ ์ด๊ธฐํ)๋ก\n * ๋จ์ด์ก๋ค โ ๊ฐ์ด ํ๋ ์ด๊ธ๋๋ ์๊ฐ ์ด๋ ฅ์ ์ง์ฐ๋ ๊ธธ์ด๋ค. ์ด์ ์ฝ๋ ์ชฝ์ด **์ค๋ฅ๋ฅผ ๋ธ๋ค**\n * (`engine/restart-policy.ts`). ์ ์ธ์ ํ๋ก๋น์ ๋ํ๋ ์ชฝ์ ๋ชซ์ด๋ค.\n */\n @Column()\n @Field({ description: \"Restart policy: 'resync' (read again from the external source) | 'resume' (continue this twin's own journal) | 'reset' (wipe and replay from the seed). No default โ an unspecified policy is refused.\" })\n restartPolicy: string\n\n /* ์ฝ์ ๋ ์ดํ ์ธ๋๋ฅผ ํก์ํ๋ค(`nodes`/`movers`/`equipmentList` โ `locations`/`equipment`). (vocabulary-guard: allow โ ์ธ๋ ์ด๋ฆ ์์ด๋ ์ค๋ช
ํ ์ ์๋ค.)\n ์๋ฆฌ๋ง๋ค ๋ฆฌ๋๋ฅผ ์ฐ๊ฒ ํ๋ฉด ๋ค์์ ์ถ๊ฐ๋๋ ์๋ฆฌ๊ฐ ๋ ๋น ์ง๊ณ , ๋น ์ง ๊ฒ์ ์ค๋ฅ๊ฐ ์๋๋ผ **๋น ๊ณต์ฅ**์ด๋ผ\n ๋ค์ด์จ ๊ฒ์ด ์๋ค(2026-08-06: ๋ชจ๋ธ๋ฌ ์ํฐํฐ ๋ชฉ๋ก์ด ํต์งธ๋ก ๋น์๋ค). ์์ธ `engine/model-vocabulary.ts`. */\n @Column({ type: 'simple-json', nullable: true, transformer: modelColumnTransformer })\n @Field(type => ScalarObject, { nullable: true, description: 'TwinModelDef blueprint (locations/equipment) required to replay events into state. Older stored boards used nodes/movers/equipmentList; they are normalised on read so consumers see one vocabulary.' }) // vocabulary-guard: allow โ ์ ์ดํ๋ฅผ ํก์ํ๋ ๊ฒ์ด ์ด ์ฝ๋์ ์ผ์ด๋ค(์ธ๋ ์ด๋ฆ์ ์ ์ด์ผ ํก์ํ ์ ์๋ค)\n model?: any\n\n /*\n * ๋ก์ปฌ ์ ์ธ ๊ฒน โ **๊ตฌ์กฐ๋ ์์ฒ์ด, ์๋ ์ฐ๋ฆฌ๊ฐ.**\n *\n * ์๊ธ ๋จ๊ฐยท๊ณ์ฝ ์ ๋ณดยท์ถ์ ์ง ์ถฉ์ ์จ์ฒ๋ผ ์ ์์คํ
์ด ๋ชจ๋ฅด๋ ๊ฐ์ ๋ฃ๋ ์๋ฆฌ๋ค. `model` ์ ์ง์ ์ฐ์ง\n * ์๋ ์ด์ ๋ ๊ทธ๊ฒ์ด **์์ฒ์ ์ฌ๋ณธ**์ด๊ธฐ ๋๋ฌธ์ด๋ค: ๋ค์ ์ฝ๊ธฐ๊ฐ ์ฌ๋ณธ์ ์๋ก ๊ทธ๋ฆฌ๋ฉด ์ง์ ์ด ๊ฐ์ ์๋ฆฌ์ง ์๊ณ \n * ์ฌ๋ผ์ง๋ค(์๊ธ์ด ์ฌ๋ผ์ง๋ฉด ๊ธ์ก๋ ์ฌ๋ผ์ง๊ณ , ์ฌ์ฉ์๋ ์ด์ ๋ฅผ ์ ์ ์๋ค).\n *\n * ๊ทธ๋์ ์ฌ๊ธฐ ๋จ๊ธฐ๊ณ , ๋ชจ๋ธ์ ๊ทธ๋ฆด ๋๋ง๋ค ๊ทธ ์์ ์น๋๋ค(`engine/local-declarations`). ์นํ ๊ฐ์๋\n * `source: 'local'` ์ด ๋ถ๋๋ค โ ์ปค๋ ๊ณ์ฝ์ `PropertySource` ์ถ(`reference` โ `local`)์ด๊ณ , ใ๋ฐ์์\n * ์ฐธ์กฐํด ์จ ๊ฐ์ด๋, ์ด ์์์ ์ ํ ๊ฐ์ด๋ใ์ ๋ตํ๋ค.\n *\n * **์ด๋ฆ์ ์ฅ์ ๋ฑ๋ง์ ์ฐ์ง ์๋๋ค**(์ ์ด๋ฆ `siteDeclarations`): ์ด ์ฝ๋์์ `site` ๋ **์ธ๋ถ\n * ์์คํ
์ด ๋ถ๋ฅด๋ ์ฌ์
์ฅ**์ด๊ณ (SAP `P3`ยทOracle `W01` ์ด ๊ฐ์ ํ์ฅ), ์ฌ๊ธฐ ๋ด๊ธฐ๋ ๊ฒ์ ๊ทธ ์ธ๋ถ ์์คํ
์ด\n * **๋ชจ๋ฅด๋** ๊ฐ์ด๋ค โ ์ด๋ฆ์ด ๋ด์ฉ๊ณผ ์ ๋ฐ๋์๋ค. `space` ๋ ์๋๋ค: ๊ทธ๊ฒ์ ใ์ด๋ใ์ ๋ตํ๊ณ ์ด ์ถ์\n * ใ๋๊ฐ ๋งํ๋ใ์ ๋ตํ๋ค.\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: \"Locally-declared values layered on top of the reference-derived model (tariff, contract, state of charge) โ values whose authority sits here, not in the source system. Kept apart from `model` so a resync cannot silently drop them.\" })\n localDeclarations?: any\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Owning space id (co-location anchor). Promoted from model.spaceId โ first-class \"space โ its twins\" query (space-centered ontology).' })\n spaceId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Owning area id within the space (optional scope). Promoted from model.areaId.' })\n areaId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Lifecycle status: running | stopped.' })\n status?: string\n\n /*\n * purpose โ ์ด ์ธ์คํด์ค๊ฐ ์ด์ ํธ์์ธ์ง, ๊ฒฉ๋ฆฌ๋ ๋ฒค์น ์ฌ๋ณธ์ธ์ง 1๊ธ ์ ์ธ(์ด๋ฆ ์ ๋์ฌ๊ฐ ์๋๋ผ ์์ฑ์ผ๋ก ๊ตฌ๋ณ).\n * 'bench' ๋ ๊ท๋ชจ/๋ถํ ์คํ์ฉ ๊ฒฉ๋ฆฌ ์ฌ๋ณธ โ ๋ชฉ๋กยท์ ๋ฆฌยท์์ ๊ฐ๋๊ฐ ์ด ์์ฑ์ ํค๋ก ๋์(์ด์ ํธ์ ๋ฌด์ค์ผ ๋ณด์ฅ).\n *\n * **๋น์ด ์์ ์ ์๋ค.** ํ๋ก๋น์ ๋์ด `register` ์์ 'operational' ๋ก ๊ฐ์ธํ๊ณ , ๋ฒค์น ์ฌ๋ณธ๋ง\n * `setPurpose` ๋ก ๋ค์ง๋๋ค. ์์ ์๋ ๋น์ ๋ ์ฑ ์ฝ๋ ์ชฝ์์ ๋ฉ์ ๋๋ฐ, ๊ทธ๋ฌ๋ฉด \"์ด์์ด๋ผ๊ณ ์ ์ธ๋ ๊ฒ\"\n * ๊ณผ \"์๋ฌด๋ ๋งํ์ง ์์ ๊ฒ\" ์ด ๊ฐ์ ๊ฐ์ผ๋ก ๋ณด์ฌ์ ๋ฒค์น ๊ฒฉ๋ฆฌ๊ฐ ์ถ์ธก์ ๊ธฐ๋๊ฒ ๋๋ค.\n */\n @Column()\n @Field({ description: \"Instance purpose: 'operational' (real twin) | 'bench' (isolated copy for scale/load experiments).\" })\n purpose: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'For a bench copy: the source spaceId it was copied from (provenance).' })\n copyOf?: string\n\n /**\n * **์ด ํธ์์ ๋ค์ ์ฝ๋ ๋ฐฉ๋ฒ** โ ์ด๋ค ์๋ณธ์์ ๋์๋(`MasterOrigin`).\n *\n * ํธ์์ ์๋ณธ์ ๋น์ถ ๋ฟ์ด๋ฏ๋ก(ADR-0028) ์๋ณธ์ด ๋ฌ๋ผ์ง๋ฉด ๋ค์ ์ฝ์ด์ผ ํ๋ค. ๊ทธ๋ฐ๋ฐ ์ด ์๋ฆฌ๊ฐ ์๋\n * ๋์ ํธ์์ **์๊ธฐ๊ฐ ๋ฌด์์์ ๋์๋์ง ๋ชฐ๋๋ค** โ ์ด๋ํฐ๋ก ๋ค์ด์จ ํธ์์ `TwinReference` ํ์ด\n * ์์์ง๋ง ํ
ํ๋ฆฟ์ผ๋ก ์ธ์ด ํธ์์๋ ์๋ฌด ํ์๋ ์์๊ณ , ๊ทธ๋์ ์ฒซ๋ ์ ๋ชจ์ต์ ์์ํ ๋จธ๋ฌด๋\n * ํธ์์ด ๋ง๋ค์ด์ก๋ค. ์์ฒ์ด ๋ฌด์์ด๋ ์ฌ๊ธฐ ํ ์๋ฆฌ์ ๋จ๊ธด๋ค.\n *\n * **๋น์ด ์์ ์ ์๋ค** โ ์ด ์๋ฆฌ๊ฐ ์๊ธฐ๊ธฐ ์ ์ ๋ง๋ค์ด์ง ํธ์์ด ๊ทธ๋ ๋ค. ๊ทธ๋๋ \"๋ค์ ์ฝ์ ์\n * ์๋ค\" ๊ฐ ์ฌ์ค์ด๋ฏ๋ก ํ๋ฉด์ด ๊ทธ๋๋ก ๋งํ๋ค(์ง์ํด ์ฑ์ฐ์ง ์๋๋ค).\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, {\n nullable: true,\n description:\n \"How this twin's master can be produced again โ {kind:'reference', source} or {kind:'template', templateId, params}. Absent means this twin cannot be re-read from its source.\"\n })\n origin?: any\n\n /*\n * `revision` ์ปฌ๋ผ์ **์์ด๋ค**(2026-08-08).\n *\n * `ADR-0015` ๊ฐ \"์ ์๋ง ์๊ณ write ์ ๋จ โ ํ๋ก๋น์ ๋์์ ์ต์ ์ ๋ revision ์ ๋ฐ์ํ๋๋ก\n * ์ฑ์ด๋ค\" ๊ณ ์ ์ด ๋์๋๋ฐ, ์ฑ์ฐ์ง ์๋ ํธ์ด ๋ง๋ค. ์ ๋์ ์ต์ ๋ฒํธ๋ **์ ๋์ด ์๋ ์ฌ์ค**์ด๊ณ \n * (`TwinEngine.list` ๊ฐ `MAX(revision)` ์ผ๋ก ๋ธ๋ค), ์ฌ๊ธฐ ๋ณต์ ํ๋ฉด **๊ฐ์ ์ฌ์ค์ ์ง์ด ๋**์ด ๋๋ค.\n * ์ด ์ธ์
์๋ง ๊ทธ ๋ถ๋ฅ๋ฅผ ์
๊ฒช์๋ค(`model.operations` ๋ ์ง ยท `materials` ๋ ์ง ยท tenantId ์ค๋ณต).\n *\n * ๋ณต์ ํ ๊ฐ์ ๋ฐ๋์ ์ด๊ธ๋๋ค โ ์ ๋์ ํฑ๋ง๋ค ๋๊ณ ์ด ์ปฌ๋ผ์ ์ ์ฅํ ๋๋ง ๊ฐฑ์ ๋๋ฏ๋ก, ํ๋ฉด์ด\n * ์ด๋ ์ชฝ์ ์ฝ๋๋๋ก ๋ค๋ฅธ ์ซ์๊ฐ ๋์จ๋ค. ๊ทธ ๋ค์ด์จ ๊ฒ์ด ์๋ ์ด๊ธ๋จ์ ๋ง๋ค ์ด์ ๊ฐ ์๋ค.\n */\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when the instance was first registered.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when the instance registry row was last updated.' })\n updatedAt?: Date\n\n /*\n * ๋๊ฐ ๋ง๋ค๊ณ ๋๊ฐ ๊ณ ์ณค๋ โ **์ด ํ์ ์ฌ๋์ด ๋ง๋ ๋ค**(ํ๋ก๋น์ ๋์ ์ฌ์ฉ์ ํ์)์ด๋ฏ๋ก ๊ท์ฝ์\n * ํ์ธํธ๋ฅผ ๊ฐ๋๋ค. ํฌ์ ํ(์๋ฆฌยท์ค๋นยท๊ณต์ )์ ๋ฐ๋๋ก ์ธ์ ์คํธ๊ฐ ๊ทธ๋ฆฐ ๊ฒ์ด๋ผ ์ ์๊ฐ ์ฌ๋์ด ์๋๊ณ ,\n * ๊ทธ ์ ์๋ `sourceRef`+`ingestedAt` ์ด ์ด๋ฏธ ๋งํ๋ค โ ๊ทธ๋์ ๊ทธ์ชฝ์๋ ๋์ง ์๋๋ค.\n *\n * ๋น์ด ์์ ์ ์๋ค: ๋ถํ
์๋ ํ๋ก๋น์ ๋์ฒ๋ผ **์ฌ๋์ด ์๋ ๊ฒฝ๋ก**๋ก ๋ง๋ค์ด์ง ํ์ด ๊ทธ๋ ๋ค.\n * ๊ทธ๋ ์๋ฌด ์ฌ์ฉ์๋ฅผ ์ ์ด ๋ฃ์ผ๋ฉด ๊ฐ์ฌ ๊ธฐ๋ก์ด ๊ฑฐ์ง์ด ๋๋ค.\n */\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who first provisioned this twin. Empty when it was created by a system path (boot provisioning).' })\n creator?: User\n\n @RelationId((e: TwinInstance) => e.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last changed this twin registry row.' })\n updater?: User\n\n @RelationId((e: TwinInstance) => e.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event-type-split-shape.js","sourceRoot":"","sources":["../../../server/service/twin-journal/event-type-split-shape.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * **์ด ๋ฌผ์์ด ใ์ฌ๋ฌ ์ข
๋ฅ๋ฅผ ์๊ฐ์์ผ๋กใ์ธ๊ฐ** โ ์์ ํ๋จ๋ง ์ฌ๊ธฐ ๋๋ค.\n *\n * ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ถ๋ฅด์ง ์๋๋ค. ๊ทธ๋์ ์ํ์ด ์ด ํ์ผ์ ๊ทธ๋๋ก ๋ถ๋ฅผ ์ ์๋ค(๋ฐ์ฝ๋ ์ดํฐ๊ฐ ์๋ค).\n * ํ๋จ์ด ์กฐํ ์ฝ๋ ์์ ์์ฌ ์์ผ๋ฉด ๊ทธ ํ๋จ๋ง ํ์ธํ ๋ฐฉ๋ฒ์ด ์๊ณ , ๊ทธ๋ฌ๋ฉด ใ์ด๋ค ๋ฌผ์์ด ๋๋ ๋ฌป๋\n * ๊ฐ๋๋ก ๊ฐ๋๊ฐใ๊ฐ ์๋ฌด๋ ์ฝ์ง ๋ชปํ๋ ๊ท์น์ด ๋๋ค.\n *\n * ์ค์ธก ๊ทผ๊ฑฐ์ ๊ณ ์นจ์ ๋ป์ `event-type-split.ts` ๋จธ๋ฆฌ์ ์๋ค.\n */\nimport { absoluteTime } from '../../engine/read-time.js'\n\n/** ์ง์๋ฅผ ๋ช ๊ฐ๊น์ง ๋๋๊น โ ๋์ ร ์ข
๋ฅ. ์ด ์ด์์ด๋ฉด ๋๋๋ ๊ฒ์ด ์ํด๋ค. */\nexport const MAX_SPLIT = 24\n\n/** ์ข
๋ฅ ๋ชฉ๋ก์ ์ํ โ ์ด๋ณด๋ค ๋ง์ผ๋ฉด ใ์ด ์ข
๋ฅ๋งใ์ด ์๋๋ผ ์ฌ์ค์ ์ ์ฒด๋ค. */\nconst MAX_TYPES = 12\n\nexport interface SplitShape {\n eventTypes: string[]\n /**\n * ๊ณต์ ๋จ๊ณ ํ๋๋ก ์ขํ ๊ฒฝ์ฐ โ ๊ทธ ๊ฐ์ ๊ฐ๋๋ง๋ค ํจ๊ป ๊ฑด๋ค.\n *\n * ์ด ํํฐ๋ฅผ ๋ง๋๋ฉด ๊ฐ๋๋ฅผ ํฌ๊ธฐํ๋ ๊ฒ์ ๊ณ ์ณค๋ค(2026-08-29). ์์ฅ์ ์ข
๋ฅ๋ฅผ ๋ด์ ๋ฌป๊ณ ๊ทธ ์์ ๋จ๊ณ\n * ์นฉ์ ๊ฒน์น๋๋ฐ, ์นฉ์ ๊ณ ๋ฅธ ์๊ฐ ์์ ๊ฒฝ๋ก๋ก ๋จ์ด์ ธ **๊ณ ๋ฅด์ง ์์ ์ชฝ์ด ๋ ๋นจ๋๋ค.**\n *\n * ๋จ๊ณ ์ปฌ๋ผ์๋ ์์ธ์ด ์๋ค. ๊ทธ๋๋ ๋๋ ค์ง์ง ์๋๋ค โ ์ข
๋ฅ ์ ํ์ผ์น๊ฐ ์์ธ์ผ๋ก ์๊ฐ ์์๊น์ง ์ฃผ๊ณ ,\n * ๋จ๊ณ๋ ๊ทธ ์์์ ํ๋ง๋ค ํ์ธํ๋ ์กฐ๊ฑด์ด๋ค(๊ฑท๋ ํ์ด ๊ทธ ์ข
๋ฅ์ ๊ฒ์ผ๋ก ์ด๋ฏธ ์ขํ์ ธ ์๋ค).\n */\n bizStep?: string\n untilTime?: Date\n fromTime?: Date\n}\n\n/**\n * ์ด ๋ฌผ์์ด ใ์ฌ๋ฌ ์ข
๋ฅ๋ฅผ ์๊ฐ์์ผ๋กใ์ธ๊ฐ โ ์๋๋ฉด `null`.\n *\n * ๋ฐ๋ ๋ชจ์\n * `eventType` ์ `in` ์ผ๋ก ยท ์๊ฐ ์ํ์ด๋ ๊ตฌ๊ฐ ยท ์๊ฐ ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ\n *\n * ๋ณด๋ด๋ ๋ชจ์(์ผ๋ฐ ๊ฒฝ๋ก๋ก)\n * ์์ ๊ฒ์์ด ยท ๊ทธ ๋ฐ์ ํํฐ(์ถยท์๊ด ์๋ณ์ยท์
๋ฌด ๋จ๊ณ) ยท ๊ทธ ๋ฐ์ ์ ๋ ฌ์ด๋ ์ฐ์ฐ์\n */\nexport function splitShape(params: any, sortings: any[]): SplitShape | null {\n const filters: any[] = Array.isArray(params?.filters) ? params.filters : []\n if (typeof params?.search === 'string' && params.search.trim()) return null\n if (sortings.length !== 1 || sortings[0]?.name !== 'eventTime' || sortings[0]?.desc !== true) return null\n\n let eventTypes: string[] | undefined\n let untilTime: Date | undefined\n let fromTime: Date | undefined\n let bizStep: string | undefined\n for (const f of filters) {\n if (f?.name === 'eventType') {\n if (f.operator !== 'in' || !Array.isArray(f.value)) return null\n const types: string[] = f.value.map((v: unknown) => String(v ?? '').trim()).filter((t: string) => !!t)\n /* ํ๋๋ฉด ๋๋ ๊ฒ์ด ์๋ค(์ด๋ฏธ ์ ํ์ผ์น๋ผ ์์ธ์ ํ๋ค). ๋๋ฌด ๋ง์ผ๋ฉด ์ฌ์ค์ ์ ์ฒด๋ค. */\n if (types.length < 2 || types.length > MAX_TYPES) return null\n if (eventTypes) return null\n eventTypes = [...new Set(types)]\n } else if (f?.name === 'bizStep') {\n /* ํ๋๋ก ์ขํ ๊ฒฝ์ฐ๋ง ๋ฐ๋๋ค โ ์ฌ๋ฌ ๊ฐ์ด๋ฉด ์ข
๋ฅ ร ๋จ๊ณ๋ก ๊ฐ๋๊ฐ ๊ณฑํด์ง๋ค. */\n if (f.operator !== 'eq') return null\n const v = String(f.value ?? '').trim()\n if (!v) return null\n if (bizStep) return null\n bizStep = v\n } else if (f?.name === 'eventTime') {\n if (f.operator === 'lte' || f.operator === 'lt') {\n untilTime = absoluteTime(f.value) ?? undefined\n if (!untilTime) return null\n } else if (f.operator === 'between' && Array.isArray(f.value)) {\n fromTime = absoluteTime(f.value[0]) ?? undefined\n untilTime = absoluteTime(f.value[1]) ?? undefined\n if (!fromTime || !untilTime) return null\n } else return null\n } else return null\n }\n return eventTypes ? { eventTypes, untilTime, fromTime, bizStep } : null\n}\n\n/**\n * **๋๋ ๋ฌผ์ ๊ฐ๋๋ค์ ํฉ์ณ ์์์ `limit` ๊ฐ** โ ์ด ๊ท์จ์ด ์ ํ์ฑ์ ๊ทผ๊ฑฐ๋ค.\n *\n * โโ ์ ๊ฐ๋๋ง๋ค `limit` ๊น์ง ๋ฐ์์ผ ํ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ฐ๋๋ง๋ค `limit` ๊ฐ๋ฅผ ๋ฐ์ ํฉ์น๋ฉด, ํฉ์น ๊ฒ์ ์ `limit` ๊ฐ๋ **์ ์ฒด์์๋** ์ `limit` ๊ฐ๋ค.\n * ์ด๋ค ๊ฐ๋์์ ๋น ์ง ํ์ ๊ทธ ๊ฐ๋์ `limit` ๋ฒ์งธ๋ณด๋ค ๋ค์ด๊ณ , ์ฐ๋ฆฌ๋ ์ ์ฒด์์ `limit` ๊ฐ๋ง ์ทจํ๋ฏ๋ก\n * ๊ทธ ํ์ด ์ด ํ์ด์ง์ ๋ค์ด์ฌ ์ ์๋ค.\n *\n * ๊ฐ๋๋ง๋ค **๋ ์ ๊ฒ** ๋ฐ์ผ๋ฉด ๊ทธ ์ฑ์ง์ด ๊นจ์ง๋ค. ํ ๊ฐ๋๊ฐ ์์ ๋ค ์ฐจ์งํ๋ ๊ฒฝ์ฐ\n * (์ข
๋ฅ A ์ ๋ง์ง๋ง์ด ์ข
๋ฅ B ์ ์ฒซ์งธ๋ณด๋ค ์์ ๋ค) ๊ทธ ๊ฐ๋์์ ๋ชป ๋ฐ์ ๊ฒ์ด ๋น ์ง๊ณ , ๊ฒฐ๊ณผ๋ ๊ตฌ๊ฐ์\n * ์๋ถ๋ถ๋ง ๊ณ์ฐํ ๊ฒ์ด ๋๋ค โ ๊ทธ๋ฐ๋ฐ ํ๋ฉด์ ใ์ผ๋ถ๋ง ์ฝ์๋คใ๊ณ ๋ง ๋งํ๊ณ ์ด๋ ๋ถ๋ถ์ธ์ง๋ ๋งํ์ง ๋ชปํ๋ค.\n * (2026-08-28 ยท UX ๋ ์ธ์ด ๋ฏธ๋ฆฌ ์ง์ด ์ค ํจ์ ์ด๋ค.)\n *\n * ๊ทธ๋์ ์ด ํจ์๋ **`limit` ๋ฏธ๋ง์ผ๋ก ๋ฐ์ ๊ฐ๋๊ฐ ์์ผ๋ฉด ๊ทธ๊ฒ์ ๋งํ๋ค** โ ๋ถ๋ฅด๋ ์ชฝ์ด ๊ทธ ์ํ๋ก\n * ๋ตํ์ง ์๊ฒ.\n */\nexport function mergeStreams<T>(\n streams: readonly T[][],\n limit: number,\n /** ์์ ์์ผ ํ๋ ๊ฒ์ด ์์ โ `Array.prototype.sort` ์ ๊ฐ์ ๊ท์ฝ. */\n compare: (a: T, b: T) => number\n): { items: T[]; capped: boolean; underfilled: boolean } {\n const underfilled = streams.some(s => s.length > limit)\n const merged = streams.flat().sort(compare)\n return {\n items: merged.slice(0, limit),\n /* ํฉ์น ๊ฒ์ด ์ํ์ ๋์์ผ๋ฉด ๋ ์์๋ค๋ ๋ป์ด๋ค โ ์๋๋ค๋ ์ฌ์ค์ ๋ถ๋ฅด๋ ์ชฝ์ด ๋งํด์ผ ํ๋ค. */\n capped: merged.length > limit || streams.some(s => s.length >= limit),\n /* ๊ฐ๋๊ฐ ์ํ๋ณด๋ค ๋ง์ด ๋ฐ์ ์๋ค โ ์์ ์ ์๋ ์ผ์ด๋ฏ๋ก ๋ถ๋ฅด๋ ์ชฝ์ด ์์์ผ ํ๋ค. */\n underfilled\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event-type-split.js","sourceRoot":"","sources":["../../../server/service/twin-journal/event-type-split.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\n\nimport { TwinEvent } from '../twin-event/twin-event.js'\nimport { absoluteTime } from '../../engine/read-time.js'\nimport { MAX_SPLIT, type SplitShape } from './event-type-split-shape.js'\n\n/*\n * **์ฌ๋ฌ ์ข
๋ฅ๋ฅผ ์๊ฐ์์ผ๋ก โ ์ข
๋ฅ๋ฅผ ํ๋์ฉ ๋๋ ๋ฌป๋๋ค** (2026-08-28 ์ค์ธก).\n *\n * โโ ๋ฌด์์ด ๋๋ ธ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์๋์ง ์์ฅ์ ใ์ด ์ฌ๋ ์ข
๋ฅ๋ฅผ ์๊ฐ ๋ด๋ฆผ์ฐจ์์ผ๋ก 50๊ฑดใ์ ๋ฌป๋๋ค. ๊ทธ ๋ชจ์์์ sqlite ๋ ์ข
๋ฅ ์์ธ์\n * **๋ฒ๋ฆฐ๋ค**:\n *\n * ์ข
๋ฅ IN + ์๊ฐ์ SEARCH USING INDEX ix_twin_event_1 (domain, instance) 37.181์ด ยท ๊ฒฐ๊ณผ 0๊ฑด\n * ๊ฐ์ ์กฐ๊ฑด ยท ์ ๋ ฌ ์์ SEARCH USING INDEX ix_twin_event_7 (โฆ, event_type=?) 0.003์ด\n * ์ข
๋ฅ ํ๋ + ์๊ฐ์ SEARCH USING INDEX ix_twin_event_7 (โฆ, event_type=?) 0.003์ด\n *\n * ์ ๋ ฌ์ ๋ถ์ด๋ ์๊ฐ ์ฌ๋ฌ ์ข
๋ฅ์ ์์๋ฅผ ํฉ์น ๋ฐฉ๋ฒ์ด ์์ด, ์๊ฐ ์์ธ์ผ๋ก 337๋ง ํ์ ๊ฑธ์ผ๋ฉฐ ํ๋ง๋ค\n * ์ข
๋ฅ๋ฅผ ํ์ธํ๋ค. ์นํํธ๋์ ์๋์ง ์ฌ๊ฑด์ 0๊ฑด์ด๋ค โ **์๋ ๊ฒ์ ์ฐพ๋๋ผ 37์ด**๋ฅผ ์ด๋ค.\n *\n * 360 ์ด๋ ฅ์ด 64์ด์๋ ๊ฒ๊ณผ ๊ฐ์ ๋ถ๋ฅ๋ค: **๊ฑฐ๋ฅด๋ ์ถ๊ณผ ์ ๋ ฌ ์ถ์ด ์ด๊ธ๋๋ค.**\n *\n * โโ ๊ณ ์นจ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ข
๋ฅ๋ฅผ **์ ํ์ผ์น๋ก ํ๋์ฉ** ๋ฌผ์ผ๋ฉด ์์ธ์ด ์๊ฐ ์์๊น์ง ๊ทธ๋๋ก ์ค๋ค(์ ๋ ฌ์ด ์ฌ๋ผ์ง๋ค). ์ฌ๋ ์ข
๋ฅ๋ฉด\n * ์ง์ ์ฌ๋ ๊ฐ์ด๊ณ ๊ฐ 0.003์ด๋ค. ๋ฐ์ ๊ฒ์ ์๊ฐ์์ผ๋ก ํฉ์ณ ํ ํ์ด์ง๋ฅผ ๋ง๋ ๋ค.\n *\n * ์ ์์ธ๋, ์ ํ
์ด๋ธ๋ ํ์ ์๋ค โ ์๋ ์์ธ์ ์ฐ๊ฒ ํ๋ ๊ฒ์ด ์ ๋ถ๋ค.\n *\n * โโ ์ข๊ฒ ์ก๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ๋ชจ์์ด ์๋ ๋ฌผ์์ ๋ตํ์ง ์๊ณ (`null`) ์ ๋์ ์ผ๋ฐ ๊ฒฝ๋ก๋ก ๋ณด๋ธ๋ค. ์ต์ง๋ก ๋ตํ๋ฉด ๋ชฉ๋ก์ด ์๋ฆฌ์ง\n * ์๊ณ ๋ฌ๋ผ์ง๋ค.\n *\n * โโ โ
**์ด ๊ฐ๋๋ฅผ ๊ฑท์ ์กฐ๊ฑด** โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฑ์์ ์ข
๋ฅ๋ฅผ ์ฌ๋ฌ ๊ฐ์ผ๋ก ๋ณด๋ด๋ ๊ณณ์ **์๋์ง ์์ฅ ํ ๊ณณ๋ฟ**์ด๋ค(2026-08-28 ํ์ธ). ๊ทธ ํ๋ฉด์ด\n * ์ข
๋ฅ๋ฅผ ํ๋์ฉ ๊ณ ๋ฅด๋ ๋ชจ์์ผ๋ก ๋ฐ๋๋ฉด ์ด ๊ฐ๋๋ฅผ ๋ถ๋ฅด๋ ๋ฐ๊ฐ ์์ด์ง๋ค โ ๊ทธ๋ **์ง์ด๋ค.**\n *\n * ๋ถ๋ฅด๋ ๋ฐ๊ฐ ์๋ ๊ฐ๋๋ฅผ ๋ค๊ณ ์์ผ๋ฉด, ๊ทธ๊ฒ์ด ๋ฌด์ธ๊ฐ๋ฅผ ๋ฐ์ณ ์ฃผ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ฉด์ ์ค์ ๋ก๋ ์๋ฌด๊ฒ๋\n * ํ์ง ์๋๋ค. ์ง๊ธ ์ด๋ ค ๋๋ ์ด์ ๋ ํ๋๋ค: ์ค ๊ณ ๊ฐ ํธ์์์ 37์ด ์ง์๊ฐ ๋๊ณ ์๊ณ ํ๋ฉด ์์ ์\n * ๋ค๋ฅธ ๋ ์ธ์ ์ผ์ด๋ค.\n */\n\nexport interface SplitPage {\n items: TwinEvent[]\n nextCursor?: string\n}\n\n/**\n * ๋๋ ๋ฌป๊ณ ํฉ์ณ ํ ํ์ด์ง โ ๋ตํ ์ ์์ผ๋ฉด `null`.\n *\n * ์ด์ด ์ฝ๊ธฐ ์ง์ ์ **๋ชจ๋ ๊ฐ๋์ ๊ฐ์ด** ๊ฑด๋ค. ๊ทธ๋์ผ ํฉ์น ๊ฒฐ๊ณผ๊ฐ ์ปค์ ์๋์์๋ง ๋์จ๋ค โ ๊ฐ๋๋ง๋ค\n * ๋ค๋ฅด๊ฒ ๊ฑธ๋ฉด ์ด๋ค ์ข
๋ฅ๋ ์ด๋ฏธ ์ง๋๊ฐ ๊ตฌ๊ฐ์ ๋ค์ ๋ธ๋ค.\n */\nexport async function eventTypeSplitPage(\n domainId: string,\n instanceIds: string[],\n shape: SplitShape,\n limit: number,\n /** ๋์๊ฐ์ ๊ฐ๋ฆฌ๋ ์ถ โ ํธ์ ํ๋๋ฉด `revision`, ์ฌ๋ฟ์ด๋ฉด ๊ธฐ๋ณธํค(ยง`cursorTiebreak`). */\n tiebreak: 'revision' | 'id',\n after?: string\n): Promise<SplitPage | null> {\n const pairs = instanceIds.length * shape.eventTypes.length\n if (!pairs || pairs > MAX_SPLIT) return null\n\n let cursor: { at: Date; tie: string | number } | null = null\n if (after) {\n cursor = decodeCursorPair(after)\n if (!cursor) return null\n }\n\n const rows: TwinEvent[][] = []\n for (const instanceId of instanceIds) {\n for (const eventType of shape.eventTypes) {\n const qb = getRepository(TwinEvent)\n .createQueryBuilder('e')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n /* **์ ํ์ผ์น**๊ฐ ์์ ์ด๋ค โ ๊ทธ๋์ผ ์์ธ์ด ์๊ฐ ์์๊น์ง ์ค๋ค(ยง ์ ์ค์ธก). */\n .andWhere('e.eventType = :eventType', { eventType })\n /* ๋จ๊ณ๋ ์์ธ์ด ์๋๋ผ ํ ์กฐ๊ฑด์ด๋ค โ ์ข
๋ฅ ์ ํ์ผ์น๊ฐ ์ด๋ฏธ ๊ฑท๋ ๋ฒ์๋ฅผ ์ขํ ๋์๋ค. */\n if (shape.bizStep) qb.andWhere('e.bizStep = :bizStep', { bizStep: shape.bizStep })\n if (shape.fromTime) qb.andWhere('e.eventTime >= :fromTime', { fromTime: shape.fromTime })\n if (shape.untilTime) qb.andWhere('e.eventTime <= :untilTime', { untilTime: shape.untilTime })\n if (cursor) {\n qb.andWhere(`(e.eventTime < :curAt OR (e.eventTime = :curAt AND e.${tiebreak} < :curTie))`, {\n curAt: cursor.at,\n curTie: cursor.tie\n })\n }\n const page = await qb\n .orderBy('e.eventTime', 'DESC')\n .addOrderBy(`e.${tiebreak}`, 'DESC')\n .limit(limit)\n .getMany()\n .catch(() => null)\n /* ํ ๊ฐ๋๋ผ๋ ๋ชป ์ฝ์ผ๋ฉด ํฉ์น ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ชฝ์ด๋ค โ ๋ฐ์ชฝ์ ์ ๋ถ์ธ ๊ฒ์ฒ๋ผ ๋ด์ง ์๋๋ค. */\n if (!page) return null\n rows.push(page)\n }\n }\n\n /*\n * ํฉ์น๋ค. ๊ฐ๋๋ง๋ค `limit` ๊น์ง ๋ฐ์์ผ๋ฏ๋ก, ํฉ์ณ์ ์์ `limit` ๊ฐ๋ **์ ์ฒด์์๋** ์์ `limit` ๊ฐ๋ค\n * (๊ฐ ๊ฐ๋๊ฐ ์๊ธฐ ์์์ ์ ๋ ฌ๋ผ ์๊ณ ๊ทธ๋ณด๋ค ์์ ๊ฒ์ ๋น ๋จ๋ฆด ์ ์๋ค).\n */\n const merged = rows\n .flat()\n .sort((a: any, b: any) => {\n /* `getMany` ๋ ์ํฐํฐ๋ฅผ ์ฃผ๋ฏ๋ก ์๊ฐ์ด ์ด๋ฏธ ๋ ์ง๋ค โ ๊ฐ์ธ๋ฉด ๋๋ผ์ด๋ฒ ๊ฐ์ ์์ผ๋ก ์ฝ๋ ๋ชจ์์ด ๋๋ค. */\n const at = (b.eventTime as Date).getTime() - (a.eventTime as Date).getTime()\n if (at !== 0) return at\n const x = a[tiebreak]\n const y = b[tiebreak]\n return x === y ? 0 : x < y ? 1 : -1\n })\n .slice(0, limit)\n\n const last: any = merged[merged.length - 1]\n const nextCursor =\n merged.length === limit && last?.eventTime instanceof Date && last[tiebreak] !== undefined\n ? encodeCursorPair(last.eventTime, last[tiebreak])\n : undefined\n\n return { items: merged, nextCursor }\n}\n\n/** ์ ๋ ๊ฒฝ๋ก์ ๊ฐ์ ์ปค์ โ `[eventTime, ๋์๊ฐ ์ถ]`(ยง`buildNextCursor`). */\nfunction encodeCursorPair(at: Date, tie: string | number): string {\n return Buffer.from(JSON.stringify([at, tie]), 'utf8').toString('base64url')\n}\n\nfunction decodeCursorPair(cursor: string): { at: Date; tie: string | number } | null {\n let values: unknown\n try {\n values = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'))\n } catch {\n return null\n }\n if (!Array.isArray(values) || values.length !== 2) return null\n const at = absoluteTime(values[0])\n const tie = values[1]\n if (!at || (typeof tie !== 'string' && typeof tie !== 'number')) return null\n return { at, tie }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/twin-journal/index.ts"],"names":[],"mappings":";;;AAAA,mEAA0D;AAE7C,QAAA,SAAS,GAAG,CAAC,wCAAgB,CAAC,CAAA","sourcesContent":["import { TwinJournalQuery } from './twin-journal-query.js'\n\nexport const resolvers = [TwinJournalQuery]\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"journal-order.js","sourceRoot":"","sources":["../../../server/service/twin-journal/journal-order.ts"],"names":[],"mappings":";;AAMA,oCAaC;AAnBD;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,CAK5B;IAIC,iEAAiE;IACjE,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAA;IACxD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;IAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;AAChD,CAAC","sourcesContent":["/**\n * ์ง๋ ๊ธฐ๋ก ์กฐํ์ ์ ๋ ฌ ์ถ โ **๋ถ๋ฅด๋ ์ชฝ์ด ๋ฌด์์ผ๋ก ๋ฌผ์๋์ง์ ๋ง์ถ๋ค.**\n *\n * ๋ฆฌ์กธ๋ฒ ์์ ๋๋ฉด ์ด ๊ท์น์ ํ์ธํ ๋ฐฉ๋ฒ์ด ์์ค๋ฅผ ๊ธ์๋ก ์ ์ ์กฐํํ๋ ๊ฒ๋ฟ์ด๋ค. ๊ท์น ์์ฒด๋ฅผ ๋ถ๋ฅผ ์ ์๊ฒ\n * ๋ฐ์ผ๋ก ๋บ๋ค(`test/journal-order-axis.test.ts`).\n */\nexport function journalOrder(q: {\n untilTime?: string | null\n fromTime?: string | null\n fromRevision?: number | null\n toRevision?: number | null\n}): {\n eventTime?: 'DESC'\n revision: 'DESC'\n} {\n /* `revision` ์ผ๋ก ๋ฌผ์์ผ๋ฉด ๊ทธ ์์๊ฐ ๋ฌผ์์ ๋ต์ด๋ค. ๊ฑฐ๋ฅด๋ ์ถ๊ณผ ์ ๋ ฌ ์ถ์ ๋ง์ถ๋ ๊ท์น๊ณผ๋ ๊ฐ๋ค. */\n const byTime = q.untilTime != null || q.fromTime != null\n if (!byTime && (q.fromRevision != null || q.toRevision != null)) return { revision: 'DESC' }\n return { eventTime: 'DESC', revision: 'DESC' }\n}\n"]}
|