@things-factory/headless-twin 10.1.277 → 10.1.279
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,262 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* 이미 있는 트윈을 다른 현장으로 옮긴다 — **판정만**. 순수.
|
|
3
|
-
*
|
|
4
|
-
* ── 왜 있나 (2026-08-13) ────────────────────────────────────────────────────
|
|
5
|
-
* 트윈↔현장 연결은 **만들 때만** 정할 수 있었다(템플릿 위자드·import 의 `spaceId`). 잘못 넣었거나,
|
|
6
|
-
* 나중에 "이 창고는 사실 저 공장과 같은 부지다" 를 알게 되면 지우고 다시 만드는 것이 유일한 길이었다 —
|
|
7
|
-
* 다시 만들면 그 트윈의 저널(일어난 일)이 사라진다. 고칠 수 있는 실수를 데이터 손실로 갚게 하는 설계다.
|
|
8
|
-
*
|
|
9
|
-
* ── 옮기는 것이 무엇을 옮기나 (엔티티 키를 보고 정했다) ──────────────────────
|
|
10
|
-
* 무엇이 트윈에 매여 있고 무엇이 공간에 매여 있는지가 답을 정한다:
|
|
11
|
-
*
|
|
12
|
-
* · `TwinEvent` `(domain, instanceId, …)` → **따라온다.** 저널을 다시 쓰지 않는다.
|
|
13
|
-
* · `TwinLocation/Equipment/Operation` `(domain, instance, …)` → **따라온다.**
|
|
14
|
-
* · `TwinArea` `(domain, space, areaId)` → **남는다.** 구역은 공간의 것이다.
|
|
15
|
-
* · `TwinSpaceRepresentation`(지도·이미지·보드) → **남는다.** 표현도 공간의 것이다.
|
|
16
|
-
*
|
|
17
|
-
* 그래서 옮기기는 이력 이전이 아니라 **소속 갱신**이다(`instance.spaceId` + `model.spaceId`).
|
|
18
|
-
* 대신 공간에 매인 것들과의 연결이 끊길 수 있고, 그것을 **알리지 않고 넘기지 않는 것**이 이 모듈의 일이다.
|
|
19
|
-
*
|
|
20
|
-
* ── 거절과 경고를 가른다 ────────────────────────────────────────────────────
|
|
21
|
-
* 거절: 되돌릴 수 없거나 뜻이 성립하지 않는 것(없는 공간·같은 공간·벤치 사본).
|
|
22
|
-
* 경고: 사용자가 알고 나면 정당할 수 있는 것(구역 소속이 끊긴다·시간대가 다르다·옛 표현이 남는다).
|
|
23
|
-
* 경고를 거절로 올리면 정당한 이전을 막고, 거절을 경고로 낮추면 들어온 것이 없는 사고가 된다.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/** 옮길 수 없는 이유 — 언어 중립 코드(발견 오류·인제스트 거절과 같은 규약). */
|
|
27
|
-
export type MoveSpaceRefusalCode = 'twin-not-found' | 'space-not-found' | 'same-space' | 'bench-copy'
|
|
28
|
-
|
|
29
|
-
/** 옮겨도 되지만 알아야 하는 것 — 같은 규약. */
|
|
30
|
-
export type MoveSpaceWarningCode = 'areas-left-behind' | 'timezone-differs' | 'representations-left-behind' | 'running'
|
|
31
|
-
|
|
32
|
-
export interface MoveSpaceNote<C extends string> {
|
|
33
|
-
code: C
|
|
34
|
-
params?: Record<string, string | number>
|
|
35
|
-
/** 영어 canonical — 로그에 남고, 번역이 없으면 그대로 보인다. */
|
|
36
|
-
message: string
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type MoveSpaceRefusal = MoveSpaceNote<MoveSpaceRefusalCode>
|
|
40
|
-
export type MoveSpaceWarning = MoveSpaceNote<MoveSpaceWarningCode>
|
|
41
|
-
|
|
42
|
-
export interface MoveSpaceInput {
|
|
43
|
-
/** 옮길 트윈. 없으면 거절한다. */
|
|
44
|
-
instanceId?: string
|
|
45
|
-
/** 지금 속한 공간(없을 수 있다 — 옛 트윈). */
|
|
46
|
-
fromSpaceId?: string
|
|
47
|
-
/** 옮겨 갈 공간. */
|
|
48
|
-
toSpaceId: string
|
|
49
|
-
/** 그 공간이 이 테넌트에 실제로 있나(호출측이 조회해 넘긴다). */
|
|
50
|
-
toSpaceExists: boolean
|
|
51
|
-
/** 운영 트윈인가 벤치 사본인가 — 사본은 원본의 공간을 따라야 하므로 옮기지 않는다. */
|
|
52
|
-
purpose?: string
|
|
53
|
-
/** 지금 실행 중인가 — 시간대 변화는 재기동 뒤에 커널에 실린다. */
|
|
54
|
-
running?: boolean
|
|
55
|
-
/** 두 공간의 시간대(IANA). 다르면 앞으로의 시각 해석이 달라진다. */
|
|
56
|
-
fromTimezone?: string
|
|
57
|
-
toTimezone?: string
|
|
58
|
-
/** 이 트윈의 로케이션들이 소속으로 가리키는 구역 id 들(중복 포함 가능). */
|
|
59
|
-
areaRefs?: readonly (string | undefined | null)[]
|
|
60
|
-
/** 옮겨 갈 공간에 있는 구역 id 들. */
|
|
61
|
-
toAreaIds?: readonly string[]
|
|
62
|
-
/** 옛 공간의 표현 수 — 그 표현의 폴리곤이 이 트윈을 가리키고 있었을 수 있다. */
|
|
63
|
-
fromRepresentationCount?: number
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface MoveSpaceJudgement {
|
|
67
|
-
/** 있으면 옮기지 않는다. */
|
|
68
|
-
refusal?: MoveSpaceRefusal
|
|
69
|
-
/** 옮기되 함께 알린다. 비어 있으면 잃는 것이 없다. */
|
|
70
|
-
warnings: MoveSpaceWarning[]
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** 옮겨도 되나 — 되면 무엇을 알려야 하나. */
|
|
74
|
-
export function judgeMoveTwinSpace(input: MoveSpaceInput): MoveSpaceJudgement {
|
|
75
|
-
const to = (input.toSpaceId ?? '').trim()
|
|
76
|
-
const from = (input.fromSpaceId ?? '').trim()
|
|
77
|
-
|
|
78
|
-
if (!input.instanceId) {
|
|
79
|
-
return {
|
|
80
|
-
refusal: { code: 'twin-not-found', message: 'no such twin in this tenant' },
|
|
81
|
-
warnings: []
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (!to || !input.toSpaceExists) {
|
|
85
|
-
return {
|
|
86
|
-
refusal: {
|
|
87
|
-
code: 'space-not-found',
|
|
88
|
-
params: { spaceId: to },
|
|
89
|
-
message: `space "${to}" not found — cannot move a twin into a space that does not exist`
|
|
90
|
-
},
|
|
91
|
-
warnings: []
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (from && from === to) {
|
|
95
|
-
return {
|
|
96
|
-
refusal: {
|
|
97
|
-
code: 'same-space',
|
|
98
|
-
params: { spaceId: to },
|
|
99
|
-
message: `twin "${input.instanceId}" is already in space "${to}"`
|
|
100
|
-
},
|
|
101
|
-
warnings: []
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
/* 벤치 사본은 "이 공장이 이만큼 커지면" 을 재는 사본이라 원본의 현장에 매여 있다. 옮기면 그 측정이
|
|
105
|
-
무엇의 측정인지 말할 수 없게 된다 — 사본을 옮기는 대신 원본을 옮기고 사본을 다시 뜬다. */
|
|
106
|
-
if (input.purpose === 'bench') {
|
|
107
|
-
return {
|
|
108
|
-
refusal: {
|
|
109
|
-
code: 'bench-copy',
|
|
110
|
-
params: { instanceId: input.instanceId },
|
|
111
|
-
message: `twin "${input.instanceId}" is a bench copy — move its source twin instead`
|
|
112
|
-
},
|
|
113
|
-
warnings: []
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const warnings: MoveSpaceWarning[] = []
|
|
118
|
-
|
|
119
|
-
/* 로케이션의 구역 소속 — 구역은 공간의 것이라 새 공간에 같은 id 가 없으면 소속이 끊긴다.
|
|
120
|
-
막지는 않는다(새 공간에서 구역을 다시 그리는 것이 정상 경로다). 다만 몇 개가 끊기는지 말한다. */
|
|
121
|
-
const refs = [...new Set((input.areaRefs ?? []).filter((x): x is string => !!x && !!x.trim()))]
|
|
122
|
-
const have = new Set(input.toAreaIds ?? [])
|
|
123
|
-
const orphaned = refs.filter(r => !have.has(r)).sort()
|
|
124
|
-
if (orphaned.length) {
|
|
125
|
-
warnings.push({
|
|
126
|
-
code: 'areas-left-behind',
|
|
127
|
-
params: { count: orphaned.length, areas: orphaned.slice(0, 5).join(', ') },
|
|
128
|
-
message: `${orphaned.length} area reference(s) do not exist in the target space — those locations lose their grouping: ${orphaned
|
|
129
|
-
.slice(0, 5)
|
|
130
|
-
.join(', ')}`
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/* 시간대 — 공간이 정하고 커널이 분 오프셋으로 받는다. 다르면 같은 저널이 다른 시각으로 읽힌다. */
|
|
135
|
-
const tzFrom = (input.fromTimezone ?? '').trim()
|
|
136
|
-
const tzTo = (input.toTimezone ?? '').trim()
|
|
137
|
-
if (tzFrom !== tzTo) {
|
|
138
|
-
warnings.push({
|
|
139
|
-
code: 'timezone-differs',
|
|
140
|
-
params: { from: tzFrom || '—', to: tzTo || '—' },
|
|
141
|
-
message: `time zone changes from "${tzFrom || 'unset'}" to "${tzTo || 'unset'}" — shift boundaries and day buckets will read differently`
|
|
142
|
-
})
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/* 옛 공간의 표현 — 폴리곤 바인딩이 이 트윈의 로케이션·그룹을 가리키고 있었을 수 있다. 표현은
|
|
146
|
-
공간에 남으므로, 그 화면에서 이 트윈이 사라진다. 몇 개가 남는지 말해 두면 사람이 찾아갈 수 있다. */
|
|
147
|
-
if ((input.fromRepresentationCount ?? 0) > 0) {
|
|
148
|
-
warnings.push({
|
|
149
|
-
code: 'representations-left-behind',
|
|
150
|
-
params: { count: input.fromRepresentationCount as number, spaceId: from || '—' },
|
|
151
|
-
message: `${input.fromRepresentationCount} representation(s) stay with space "${from}" — bindings that pointed at this twin will no longer resolve there`
|
|
152
|
-
})
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/* 실행 중 — 소속은 즉시 바뀌지만 시간대는 커널을 세울 때 실린다. 시간대가 같으면 말할 것이 없다. */
|
|
156
|
-
if (input.running && tzFrom !== tzTo) {
|
|
157
|
-
warnings.push({
|
|
158
|
-
code: 'running',
|
|
159
|
-
params: { instanceId: input.instanceId },
|
|
160
|
-
message: `twin "${input.instanceId}" is running — the new time zone applies after it is restarted`
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return { warnings }
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/*
|
|
168
|
-
* ── 현장에서 떼기 (2026-08-13) ──────────────────────────────────────────────
|
|
169
|
-
*
|
|
170
|
-
* 더하기·옮기기만 있으면 잘못 넣은 것을 되돌릴 수 없다. 떼기는 "어느 현장에도 속하지 않음" 으로
|
|
171
|
-
* 되돌리는 일이고, 데이터 모델이 그 상태를 이미 허용한다(`TwinInstance.spaceId` 는 선택 컬럼).
|
|
172
|
-
*
|
|
173
|
-
* 떼면 무엇이 달라지나 — 옮기기와 같은 규칙이지만 **갈 곳이 없다**는 점이 다르다:
|
|
174
|
-
* · 저널·로케이션·설비는 그대로 트윈에 남는다(잃는 것 없음).
|
|
175
|
-
* · 구역·표현은 옛 현장에 남는다 → 그 화면에서 이 트윈이 사라진다.
|
|
176
|
-
* · **볼 무대가 없어진다** — 현장 현황(지도·보드)은 현장의 표현으로 그리므로, 뗀 트윈은 목록과
|
|
177
|
-
* 조회 화면에서만 보인다. 이것을 말하지 않으면 사용자는 트윈이 고장 났다고 읽는다.
|
|
178
|
-
* · 시간 기준(`utcOffsetMinutes`)은 **옛 현장의 것으로 남는다.** 지우면 알리지 않고 UTC 로 읽히므로
|
|
179
|
-
* 그쪽이 더 위험하다 — 남기고 그 사실을 말한다.
|
|
180
|
-
*/
|
|
181
|
-
|
|
182
|
-
/** 뗄 수 없는 이유 — 언어 중립 코드. */
|
|
183
|
-
export type DetachSpaceRefusalCode = 'twin-not-found' | 'no-space' | 'bench-copy'
|
|
184
|
-
|
|
185
|
-
/** 떼도 되지만 알아야 하는 것. */
|
|
186
|
-
export type DetachSpaceWarningCode = 'no-stage' | 'representations-left-behind' | 'timebase-kept'
|
|
187
|
-
|
|
188
|
-
export type DetachSpaceRefusal = MoveSpaceNote<DetachSpaceRefusalCode>
|
|
189
|
-
export type DetachSpaceWarning = MoveSpaceNote<DetachSpaceWarningCode>
|
|
190
|
-
|
|
191
|
-
export interface DetachSpaceInput {
|
|
192
|
-
instanceId?: string
|
|
193
|
-
/** 지금 속한 공간 — 없으면 뗄 것이 없다. */
|
|
194
|
-
fromSpaceId?: string
|
|
195
|
-
purpose?: string
|
|
196
|
-
/** 옛 공간의 표현 수. */
|
|
197
|
-
fromRepresentationCount?: number
|
|
198
|
-
/** 옛 공간의 시간대 — 있으면 그 기준이 model 에 남는다. */
|
|
199
|
-
fromTimezone?: string
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export interface DetachSpaceJudgement {
|
|
203
|
-
refusal?: DetachSpaceRefusal
|
|
204
|
-
warnings: DetachSpaceWarning[]
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/** 떼도 되나 — 되면 무엇을 알려야 하나. */
|
|
208
|
-
export function judgeDetachTwinSpace(input: DetachSpaceInput): DetachSpaceJudgement {
|
|
209
|
-
const from = (input.fromSpaceId ?? '').trim()
|
|
210
|
-
|
|
211
|
-
if (!input.instanceId) {
|
|
212
|
-
return { refusal: { code: 'twin-not-found', message: 'no such twin in this tenant' }, warnings: [] }
|
|
213
|
-
}
|
|
214
|
-
if (!from) {
|
|
215
|
-
return {
|
|
216
|
-
refusal: {
|
|
217
|
-
code: 'no-space',
|
|
218
|
-
params: { instanceId: input.instanceId },
|
|
219
|
-
message: `twin "${input.instanceId}" is not on any site — nothing to detach`
|
|
220
|
-
},
|
|
221
|
-
warnings: []
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
/* 벤치 사본은 원본의 현장을 따라야 측정이 무엇의 측정인지 말할 수 있다(옮기기와 같은 이유). */
|
|
225
|
-
if (input.purpose === 'bench') {
|
|
226
|
-
return {
|
|
227
|
-
refusal: {
|
|
228
|
-
code: 'bench-copy',
|
|
229
|
-
params: { instanceId: input.instanceId },
|
|
230
|
-
message: `twin "${input.instanceId}" is a bench copy — it must stay on the site it measures`
|
|
231
|
-
},
|
|
232
|
-
warnings: []
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const warnings: DetachSpaceWarning[] = [
|
|
237
|
-
{
|
|
238
|
-
code: 'no-stage',
|
|
239
|
-
params: { instanceId: input.instanceId },
|
|
240
|
-
message: `twin "${input.instanceId}" will have no site to be drawn on — it stays visible in lists and inspection only`
|
|
241
|
-
}
|
|
242
|
-
]
|
|
243
|
-
|
|
244
|
-
if ((input.fromRepresentationCount ?? 0) > 0) {
|
|
245
|
-
warnings.push({
|
|
246
|
-
code: 'representations-left-behind',
|
|
247
|
-
params: { count: input.fromRepresentationCount as number, spaceId: from },
|
|
248
|
-
message: `${input.fromRepresentationCount} representation(s) stay with space "${from}" — bindings that pointed at this twin will no longer resolve there`
|
|
249
|
-
})
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const tz = (input.fromTimezone ?? '').trim()
|
|
253
|
-
if (tz) {
|
|
254
|
-
warnings.push({
|
|
255
|
-
code: 'timebase-kept',
|
|
256
|
-
params: { timezone: tz },
|
|
257
|
-
message: `the time base stays as "${tz}" (the site it came from) — clearing it would silently read times as UTC`
|
|
258
|
-
})
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return { warnings }
|
|
262
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* 표현이 무엇을 위한 것인가 — **닫힌 목록** (2026-08-27 · 사용자 지시).
|
|
3
|
-
*
|
|
4
|
-
* index 표현 목록에 나온다. 비어 있으면 이것이다(흔한 쪽을 기본으로 둔다)
|
|
5
|
-
* derived 다른 표현에서 열린다(팝업·드릴 대상). 목록에서는 접어 세어 보인다 — 감추지 않는다
|
|
6
|
-
*
|
|
7
|
-
* 열어 두면 넣는 쪽마다 다른 이름을 쓰고, 그러면 화면이 어느 이름을 목록에 넣어야 하는지 알 수 없다.
|
|
8
|
-
* 늘려야 하면 이 목록에 더한다.
|
|
9
|
-
*
|
|
10
|
-
* ── 왜 엔티티가 아니라 이 파일인가 ──────────────────────────────────────────
|
|
11
|
-
* 엔티티에는 데코레이터가 있어서 테스트가 그 파일을 읽을 수 없다(런타임의 타입 제거가 데코레이터를
|
|
12
|
-
* 파싱하지 못한다). 값으로 확인해야 하는 것은 데코레이터 없는 파일에 둔다.
|
|
13
|
-
*/
|
|
14
|
-
export const REPRESENTATION_ROLES = ['index', 'derived'] as const
|
|
15
|
-
export type RepresentationRole = (typeof REPRESENTATION_ROLES)[number]
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* 공간 ↔ 트윈 ↔ 가시화 정합성 — **순수**. 세 축이 서로 어긋난 자리를 찾는다.
|
|
3
|
-
*
|
|
4
|
-
* ── 왜 있나 (2026-08-13) ────────────────────────────────────────────────────
|
|
5
|
-
* 이 셋은 서로를 id 로만 가리킨다. 참조 무결성을 DB 가 지켜 주지 않는 지점이 많다:
|
|
6
|
-
* 공간·구역은 공간에 매이고, 로케이션·설비는 트윈에 매이고, 폴리곤은 **양쪽을 가리킨다.**
|
|
7
|
-
* 그래서 트윈을 옮기거나 떼거나(2026-08-13 추가) 원본을 다시 읽으면, 아무 오류 없이 **가리킬 것이
|
|
8
|
-
* 없는 도형**과 **소속 없는 로케이션**이 남는다. 증상은 "지도가 비었다" 뿐이고 원인은 화면에 없다.
|
|
9
|
-
*
|
|
10
|
-
* 그 어긋남을 사람이 눈으로 맞추고 있었다(spaceId 를 목록에서 대조). 기계가 대신 본다.
|
|
11
|
-
*
|
|
12
|
-
* ── 무엇을 사실로 보나 ─────────────────────────────────────────────────────
|
|
13
|
-
* 판정은 **조회 결과만** 받는다(DB 를 물지 않는다). 그래서 단위테스트로 전부 부를 수 있고, 호출측은
|
|
14
|
-
* 사실을 모으는 일만 한다. 각 발견은 언어 중립 코드 + 파라미터이고, 화면이 사람 말을 만든다.
|
|
15
|
-
*
|
|
16
|
-
* ── 심각도를 가른다 ────────────────────────────────────────────────────────
|
|
17
|
-
* `broken` 은 무언가 이미 보이지 않는 상태다(가리킬 대상이 없다). `warn` 은 아직 보이지만 뜻이
|
|
18
|
-
* 흐려진 상태다(소속 없음·대표 없음). 섞으면 사람이 무엇을 먼저 볼지 정할 수 없다.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
export type SpaceIntegrityCode =
|
|
22
|
-
/** 트윈이 없는 공간을 가리킨다 — 그 트윈은 무대가 사라졌다. */
|
|
23
|
-
| 'twin-space-missing'
|
|
24
|
-
/** 레지스트리와 model 의 공간이 다르다 — 어느 쪽이 사실인지 알 수 없다. */
|
|
25
|
-
| 'twin-space-mismatch'
|
|
26
|
-
/** 폴리곤이 이 공간에 없는 구역을 가리킨다. */
|
|
27
|
-
| 'polygon-area-missing'
|
|
28
|
-
/** 폴리곤이 이 공간에 사는 어느 트윈에도 없는 로케이션·설비를 가리킨다. */
|
|
29
|
-
| 'polygon-target-missing'
|
|
30
|
-
/** 로케이션이 이 공간에 없는 구역에 소속되어 있다. */
|
|
31
|
-
| 'location-area-missing'
|
|
32
|
-
/** 대표 표현이 이 공간의 표현이 아니다. */
|
|
33
|
-
| 'primary-representation-missing'
|
|
34
|
-
/** 보드 표현이 보드를 가리키지 않는다(또는 없는 보드를 가리킨다). */
|
|
35
|
-
| 'board-representation-unbound'
|
|
36
|
-
/** 표현이 하나도 없는 공간에 트윈이 산다 — 볼 화면이 없다. */
|
|
37
|
-
| 'space-without-representation'
|
|
38
|
-
/** 어느 공간에도 속하지 않은 트윈 — 뗀 결과일 수 있다(사실이면 정상). */
|
|
39
|
-
| 'twin-without-space'
|
|
40
|
-
/**
|
|
41
|
-
* 이 트윈이 **담을 줄 모르는 어휘**를 받고 있다 — 리비전은 오르는데 상태가 채워지지 않는다.
|
|
42
|
-
*
|
|
43
|
-
* 커널은 모르는 `eventType` 을 버리고(전방 호환) 종류별로 센다(`state.unhandled`). 그 수가 0이
|
|
44
|
-
* 아니면 둘 중 하나다: 커넥터가 엉뚱한 트윈에 붙었거나(예: `energy.*` 가 창고 트윈으로), 커널이
|
|
45
|
-
* 낡아 새 어휘를 모른다. 둘 다 사람이 손봐야 하는 것이고, 알리지 않고 두면 「정상인데 빈」 트윈이 된다.
|
|
46
|
-
*/
|
|
47
|
-
| 'twin-unhandled-vocabulary'
|
|
48
|
-
|
|
49
|
-
export type SpaceIntegritySeverity = 'broken' | 'warn'
|
|
50
|
-
|
|
51
|
-
export interface SpaceIntegrityFinding {
|
|
52
|
-
code: SpaceIntegrityCode
|
|
53
|
-
severity: SpaceIntegritySeverity
|
|
54
|
-
/** 어디의 문제인가 — 화면이 그 자리로 데려갈 수 있게. */
|
|
55
|
-
spaceId?: string
|
|
56
|
-
instanceId?: string
|
|
57
|
-
representationId?: string
|
|
58
|
-
params?: Record<string, string | number>
|
|
59
|
-
/** 영어 canonical — 로그·폴백. */
|
|
60
|
-
message: string
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/* ── 입력(조회 결과) ──────────────────────────────────────────────────────── */
|
|
64
|
-
|
|
65
|
-
export interface IntegritySpace {
|
|
66
|
-
spaceId: string
|
|
67
|
-
primaryRepresentationId?: string | null
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface IntegrityInstance {
|
|
71
|
-
instanceId: string
|
|
72
|
-
/** 레지스트리 컬럼. */
|
|
73
|
-
spaceId?: string | null
|
|
74
|
-
/** 저장된 model 의 공간 — 레지스트리와 같아야 한다. */
|
|
75
|
-
modelSpaceId?: string | null
|
|
76
|
-
purpose?: string | null
|
|
77
|
-
/** 이 트윈의 로케이션 id 들. */
|
|
78
|
-
locationIds?: readonly string[]
|
|
79
|
-
/** 이 트윈의 설비 id 들. */
|
|
80
|
-
equipmentIds?: readonly string[]
|
|
81
|
-
/** 로케이션의 소속 구역 id 들(중복 가능). */
|
|
82
|
-
areaRefs?: readonly (string | undefined | null)[]
|
|
83
|
-
/**
|
|
84
|
-
* 커널이 담을 줄 몰라 버린 사건들 — 실행 중인 트윈의 상태에서 온다(`state.unhandled`).
|
|
85
|
-
*
|
|
86
|
-
* 정지한 트윈에서는 알 수 없으므로 `undefined` 다 — **없는 것과 모르는 것을 구별한다**(빈 배열을
|
|
87
|
-
* 넣으면 「받은 것이 없다」는 사실 주장이 되고, 그것은 우리가 확인한 바가 아니다).
|
|
88
|
-
*/
|
|
89
|
-
unhandled?: readonly { eventType: string; count: number }[]
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export interface IntegrityRepresentation {
|
|
93
|
-
id: string
|
|
94
|
-
spaceId: string
|
|
95
|
-
type: string
|
|
96
|
-
/** 보드 표현이면 보드 id. */
|
|
97
|
-
boardId?: string | null
|
|
98
|
-
/** 폴리곤 바인딩들. */
|
|
99
|
-
polygons?: readonly IntegrityPolygon[]
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export interface IntegrityPolygon {
|
|
103
|
-
id?: string
|
|
104
|
-
/** 논리 구역 바인딩(그룹). */
|
|
105
|
-
groupId?: string | null
|
|
106
|
-
/** 개체 바인딩 — 로케이션 또는 설비. */
|
|
107
|
-
targetKind?: 'location' | 'equipment' | null
|
|
108
|
-
targetId?: string | null
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export interface SpaceIntegrityInput {
|
|
112
|
-
spaces: readonly IntegritySpace[]
|
|
113
|
-
instances: readonly IntegrityInstance[]
|
|
114
|
-
representations: readonly IntegrityRepresentation[]
|
|
115
|
-
/** 공간별 구역 id 들. */
|
|
116
|
-
areasBySpace: Readonly<Record<string, readonly string[]>>
|
|
117
|
-
/** 존재하는 보드 id 들 — 보드 표현이 실제 보드를 가리키는지 본다. */
|
|
118
|
-
boardIds?: readonly string[]
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** 세 축을 맞대어 어긋난 자리를 모두 낸다. 비어 있으면 정합하다. */
|
|
122
|
-
export function checkSpaceIntegrity(input: SpaceIntegrityInput): SpaceIntegrityFinding[] {
|
|
123
|
-
const out: SpaceIntegrityFinding[] = []
|
|
124
|
-
const spaceIds = new Set(input.spaces.map(s => s.spaceId))
|
|
125
|
-
const areasOf = (spaceId: string) => new Set(input.areasBySpace[spaceId] ?? [])
|
|
126
|
-
const repsOf = (spaceId: string) => input.representations.filter(r => r.spaceId === spaceId)
|
|
127
|
-
const boards = new Set(input.boardIds ?? [])
|
|
128
|
-
|
|
129
|
-
/* 벤치 사본은 측정용 사본이라 이 검사의 대상이 아니다 — 사본의 공간은 잠깐 살고 지워진다. */
|
|
130
|
-
const instances = input.instances.filter(i => i.purpose !== 'bench')
|
|
131
|
-
|
|
132
|
-
/* ── 트윈 → 공간 ─────────────────────────────────────────────────────── */
|
|
133
|
-
for (const t of instances) {
|
|
134
|
-
const sid = (t.spaceId ?? '').trim()
|
|
135
|
-
const msid = (t.modelSpaceId ?? '').trim()
|
|
136
|
-
|
|
137
|
-
if (!sid) {
|
|
138
|
-
out.push({
|
|
139
|
-
code: 'twin-without-space',
|
|
140
|
-
severity: 'warn',
|
|
141
|
-
instanceId: t.instanceId,
|
|
142
|
-
message: `twin "${t.instanceId}" is on no site — it has no map or board to be drawn on`
|
|
143
|
-
})
|
|
144
|
-
} else if (!spaceIds.has(sid)) {
|
|
145
|
-
out.push({
|
|
146
|
-
code: 'twin-space-missing',
|
|
147
|
-
severity: 'broken',
|
|
148
|
-
instanceId: t.instanceId,
|
|
149
|
-
spaceId: sid,
|
|
150
|
-
message: `twin "${t.instanceId}" points at site "${sid}" which does not exist`
|
|
151
|
-
})
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/* 두 곳이 어긋나면 어느 쪽이 사실인지 알 수 없다 — 보드는 model 을, 목록은 컬럼을 읽는다. */
|
|
155
|
-
if (sid !== msid) {
|
|
156
|
-
out.push({
|
|
157
|
-
code: 'twin-space-mismatch',
|
|
158
|
-
severity: 'broken',
|
|
159
|
-
instanceId: t.instanceId,
|
|
160
|
-
spaceId: sid || undefined,
|
|
161
|
-
params: { registry: sid || '—', model: msid || '—' },
|
|
162
|
-
message: `twin "${t.instanceId}" registry site "${sid || 'none'}" differs from its model site "${msid || 'none'}"`
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/* 로케이션의 소속 구역은 **트윈이 속한 공간**의 것이어야 한다. */
|
|
167
|
-
if (sid && spaceIds.has(sid)) {
|
|
168
|
-
const have = areasOf(sid)
|
|
169
|
-
const refs = [...new Set((t.areaRefs ?? []).filter((x): x is string => !!x && !!x.trim()))]
|
|
170
|
-
const missing = refs.filter(r => !have.has(r)).sort()
|
|
171
|
-
if (missing.length) {
|
|
172
|
-
out.push({
|
|
173
|
-
code: 'location-area-missing',
|
|
174
|
-
severity: 'warn',
|
|
175
|
-
instanceId: t.instanceId,
|
|
176
|
-
spaceId: sid,
|
|
177
|
-
params: { count: missing.length, areas: missing.slice(0, 5).join(', ') },
|
|
178
|
-
message: `${missing.length} area(s) referenced by locations of "${t.instanceId}" do not exist in site "${sid}": ${missing
|
|
179
|
-
.slice(0, 5)
|
|
180
|
-
.join(', ')}`
|
|
181
|
-
})
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/*
|
|
186
|
-
* 어휘가 맞는가 — 저널이 들어오는데 상태가 채워지지 않는 경우를 잡는다.
|
|
187
|
-
*
|
|
188
|
-
* `undefined` 는 「모른다」다(정지한 트윈). 세지 않는다 — 확인하지 않은 것을 정합으로도, 결함으로도
|
|
189
|
-
* 세지 않는 것이 이 하네스의 규율이다.
|
|
190
|
-
*/
|
|
191
|
-
if (t.unhandled?.length) {
|
|
192
|
-
const total = t.unhandled.reduce((n, u) => n + u.count, 0)
|
|
193
|
-
const kinds = [...t.unhandled].sort((a, b) => b.count - a.count)
|
|
194
|
-
out.push({
|
|
195
|
-
code: 'twin-unhandled-vocabulary',
|
|
196
|
-
severity: 'warn',
|
|
197
|
-
instanceId: t.instanceId,
|
|
198
|
-
spaceId: sid || undefined,
|
|
199
|
-
params: { events: total, kinds: kinds.length, types: kinds.slice(0, 3).map(u => u.eventType).join(', ') },
|
|
200
|
-
message: `twin "${t.instanceId}" received ${total} event(s) of ${kinds.length} type(s) its kernel does not handle: ${kinds
|
|
201
|
-
.slice(0, 3)
|
|
202
|
-
.map(u => u.eventType)
|
|
203
|
-
.join(', ')}`
|
|
204
|
-
})
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/* ── 공간 → 가시화 ───────────────────────────────────────────────────── */
|
|
209
|
-
for (const s of input.spaces) {
|
|
210
|
-
const reps = repsOf(s.spaceId)
|
|
211
|
-
const livesHere = instances.filter(t => (t.spaceId ?? '') === s.spaceId)
|
|
212
|
-
|
|
213
|
-
/* 트윈이 사는데 표현이 없으면 볼 화면이 없다. 트윈이 없는 빈 현장은 정상이므로 세지 않는다. */
|
|
214
|
-
if (livesHere.length && !reps.length) {
|
|
215
|
-
out.push({
|
|
216
|
-
code: 'space-without-representation',
|
|
217
|
-
severity: 'warn',
|
|
218
|
-
spaceId: s.spaceId,
|
|
219
|
-
params: { twins: livesHere.length },
|
|
220
|
-
message: `site "${s.spaceId}" has ${livesHere.length} twin(s) but no representation — there is nothing to draw them on`
|
|
221
|
-
})
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const primary = (s.primaryRepresentationId ?? '').trim()
|
|
225
|
-
if (primary && !reps.some(r => r.id === primary)) {
|
|
226
|
-
out.push({
|
|
227
|
-
code: 'primary-representation-missing',
|
|
228
|
-
severity: 'broken',
|
|
229
|
-
spaceId: s.spaceId,
|
|
230
|
-
params: { representationId: primary },
|
|
231
|
-
message: `site "${s.spaceId}" points at primary representation "${primary}" which is not one of its representations`
|
|
232
|
-
})
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/* ── 가시화 → 공간·트윈 ─────────────────────────────────────────────── */
|
|
237
|
-
for (const rep of input.representations) {
|
|
238
|
-
const have = areasOf(rep.spaceId)
|
|
239
|
-
/* 이 공간에 사는 트윈들의 개체 id — 폴리곤이 가리킬 수 있는 전부. */
|
|
240
|
-
const here = instances.filter(t => (t.spaceId ?? '') === rep.spaceId)
|
|
241
|
-
const locationIds = new Set(here.flatMap(t => [...(t.locationIds ?? [])]))
|
|
242
|
-
const equipmentIds = new Set(here.flatMap(t => [...(t.equipmentIds ?? [])]))
|
|
243
|
-
|
|
244
|
-
if (rep.type === 'board' && !(rep.boardId && boards.has(rep.boardId))) {
|
|
245
|
-
out.push({
|
|
246
|
-
code: 'board-representation-unbound',
|
|
247
|
-
severity: 'broken',
|
|
248
|
-
spaceId: rep.spaceId,
|
|
249
|
-
representationId: rep.id,
|
|
250
|
-
params: { boardId: rep.boardId ?? '—' },
|
|
251
|
-
message: `board representation "${rep.id}" of site "${rep.spaceId}" does not point at an existing board (${rep.boardId ?? 'none'})`
|
|
252
|
-
})
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
for (const p of rep.polygons ?? []) {
|
|
256
|
-
const gid = (p.groupId ?? '').trim()
|
|
257
|
-
if (gid && !have.has(gid)) {
|
|
258
|
-
out.push({
|
|
259
|
-
code: 'polygon-area-missing',
|
|
260
|
-
severity: 'broken',
|
|
261
|
-
spaceId: rep.spaceId,
|
|
262
|
-
representationId: rep.id,
|
|
263
|
-
params: { areaId: gid, polygonId: p.id ?? '—' },
|
|
264
|
-
message: `a polygon of representation "${rep.id}" binds area "${gid}" which does not exist in site "${rep.spaceId}"`
|
|
265
|
-
})
|
|
266
|
-
}
|
|
267
|
-
const tid = (p.targetId ?? '').trim()
|
|
268
|
-
if (tid && p.targetKind) {
|
|
269
|
-
const pool = p.targetKind === 'equipment' ? equipmentIds : locationIds
|
|
270
|
-
if (!pool.has(tid)) {
|
|
271
|
-
out.push({
|
|
272
|
-
code: 'polygon-target-missing',
|
|
273
|
-
severity: 'broken',
|
|
274
|
-
spaceId: rep.spaceId,
|
|
275
|
-
representationId: rep.id,
|
|
276
|
-
params: { kind: p.targetKind, targetId: tid, polygonId: p.id ?? '—' },
|
|
277
|
-
message: `a polygon of representation "${rep.id}" binds ${p.targetKind} "${tid}", which no twin on site "${rep.spaceId}" has`
|
|
278
|
-
})
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return out
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/** 심각한 것부터 — 화면이 정렬을 다시 정하지 않게 한 곳에서 정한다. */
|
|
288
|
-
export function sortFindings(findings: readonly SpaceIntegrityFinding[]): SpaceIntegrityFinding[] {
|
|
289
|
-
const rank = (s: SpaceIntegritySeverity) => (s === 'broken' ? 0 : 1)
|
|
290
|
-
return [...findings].sort(
|
|
291
|
-
(a, b) => rank(a.severity) - rank(b.severity) || a.code.localeCompare(b.code) || (a.spaceId ?? '').localeCompare(b.spaceId ?? '')
|
|
292
|
-
)
|
|
293
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
|
2
|
-
import { ObjectType, Field, ID } from 'type-graphql'
|
|
3
|
-
|
|
4
|
-
import { Domain, ScalarObject } from '@things-factory/shell'
|
|
5
|
-
|
|
6
|
-
import { TwinSpace } from './twin-space.js'
|
|
7
|
-
|
|
8
|
-
/*
|
|
9
|
-
* TwinArea — 공간의 **논리적 구역(계층)**. 표현 무관(ISA-95 building→floor→zone).
|
|
10
|
-
* area 단일화(space #2): deprecated `TwinSpace.content.areas`(blob) 를 정규화한 영구 자리.
|
|
11
|
-
* 표현별 폴리곤(`TwinSpaceArea`)은 이 논리 구역을 `areaId` 로 참조한다(P2에서 binding.groupId→areaId 전환).
|
|
12
|
-
* 안전 순서: P1=신설+인제스트 dual-write(content.areas 병행 유지) → P2 소비처 전환 → P3 blob 제거.
|
|
13
|
-
*/
|
|
14
|
-
@Entity()
|
|
15
|
-
@Index('ix_twin_area_0', (e: TwinArea) => [e.domain, e.space, e.areaId], { unique: true })
|
|
16
|
-
@ObjectType({ description: 'A logical (representation-agnostic) area in a space hierarchy (building/floor/zone). Polygons reference it by areaId.' })
|
|
17
|
-
export class TwinArea {
|
|
18
|
-
@PrimaryGeneratedColumn('uuid')
|
|
19
|
-
@Field(type => ID)
|
|
20
|
-
readonly id: string
|
|
21
|
-
|
|
22
|
-
@ManyToOne(type => Domain)
|
|
23
|
-
@Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })
|
|
24
|
-
domain?: Domain
|
|
25
|
-
|
|
26
|
-
@RelationId((e: TwinArea) => e.domain)
|
|
27
|
-
domainId?: string
|
|
28
|
-
|
|
29
|
-
@ManyToOne(type => TwinSpace)
|
|
30
|
-
@Field(type => TwinSpace, { nullable: true, description: 'Owning space.' })
|
|
31
|
-
space?: TwinSpace
|
|
32
|
-
|
|
33
|
-
@RelationId((e: TwinArea) => e.space)
|
|
34
|
-
spaceRowId?: string
|
|
35
|
-
|
|
36
|
-
@Column()
|
|
37
|
-
@Field({ description: 'Stable logical area id (unique within a space). Polygons reference this via areaId.' })
|
|
38
|
-
areaId: string
|
|
39
|
-
|
|
40
|
-
@Column({ nullable: true })
|
|
41
|
-
@Field({ nullable: true, description: 'Area name.' })
|
|
42
|
-
name?: string
|
|
43
|
-
|
|
44
|
-
@Column({ nullable: true })
|
|
45
|
-
@Field({ nullable: true, description: 'Region type (building/floor/zone/yard/dock…).' })
|
|
46
|
-
type?: string
|
|
47
|
-
|
|
48
|
-
@Column({ nullable: true })
|
|
49
|
-
@Field({ nullable: true, description: 'Parent logical area id (hierarchy). Root areas have none.' })
|
|
50
|
-
parentId?: string
|
|
51
|
-
|
|
52
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
53
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Layout footprint hint { x, y, w, h } in design coords (representation-agnostic).' })
|
|
54
|
-
layout?: any
|
|
55
|
-
|
|
56
|
-
@CreateDateColumn()
|
|
57
|
-
@Field({ nullable: true })
|
|
58
|
-
createdAt?: Date
|
|
59
|
-
|
|
60
|
-
@UpdateDateColumn()
|
|
61
|
-
@Field({ nullable: true })
|
|
62
|
-
updatedAt?: Date
|
|
63
|
-
}
|