@things-factory/headless-twin 10.0.14 → 10.0.17
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/dist-server/engine/attention-digest.d.ts +4 -4
- package/dist-server/engine/attention-digest.js +7 -7
- package/dist-server/engine/attention-digest.js.map +1 -1
- package/dist-server/engine/canonical-ingest.d.ts +11 -2
- package/dist-server/engine/canonical-ingest.js +137 -8
- package/dist-server/engine/canonical-ingest.js.map +1 -1
- package/dist-server/engine/command-routing.js +1 -1
- package/dist-server/engine/command-routing.js.map +1 -1
- package/dist-server/engine/declared-stimulus.js +1 -1
- package/dist-server/engine/declared-stimulus.js.map +1 -1
- package/dist-server/engine/energy-topology.js +1 -1
- package/dist-server/engine/energy-topology.js.map +1 -1
- package/dist-server/engine/ingest-dedupe.d.ts +38 -0
- package/dist-server/engine/ingest-dedupe.js +145 -0
- package/dist-server/engine/ingest-dedupe.js.map +1 -0
- package/dist-server/engine/ingest-health.d.ts +124 -9
- package/dist-server/engine/ingest-health.js +169 -15
- package/dist-server/engine/ingest-health.js.map +1 -1
- package/dist-server/engine/integration-probes.d.ts +3 -3
- package/dist-server/engine/integration-probes.js +6 -6
- package/dist-server/engine/integration-probes.js.map +1 -1
- package/dist-server/engine/kpi-baseline.js +4 -4
- package/dist-server/engine/kpi-baseline.js.map +1 -1
- package/dist-server/engine/kpi-fold.d.ts +122 -12
- package/dist-server/engine/kpi-fold.js +247 -18
- package/dist-server/engine/kpi-fold.js.map +1 -1
- package/dist-server/engine/kpi-query.d.ts +11 -11
- package/dist-server/engine/kpi-query.js +185 -28
- package/dist-server/engine/kpi-query.js.map +1 -1
- package/dist-server/engine/live-feed-registry.d.ts +1 -1
- package/dist-server/engine/live-feed-registry.js +1 -1
- package/dist-server/engine/live-feed-registry.js.map +1 -1
- package/dist-server/engine/load-meter.d.ts +1 -1
- package/dist-server/engine/load-meter.js.map +1 -1
- package/dist-server/engine/local-declarations.d.ts +7 -7
- package/dist-server/engine/local-declarations.js +9 -9
- package/dist-server/engine/local-declarations.js.map +1 -1
- package/dist-server/engine/log.d.ts +1 -1
- package/dist-server/engine/log.js +1 -1
- package/dist-server/engine/log.js.map +1 -1
- package/dist-server/engine/measured-estimator.js +1 -1
- package/dist-server/engine/measured-estimator.js.map +1 -1
- package/dist-server/engine/measured-yield.js +1 -1
- package/dist-server/engine/measured-yield.js.map +1 -1
- package/dist-server/engine/model-basis.d.ts +1 -1
- package/dist-server/engine/model-basis.js +1 -1
- package/dist-server/engine/model-basis.js.map +1 -1
- package/dist-server/engine/model-gap.d.ts +3 -3
- package/dist-server/engine/model-gap.js +1 -1
- package/dist-server/engine/model-gap.js.map +1 -1
- package/dist-server/engine/model-vocabulary.js +1 -1
- package/dist-server/engine/model-vocabulary.js.map +1 -1
- package/dist-server/engine/oee-accumulator.d.ts +4 -4
- package/dist-server/engine/oee-accumulator.js +3 -3
- package/dist-server/engine/oee-accumulator.js.map +1 -1
- package/dist-server/engine/property-effects.js +2 -2
- package/dist-server/engine/property-effects.js.map +1 -1
- package/dist-server/engine/read-time.d.ts +22 -0
- package/dist-server/engine/read-time.js +81 -0
- package/dist-server/engine/read-time.js.map +1 -0
- package/dist-server/engine/restart-policy.js +1 -1
- package/dist-server/engine/restart-policy.js.map +1 -1
- package/dist-server/engine/runtime-key.js +1 -1
- package/dist-server/engine/runtime-key.js.map +1 -1
- package/dist-server/engine/spec-coverage.d.ts +2 -2
- package/dist-server/engine/spec-coverage.js +1 -1
- package/dist-server/engine/spec-coverage.js.map +1 -1
- package/dist-server/engine/stage-path.d.ts +4 -4
- package/dist-server/engine/stage-path.js +1 -1
- package/dist-server/engine/stage-path.js.map +1 -1
- package/dist-server/engine/state-axes.d.ts +1 -1
- package/dist-server/engine/state-axes.js +2 -2
- package/dist-server/engine/state-axes.js.map +1 -1
- package/dist-server/engine/travel-estimator.d.ts +2 -2
- package/dist-server/engine/travel-estimator.js +1 -1
- package/dist-server/engine/travel-estimator.js.map +1 -1
- package/dist-server/engine/twin-engine.d.ts +243 -53
- package/dist-server/engine/twin-engine.js +690 -191
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/engine/warm-start.d.ts +2 -2
- package/dist-server/engine/warm-start.js +5 -5
- package/dist-server/engine/warm-start.js.map +1 -1
- package/dist-server/index.js +1 -1
- package/dist-server/index.js.map +1 -1
- package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js +1 -1
- package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +1 -1
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js +3 -3
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +1 -1
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js +2 -2
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +1 -1
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.d.ts +5 -0
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js +54 -0
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +1 -0
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.d.ts +5 -0
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js +44 -0
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +1 -0
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.d.ts +6 -0
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js +84 -0
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +1 -0
- package/dist-server/migrations/index.js +7 -1
- package/dist-server/migrations/index.js.map +1 -1
- package/dist-server/routes.d.ts +1 -0
- package/dist-server/routes.js +69 -5
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/index.d.ts +2 -2
- package/dist-server/service/index.js +27 -24
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/reference/control-routing.d.ts +1 -1
- package/dist-server/service/reference/control-routing.js +1 -1
- package/dist-server/service/reference/control-routing.js.map +1 -1
- package/dist-server/service/reference/discovery-result.d.ts +2 -2
- package/dist-server/service/reference/discovery-result.js +3 -3
- package/dist-server/service/reference/discovery-result.js.map +1 -1
- package/dist-server/service/reference/hook-contract.d.ts +43 -0
- package/dist-server/service/reference/hook-contract.js +59 -0
- package/dist-server/service/reference/hook-contract.js.map +1 -0
- package/dist-server/service/reference/ingest-space.d.ts +1 -1
- package/dist-server/service/reference/ingest-space.js +4 -4
- package/dist-server/service/reference/ingest-space.js.map +1 -1
- package/dist-server/service/reference/knob-defaults.d.ts +1 -1
- package/dist-server/service/reference/knob-defaults.js +4 -4
- package/dist-server/service/reference/knob-defaults.js.map +1 -1
- package/dist-server/service/reference/reference-adapter.d.ts +140 -8
- package/dist-server/service/reference/reference-adapter.js +27 -0
- package/dist-server/service/reference/reference-adapter.js.map +1 -1
- package/dist-server/service/reference/reference-hook.d.ts +20 -0
- package/dist-server/service/reference/reference-hook.js +133 -0
- package/dist-server/service/reference/reference-hook.js.map +1 -0
- package/dist-server/service/reference/reference-live.d.ts +2 -2
- package/dist-server/service/reference/reference-live.js +88 -13
- package/dist-server/service/reference/reference-live.js.map +1 -1
- package/dist-server/service/reference/reference-master.d.ts +14 -14
- package/dist-server/service/reference/reference-master.js +34 -12
- package/dist-server/service/reference/reference-master.js.map +1 -1
- package/dist-server/service/reference/reference-resolver.d.ts +1 -1
- package/dist-server/service/reference/reference-resolver.js +10 -10
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/reference/twin-reference.d.ts +3 -3
- package/dist-server/service/reference/twin-reference.js.map +1 -1
- package/dist-server/service/twin-attention/twin-attention-query.d.ts +1 -1
- package/dist-server/service/twin-attention/twin-attention-query.js +1 -1
- package/dist-server/service/twin-attention/twin-attention-query.js.map +1 -1
- package/dist-server/service/twin-audit/command-audit.d.ts +1 -1
- package/dist-server/service/twin-audit/command-audit.js.map +1 -1
- package/dist-server/service/twin-audit/twin-audit-event.d.ts +1 -1
- package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -1
- package/dist-server/service/twin-audit/twin-audit-query.js +1 -1
- package/dist-server/service/twin-audit/twin-audit-query.js.map +1 -1
- package/dist-server/service/twin-control/twin-control-mutation.js +1 -1
- package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-keys.d.ts +22 -2
- package/dist-server/service/twin-event/twin-event-keys.js +37 -5
- package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-type.d.ts +1 -0
- package/dist-server/service/twin-event/twin-event-type.js +8 -1
- package/dist-server/service/twin-event/twin-event-type.js.map +1 -1
- package/dist-server/service/twin-event/twin-event.d.ts +2 -2
- package/dist-server/service/twin-event/twin-event.js +32 -4
- package/dist-server/service/twin-event/twin-event.js.map +1 -1
- package/dist-server/service/twin-forecast/forecast-metrics.js +1 -1
- package/dist-server/service/twin-forecast/forecast-metrics.js.map +1 -1
- package/dist-server/service/twin-forecast/gap-analytics.d.ts +1 -1
- package/dist-server/service/twin-forecast/gap-analytics.js.map +1 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js +29 -11
- package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.d.ts +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +1 -1
- package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
- package/dist-server/service/twin-journal/event-type-split-shape.d.ts +50 -0
- package/dist-server/service/twin-journal/event-type-split-shape.js +111 -0
- package/dist-server/service/twin-journal/event-type-split-shape.js.map +1 -0
- package/dist-server/service/twin-journal/event-type-split.d.ts +15 -0
- package/dist-server/service/twin-journal/event-type-split.js +102 -0
- package/dist-server/service/twin-journal/event-type-split.js.map +1 -0
- package/dist-server/service/twin-journal/journal-order.d.ts +15 -0
- package/dist-server/service/twin-journal/journal-order.js +17 -0
- package/dist-server/service/twin-journal/journal-order.js.map +1 -0
- package/dist-server/service/twin-journal/twin-journal-query.d.ts +5 -5
- package/dist-server/service/twin-journal/twin-journal-query.js +232 -21
- package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +27 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +59 -3
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
- package/dist-server/service/twin-metrics/twin-metrics-query.js +14 -1
- package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
- package/dist-server/service/twin-model/axis-journal-evidence.js +1 -1
- package/dist-server/service/twin-model/axis-journal-evidence.js.map +1 -1
- package/dist-server/service/twin-model/epcis-coverage.js +36 -1
- package/dist-server/service/twin-model/epcis-coverage.js.map +1 -1
- package/dist-server/service/twin-model/iec61850-coverage.js +1 -1
- package/dist-server/service/twin-model/iec61850-coverage.js.map +1 -1
- package/dist-server/service/twin-model/isa95-coverage.d.ts +15 -2
- package/dist-server/service/twin-model/isa95-coverage.js +32 -8
- package/dist-server/service/twin-model/isa95-coverage.js.map +1 -1
- package/dist-server/service/twin-model/item-ref.js +2 -2
- package/dist-server/service/twin-model/item-ref.js.map +1 -1
- package/dist-server/service/twin-model/name-index.d.ts +1 -1
- package/dist-server/service/twin-model/name-index.js +1 -1
- package/dist-server/service/twin-model/name-index.js.map +1 -1
- package/dist-server/service/twin-model/project-structure.d.ts +1 -1
- package/dist-server/service/twin-model/project-structure.js +3 -3
- package/dist-server/service/twin-model/project-structure.js.map +1 -1
- package/dist-server/service/twin-model/twin-equipment.d.ts +1 -1
- package/dist-server/service/twin-model/twin-equipment.js +1 -1
- package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
- package/dist-server/service/twin-model/twin-lineage-query.js +16 -5
- package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-location.d.ts +1 -1
- package/dist-server/service/twin-model/twin-location.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-item-query.d.ts +3 -3
- package/dist-server/service/twin-model/twin-model-item-query.js +14 -14
- package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-mutation.d.ts +2 -2
- package/dist-server/service/twin-model/twin-model-mutation.js +4 -4
- package/dist-server/service/twin-model/twin-model-mutation.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-query.js +117 -28
- package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js +22 -0
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-operation.d.ts +1 -1
- package/dist-server/service/twin-model/twin-operation.js +1 -1
- package/dist-server/service/twin-model/twin-operation.js.map +1 -1
- package/dist-server/service/twin-space/move-space.js +2 -2
- package/dist-server/service/twin-space/move-space.js.map +1 -1
- package/dist-server/service/twin-space/representation-role.d.ts +2 -0
- package/dist-server/service/twin-space/representation-role.js +18 -0
- package/dist-server/service/twin-space/representation-role.js.map +1 -0
- package/dist-server/service/twin-space/space-integrity.d.ts +1 -1
- package/dist-server/service/twin-space/space-integrity.js.map +1 -1
- package/dist-server/service/twin-space/twin-space-representation.d.ts +2 -0
- package/dist-server/service/twin-space/twin-space-representation.js +16 -0
- package/dist-server/service/twin-space/twin-space-representation.js.map +1 -1
- package/dist-server/service/twin-space/twin-space-resolver.d.ts +2 -2
- package/dist-server/service/twin-space/twin-space-resolver.js +36 -7
- package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
- package/dist-server/service/twin-structure/twin-structure.js +3 -3
- package/dist-server/service/twin-structure/twin-structure.js.map +1 -1
- package/dist-server/service/twin-subject/event-subjects.d.ts +43 -0
- package/dist-server/service/twin-subject/event-subjects.js +137 -0
- package/dist-server/service/twin-subject/event-subjects.js.map +1 -0
- package/dist-server/service/twin-subject/index.d.ts +9 -0
- package/dist-server/service/twin-subject/index.js +16 -0
- package/dist-server/service/twin-subject/index.js.map +1 -0
- package/dist-server/service/twin-subject/item-resolver.d.ts +10 -0
- package/dist-server/service/twin-subject/item-resolver.js +93 -0
- package/dist-server/service/twin-subject/item-resolver.js.map +1 -0
- package/dist-server/service/twin-subject/subject-query-shape.d.ts +22 -0
- package/dist-server/service/twin-subject/subject-query-shape.js +88 -0
- package/dist-server/service/twin-subject/subject-query-shape.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-backfill.d.ts +23 -0
- package/dist-server/service/twin-subject/twin-subject-backfill.js +159 -0
- package/dist-server/service/twin-subject/twin-subject-backfill.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-event.d.ts +14 -0
- package/dist-server/service/twin-subject/twin-subject-event.js +111 -0
- package/dist-server/service/twin-subject/twin-subject-event.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-fast-path.d.ts +39 -0
- package/dist-server/service/twin-subject/twin-subject-fast-path.js +295 -0
- package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-query.d.ts +27 -0
- package/dist-server/service/twin-subject/twin-subject-query.js +232 -0
- package/dist-server/service/twin-subject/twin-subject-query.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-writer.d.ts +27 -0
- package/dist-server/service/twin-subject/twin-subject-writer.js +166 -0
- package/dist-server/service/twin-subject/twin-subject-writer.js.map +1 -0
- package/dist-server/service/twin-target/twin-target-resolver.js +1 -1
- package/dist-server/service/twin-target/twin-target-resolver.js.map +1 -1
- package/dist-shared/entity-delta.d.ts +1 -1
- package/dist-shared/entity-delta.js +3 -3
- package/dist-shared/entity-delta.js.map +1 -1
- package/dist-shared/touched-items.js +2 -2
- package/dist-shared/touched-items.js.map +1 -1
- package/dist-shared/twin-level.js +1 -1
- package/dist-shared/twin-level.js.map +1 -1
- package/package.json +3 -3
- package/server/engine/attention-digest.ts +9 -9
- package/server/engine/canonical-ingest.ts +170 -13
- package/server/engine/command-routing.ts +1 -1
- package/server/engine/declared-stimulus.ts +1 -1
- package/server/engine/energy-topology.ts +1 -1
- package/server/engine/ingest-dedupe.ts +149 -0
- package/server/engine/ingest-health.ts +234 -20
- package/server/engine/integration-probes.ts +7 -7
- package/server/engine/kpi-baseline.ts +4 -4
- package/server/engine/kpi-fold.ts +395 -27
- package/server/engine/kpi-query.ts +212 -46
- package/server/engine/live-feed-registry.ts +1 -1
- package/server/engine/load-meter.ts +1 -1
- package/server/engine/local-declarations.ts +13 -13
- package/server/engine/log.ts +1 -1
- package/server/engine/measured-estimator.ts +1 -1
- package/server/engine/measured-yield.ts +1 -1
- package/server/engine/model-basis.ts +2 -2
- package/server/engine/model-gap.ts +3 -3
- package/server/engine/model-vocabulary.ts +1 -1
- package/server/engine/oee-accumulator.ts +4 -4
- package/server/engine/property-effects.ts +2 -2
- package/server/engine/read-time.ts +77 -0
- package/server/engine/restart-policy.ts +1 -1
- package/server/engine/runtime-key.ts +1 -1
- package/server/engine/spec-coverage.ts +3 -3
- package/server/engine/stage-path.ts +5 -5
- package/server/engine/state-axes.ts +2 -2
- package/server/engine/travel-estimator.ts +2 -2
- package/server/engine/twin-engine.ts +764 -201
- package/server/engine/warm-start.ts +6 -6
- package/server/index.ts +1 -1
- package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +1 -1
- package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +3 -3
- package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +2 -2
- package/server/migrations/1786300000000-IndexEventTypeByTime.ts +48 -0
- package/server/migrations/1786400000000-IndexEventCreatedAt.ts +38 -0
- package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +93 -0
- package/server/migrations/index.ts +7 -1
- package/server/routes.ts +68 -5
- package/server/service/index.ts +4 -1
- package/server/service/reference/control-routing.ts +1 -1
- package/server/service/reference/discovery-result.ts +3 -3
- package/server/service/reference/hook-contract.ts +103 -0
- package/server/service/reference/ingest-space.ts +4 -4
- package/server/service/reference/knob-defaults.ts +4 -4
- package/server/service/reference/reference-adapter.ts +166 -9
- package/server/service/reference/reference-hook.ts +145 -0
- package/server/service/reference/reference-live.ts +92 -14
- package/server/service/reference/reference-master.ts +39 -17
- package/server/service/reference/reference-resolver.ts +10 -10
- package/server/service/reference/twin-reference.ts +3 -3
- package/server/service/twin-attention/twin-attention-query.ts +1 -1
- package/server/service/twin-audit/command-audit.ts +1 -1
- package/server/service/twin-audit/twin-audit-event.ts +2 -2
- package/server/service/twin-audit/twin-audit-query.ts +1 -1
- package/server/service/twin-control/twin-control-mutation.ts +1 -1
- package/server/service/twin-event/twin-event-keys.ts +37 -5
- package/server/service/twin-event/twin-event-type.ts +18 -1
- package/server/service/twin-event/twin-event.ts +32 -6
- package/server/service/twin-forecast/forecast-metrics.ts +1 -1
- package/server/service/twin-forecast/gap-analytics.ts +1 -1
- package/server/service/twin-forecast/twin-forecast-query.ts +30 -11
- package/server/service/twin-ingest-window/twin-ingest-window-query.ts +1 -1
- package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +1 -1
- package/server/service/twin-instance/twin-instance.ts +4 -4
- package/server/service/twin-journal/event-type-split-shape.ts +112 -0
- package/server/service/twin-journal/event-type-split.ts +144 -0
- package/server/service/twin-journal/journal-order.ts +20 -0
- package/server/service/twin-journal/twin-journal-query.ts +224 -20
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +57 -3
- package/server/service/twin-metrics/twin-metrics-query.ts +14 -1
- package/server/service/twin-model/axis-journal-evidence.ts +1 -1
- package/server/service/twin-model/epcis-coverage.ts +36 -1
- package/server/service/twin-model/iec61850-coverage.ts +1 -1
- package/server/service/twin-model/isa95-coverage.ts +45 -8
- package/server/service/twin-model/item-ref.ts +2 -2
- package/server/service/twin-model/name-index.ts +1 -1
- package/server/service/twin-model/project-structure.ts +4 -4
- package/server/service/twin-model/twin-equipment.ts +2 -2
- package/server/service/twin-model/twin-lineage-query.ts +16 -5
- package/server/service/twin-model/twin-location.ts +1 -1
- package/server/service/twin-model/twin-model-item-query.ts +14 -14
- package/server/service/twin-model/twin-model-mutation.ts +4 -4
- package/server/service/twin-model/twin-model-query.ts +117 -28
- package/server/service/twin-model/twin-model-tree-query.ts +25 -1
- package/server/service/twin-model/twin-operation.ts +2 -2
- package/server/service/twin-space/move-space.ts +3 -3
- package/server/service/twin-space/representation-role.ts +15 -0
- package/server/service/twin-space/space-integrity.ts +1 -1
- package/server/service/twin-space/twin-space-representation.ts +37 -0
- package/server/service/twin-space/twin-space-resolver.ts +39 -7
- package/server/service/twin-structure/twin-structure.ts +3 -3
- package/server/service/twin-subject/event-subjects.ts +155 -0
- package/server/service/twin-subject/index.ts +10 -0
- package/server/service/twin-subject/item-resolver.ts +92 -0
- package/server/service/twin-subject/subject-query-shape.ts +84 -0
- package/server/service/twin-subject/twin-subject-backfill.ts +196 -0
- package/server/service/twin-subject/twin-subject-event.ts +101 -0
- package/server/service/twin-subject/twin-subject-fast-path.ts +346 -0
- package/server/service/twin-subject/twin-subject-query.ts +210 -0
- package/server/service/twin-subject/twin-subject-writer.ts +189 -0
- package/server/service/twin-target/twin-target-resolver.ts +1 -1
- package/shared/entity-delta.ts +3 -3
- package/shared/touched-items.ts +2 -2
- package/shared/twin-level.ts +1 -1
- package/test/adopt-structure-live.test.ts +3 -3
- package/test/aggregate-not-findone.test.ts +112 -0
- package/test/attention-digest.test.ts +6 -6
- package/test/axis-read.test.ts +2 -2
- package/test/boot-resume.test.ts +20 -7
- package/test/broadcast-period.test.ts +2 -2
- package/test/broadcast-queue-overflow.test.ts +244 -0
- package/test/canonical-ingest-vocabularies.test.ts +179 -7
- package/test/canonical-quantity-door.test.ts +2 -2
- package/test/checkpoint-refuses-empty.test.ts +2 -2
- package/test/connector-capability-declaration.test.ts +88 -0
- package/test/control-capability.test.ts +1 -1
- package/test/cursor-stall-not-read-failure.test.ts +2 -2
- package/test/declaration-reaches-model.test.ts +5 -5
- package/test/declared-stimulus.test.ts +4 -4
- package/test/discovery-result.test.ts +2 -2
- package/test/entity-delta.test.ts +4 -4
- package/test/event-subjects.test.ts +147 -0
- package/test/event-time-column.test.ts +3 -3
- package/test/event-type-split.test.ts +155 -0
- package/test/fold-gap-speaks.test.ts +53 -0
- package/test/forecast-metrics.test.ts +1 -1
- package/test/forecast-tuning.test.ts +1 -1
- package/test/ingest-health-engine.test.ts +2 -2
- package/test/ingest-health-wiring.test.ts +7 -5
- package/test/ingest-health.test.ts +6 -6
- package/test/ingest-history.test.ts +2 -2
- package/test/ingest-idempotent.test.ts +132 -0
- package/test/ingest-space.test.ts +3 -3
- package/test/integration-probes.test.ts +3 -3
- package/test/integration-runner.test.ts +1 -1
- package/test/item-ref.test.ts +1 -1
- package/test/journal-order-axis.test.ts +80 -0
- package/test/journal-read-discipline.test.ts +16 -6
- package/test/journal-retention.test.ts +171 -29
- package/test/journal-sort-axis.test.ts +1 -1
- package/test/journal-write-door.test.ts +3 -3
- package/test/journal-write-trend.test.ts +1 -1
- package/test/kernel-kind-guard.test.ts +3 -3
- package/test/knob-defaults.test.ts +1 -1
- package/test/kpi-baseline-db.test.ts +2 -2
- package/test/kpi-fold.test.ts +185 -14
- package/test/kpi-query-bench.test.ts +3 -3
- package/test/live-cursor-wiring.test.ts +6 -6
- package/test/live-kernel-facts.test.ts +11 -11
- package/test/live-mirror-parity.test.ts +3 -3
- package/test/load-meter.test.ts +1 -1
- package/test/local-declarations.test.ts +10 -10
- package/test/log-stamp.test.ts +1 -1
- package/test/measured-yield.test.ts +2 -2
- package/test/merge-streams.test.ts +70 -0
- package/test/mirror-resumes-from-checkpoint.test.ts +13 -13
- package/test/model-basis.test.ts +2 -2
- package/test/model-gap.test.ts +4 -4
- package/test/model-vocabulary.test.ts +2 -2
- package/test/move-space.test.ts +1 -1
- package/test/oee-accumulator.test.ts +2 -2
- package/test/operational-vocabulary.test.ts +2 -2
- package/test/project-structure-db.test.ts +2 -2
- package/test/projection-reaches-screen.test.ts +2 -2
- package/test/property-effects.test.ts +3 -3
- package/test/read-failure-ledger.test.ts +106 -0
- package/test/read-failure-visible.test.ts +7 -7
- package/test/read-time.test.ts +118 -0
- package/test/reference-grounding.test.ts +1 -1
- package/test/reference-hook.test.ts +86 -0
- package/test/registry-key-guard.test.ts +1 -1
- package/test/rename-twin.test.ts +81 -0
- package/test/restart-policy.test.ts +3 -3
- package/test/resync-origin-site.test.ts +3 -3
- package/test/revision-axis.test.ts +14 -8
- package/test/runtime-key.test.ts +3 -3
- package/test/snapshot-freshness.test.ts +4 -4
- package/test/source-outcome-audit.test.ts +1 -1
- package/test/space-integrity.test.ts +1 -1
- package/test/space-representation.test.ts +66 -0
- package/test/space-scope-includes-stopped.test.ts +55 -0
- package/test/spec-coverage.test.ts +1 -1
- package/test/standard-coverage.test.ts +43 -1
- package/test/status-tally.test.ts +1 -1
- package/test/structure-revision-db.test.ts +7 -7
- package/test/subject-fast-path.test.ts +148 -0
- package/test/subject-read-model.test.ts +175 -0
- package/test/touched-items.test.ts +2 -2
- package/test/twin-audit.test.ts +1 -1
- package/test/twin-event-keys.test.ts +49 -3
- package/test/twin-model-item-db.test.ts +5 -5
- package/test/twin-model-tree-db.test.ts +35 -2
- package/test/twin-origin-resync.test.ts +1 -1
- package/test/warm-start-seam.test.ts +1 -1
- package/test/warm-start.test.ts +6 -6
- package/test/withheld-door.test.ts +95 -0
- package/test/yield-loop.test.ts +4 -4
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
* 업무 KPI 폴드 — **이벤트 저널을
|
|
3
|
+
* 업무 KPI 폴드 — **이벤트 저널을 계산해** 시간창 지표를 만든다(순수).
|
|
4
4
|
*
|
|
5
5
|
* ── 왜 필요한가 ─────────────────────────────────────────────────────────────
|
|
6
6
|
* 지금 트윈이 답할 수 있는 것은 "이 순간의 값"(점유 92%)과 "인프라 부하"(초당 이벤트 수)뿐이다.
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
*
|
|
10
10
|
* ── 원료는 이미 있다 ────────────────────────────────────────────────────────
|
|
11
11
|
* 저널(`TwinEvent`)에 `task.status`·`order.status`·`equipment.status` 전이가 `eventTime`(ISO)과 함께
|
|
12
|
-
* append-only 로 쌓인다. 그래서 새 계측을 심을 필요가 없다 —
|
|
13
|
-
* 같은 모양의 선례가 이 폴더에 있다(`oee-accumulator.ts` — equipment 전이를
|
|
12
|
+
* append-only 로 쌓인다. 그래서 새 계측을 심을 필요가 없다 — **계산만 하면 된다.**
|
|
13
|
+
* 같은 모양의 선례가 이 폴더에 있다(`oee-accumulator.ts` — equipment 전이를 계산해 OEE 카운터 생산).
|
|
14
14
|
*
|
|
15
15
|
* ── 이 파일이 하지 않는 것 ──────────────────────────────────────────────────
|
|
16
16
|
* · 목표와 비교하지 않는다. "95% 목표 대비" 는 목표를 저장하는 별개 층(경영 KPI)의 몫이고,
|
|
@@ -29,7 +29,7 @@ exports.foldKpiBuckets = foldKpiBuckets;
|
|
|
29
29
|
* 짝맞춤은 **커널이 소유한다**(`foldTaskRecords`). 완료는 작업당 하나·나중 것이 사실, 착수는 처음 것,
|
|
30
30
|
* 종류·오더는 어느 전이에서든 — 그 규칙은 커널 상태 기계에서 나오는 지식이다. 여기서 다시 적었더니
|
|
31
31
|
* 공정 타임라인과 **다른 답**을 냈다(재전송된 완료를 두 건으로 세어 처리량·점유가 부풀려졌다).
|
|
32
|
-
* 이 파일은 이제 "
|
|
32
|
+
* 이 파일은 이제 "계산한 기록 → 창 지표" 만 한다.
|
|
33
33
|
*/
|
|
34
34
|
const twin_kernel_1 = require("@operato/twin-kernel");
|
|
35
35
|
/**
|
|
@@ -128,6 +128,148 @@ function feederShares(kWh, utilization, resourceFeeder) {
|
|
|
128
128
|
* 분기 계량 합이 뿌리보다 크면(회계가 다른 두 계량기) **그 사실을 낸다** — 값을 깎아 맞추면 계량을
|
|
129
129
|
* 우리가 고쳐 쓰는 것이다.
|
|
130
130
|
*/
|
|
131
|
+
/**
|
|
132
|
+
* 창의 **발전량** — 커널이 마감한 기간 사실을 합한다.
|
|
133
|
+
*
|
|
134
|
+
* ── 왜 합이 전부인가 ───────────────────────────────────────────────────────
|
|
135
|
+
* 기간 발전량은 커널이 이미 확정한 사실이다(적산의 종류마다 다른 규칙으로 얻는다). 여기서 다시
|
|
136
|
+
* 계산하면 규칙이 두 벌이 되고, 그때부터 두 화면이 다른 발전량을 말한다. 이 함수가 하는 일은
|
|
137
|
+
* **창에 든 것을 고르고, 설비별로 묶고, 근거가 얼마나 덮였는지 세는 것**이다.
|
|
138
|
+
*
|
|
139
|
+
* ── 걸친 기간은 세지 않는다 ─────────────────────────────────────────────────
|
|
140
|
+
* 구간 마감과 같은 규칙이다. 하루의 절반이 창에 들었다고 절반을 세면 그것은 관측이 아니라 우리가 나눈
|
|
141
|
+
* 값이고, 합이 창을 넘는다.
|
|
142
|
+
*
|
|
143
|
+
* ── 덜 덮인 기간을 센다 ─────────────────────────────────────────────────────
|
|
144
|
+
* 기간의 끝이 자정인데 마지막 표본이 저녁이었으면 그 사이는 재지 않은 것이다. 그 수를 함께 내야 화면이
|
|
145
|
+
* 「이 합은 이만큼 덜 잰 것」이라고 말할 수 있다. 얼마나 어긋나면 문제인지는 현장이 정한다.
|
|
146
|
+
*/
|
|
147
|
+
function generatedOfPeriods(periods, range) {
|
|
148
|
+
const inside = periods.filter(g => g.startMs >= range.startMs && g.endMs <= range.endMs);
|
|
149
|
+
if (!inside.length)
|
|
150
|
+
return {};
|
|
151
|
+
const byEquipment = new Map();
|
|
152
|
+
let partial = 0;
|
|
153
|
+
for (const g of inside) {
|
|
154
|
+
byEquipment.set(g.equipmentId, (byEquipment.get(g.equipmentId) ?? 0) + g.kWh);
|
|
155
|
+
const coveredFrom = Number.isFinite(g.observedFromMs) ? g.observedFromMs <= g.startMs : false;
|
|
156
|
+
const coveredTo = Number.isFinite(g.observedToMs) ? g.observedToMs >= g.endMs : false;
|
|
157
|
+
if (!coveredFrom || !coveredTo)
|
|
158
|
+
partial++;
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
generated: {
|
|
162
|
+
kWh: inside.reduce((a, g) => a + g.kWh, 0),
|
|
163
|
+
counted: inside.length,
|
|
164
|
+
partial,
|
|
165
|
+
byEquipment: [...byEquipment.entries()]
|
|
166
|
+
.map(([id, kWh]) => ({ id, kWh }))
|
|
167
|
+
.sort((a, b) => b.kWh - a.kWh)
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 밖에서 마감되어 온 사용 구간을 합한다 — **구간 마감과 더하지 않는다.**
|
|
173
|
+
*
|
|
174
|
+
* 두 회계가 같은 전기를 말한다. 더하면 두 번 세고, 둘 다 있는 현장에서는 계량 쪽이 강한 근거이므로
|
|
175
|
+
* 그쪽을 쓴다. 여기서는 이쪽 몫만 계산하고, 무엇을 쓸지는 부르는 쪽이 정한다.
|
|
176
|
+
*
|
|
177
|
+
* 단가는 **모든 구간이 실었을 때만** 요금을 만든다. 일부만 실었는데 있는 것만 더하면 그 합이 창의
|
|
178
|
+
* 요금인 척한다 — 못 매긴 구간 수를 함께 낸다.
|
|
179
|
+
*/
|
|
180
|
+
function usageOfPeriods(periods, range) {
|
|
181
|
+
const inside = periods.filter(u => u.startMs >= range.startMs && u.endMs <= range.endMs);
|
|
182
|
+
if (!inside.length)
|
|
183
|
+
return undefined;
|
|
184
|
+
const byBasis = new Map();
|
|
185
|
+
let kWh = 0;
|
|
186
|
+
let charge = 0;
|
|
187
|
+
let unpriced = 0;
|
|
188
|
+
let currency;
|
|
189
|
+
for (const u of inside) {
|
|
190
|
+
kWh += u.kWh;
|
|
191
|
+
byBasis.set(u.basis, (byBasis.get(u.basis) ?? 0) + 1);
|
|
192
|
+
if (Number.isFinite(u.unitPrice)) {
|
|
193
|
+
charge += u.kWh * u.unitPrice;
|
|
194
|
+
if (!currency)
|
|
195
|
+
currency = u.currency;
|
|
196
|
+
}
|
|
197
|
+
else
|
|
198
|
+
unpriced++;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
kWh,
|
|
202
|
+
counted: inside.length,
|
|
203
|
+
...(unpriced === 0 && currency ? { charge, currency } : {}),
|
|
204
|
+
unpriced,
|
|
205
|
+
byBasis: [...byBasis.entries()].map(([basis, counted]) => ({ basis, counted })).sort((a, b) => b.counted - a.counted)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* **요금적용전력을 고른다 — 청구서가 먼저다.**
|
|
210
|
+
*
|
|
211
|
+
* 순서에 뜻이 있다. 청구서는 그 기간에 실제로 매겨진 값이고, 선언은 사람이 옮겨 적은 값이다.
|
|
212
|
+
* 그 값이 매달 바뀌므로 옮겨 적은 것은 곧 낡는다.
|
|
213
|
+
*/
|
|
214
|
+
function billingDemandOf(billsInWindow, lastBill, declaredKW) {
|
|
215
|
+
const declared = Number.isFinite(Number(declaredKW)) ? Number(declaredKW) : undefined;
|
|
216
|
+
const withValue = billsInWindow.filter(b => Number.isFinite(b.billingDemandKW));
|
|
217
|
+
const fromBill = withValue.length ? withValue.reduce((a, x) => (x.endMs > a.endMs ? x : a)).billingDemandKW : undefined;
|
|
218
|
+
const carried = Number.isFinite(Number(lastBill?.billingDemandKW)) ? Number(lastBill?.billingDemandKW) : undefined;
|
|
219
|
+
const picked = fromBill !== undefined
|
|
220
|
+
? { kW: fromBill, from: 'bill' }
|
|
221
|
+
: carried !== undefined
|
|
222
|
+
? { kW: carried, from: 'carried-forward' }
|
|
223
|
+
: declared !== undefined
|
|
224
|
+
? { kW: declared, from: 'declaration' }
|
|
225
|
+
: undefined;
|
|
226
|
+
if (!picked)
|
|
227
|
+
return undefined;
|
|
228
|
+
/* 선언이 있는데 청구서와 다르면 그 사실을 낸다 — 낡은 선언은 스스로 말해야 한다. */
|
|
229
|
+
const stale = picked.from !== 'declaration' && declared !== undefined && declared !== picked.kW;
|
|
230
|
+
return {
|
|
231
|
+
...picked,
|
|
232
|
+
...(declared !== undefined ? { declaredKW: declared } : {}),
|
|
233
|
+
...(stale ? { stale: true } : {})
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* 창에 온전히 든 청구서 하나 — 가장 늦게 끝난 것.
|
|
238
|
+
*
|
|
239
|
+
* **창이 청구 주기와 같을 때만 견준다.** 한 달 청구서를 하루 창의 값과 빼면 그 차이는 아무것도 뜻하지
|
|
240
|
+
* 않는다. 그래서 같은지를 값과 함께 낸다.
|
|
241
|
+
*/
|
|
242
|
+
function billOfWindow(bills, range, ours) {
|
|
243
|
+
const inside = bills.filter(b => b.startMs >= range.startMs && b.endMs <= range.endMs);
|
|
244
|
+
if (!inside.length)
|
|
245
|
+
return undefined;
|
|
246
|
+
const b = inside.reduce((a, x) => (x.endMs > a.endMs ? x : a));
|
|
247
|
+
const matchesWindow = b.startMs === range.startMs && b.endMs === range.endMs;
|
|
248
|
+
/* 양쪽에 있는 항목만 견준다 — 한쪽이 없는 것을 0 으로 두면 그 차이가 통째로 어긋남처럼 보인다. */
|
|
249
|
+
const gap = (mine, billed) => Number.isFinite(Number(mine)) && Number.isFinite(billed) ? Number(mine) - billed : undefined;
|
|
250
|
+
const diff = matchesWindow
|
|
251
|
+
? {
|
|
252
|
+
...(gap(ours?.total, b.total) !== undefined ? { total: gap(ours?.total, b.total) } : {}),
|
|
253
|
+
...(gap(ours?.demandCharge, b.demandCharge) !== undefined
|
|
254
|
+
? { demandCharge: gap(ours?.demandCharge, b.demandCharge) }
|
|
255
|
+
: {}),
|
|
256
|
+
...(gap(ours?.energyCharge, b.energyCharge) !== undefined
|
|
257
|
+
? { energyCharge: gap(ours?.energyCharge, b.energyCharge) }
|
|
258
|
+
: {})
|
|
259
|
+
}
|
|
260
|
+
: {};
|
|
261
|
+
return {
|
|
262
|
+
from: b.from,
|
|
263
|
+
to: b.to,
|
|
264
|
+
...(Number.isFinite(b.total) ? { total: b.total } : {}),
|
|
265
|
+
...(Number.isFinite(b.energyCharge) ? { energyCharge: b.energyCharge } : {}),
|
|
266
|
+
...(Number.isFinite(b.demandCharge) ? { demandCharge: b.demandCharge } : {}),
|
|
267
|
+
...(b.currency ? { currency: b.currency } : {}),
|
|
268
|
+
...(Number.isFinite(b.billingDemandKW) ? { billingDemandKW: b.billingDemandKW } : {}),
|
|
269
|
+
matchesWindow,
|
|
270
|
+
...(Object.keys(diff).length ? { diff } : {})
|
|
271
|
+
};
|
|
272
|
+
}
|
|
131
273
|
function measuredFeeders(windows, range, totalKWh, meterFeeder) {
|
|
132
274
|
if (!meterFeeder || !Object.keys(meterFeeder).length)
|
|
133
275
|
return undefined;
|
|
@@ -197,7 +339,7 @@ function measuredFeeders(windows, range, totalKWh, meterFeeder) {
|
|
|
197
339
|
...(remainder < 0 ? { submeterExcessKWh: -remainder } : {})
|
|
198
340
|
};
|
|
199
341
|
}
|
|
200
|
-
/** 이 기록이 요청한 축에서 어느 값에 속하는가. 값이 없으면 'unknown'(
|
|
342
|
+
/** 이 기록이 요청한 축에서 어느 값에 속하는가. 값이 없으면 'unknown'(알리지 않고 버리지 않는다). */
|
|
201
343
|
function facetKey(rec, options) {
|
|
202
344
|
const f = rec.facets;
|
|
203
345
|
switch (options.groupBy) {
|
|
@@ -227,7 +369,7 @@ function facetKey(rec, options) {
|
|
|
227
369
|
if (!options.shifts?.length)
|
|
228
370
|
return 'unknown';
|
|
229
371
|
/* 시각까지 넘긴다 — **휴일에 일어난 일은 어느 교대에도 속하지 않는다.** 되풀이만 보면 그날 서지도
|
|
230
|
-
않은 교대에 집계돼, 교대별 성과가
|
|
372
|
+
않은 교대에 집계돼, 교대별 성과가 알리지 않고 거짓이 된다. */
|
|
231
373
|
return (0, twin_kernel_1.activeShiftAt)(options.shifts, rec.at, options.utcOffsetMinutes) ?? 'unknown';
|
|
232
374
|
default:
|
|
233
375
|
return 'unknown';
|
|
@@ -256,7 +398,7 @@ function qualityOf(rows) {
|
|
|
256
398
|
* 기록을 축으로 묶어 축별 통계를 낸다 — **전체와 같은 규칙**으로(같은 stats 함수, 같은 창).
|
|
257
399
|
*
|
|
258
400
|
* 축의 값이 아주 많을 수 있다(오더 축은 수천 개). 그래서 건수 큰 것부터 상한까지만 돌려주고
|
|
259
|
-
* **잘라낸 수를 함께 알린다** —
|
|
401
|
+
* **잘라낸 수를 함께 알린다** — 들어온 것이 없는 절단은 "이게 전부" 라는 거짓을 만든다.
|
|
260
402
|
*/
|
|
261
403
|
function groupRecords(records, options) {
|
|
262
404
|
const by = options.groupBy;
|
|
@@ -320,11 +462,11 @@ function stats(values) {
|
|
|
320
462
|
};
|
|
321
463
|
}
|
|
322
464
|
/**
|
|
323
|
-
* 이벤트를
|
|
465
|
+
* 이벤트를 계산해 시간창 KPI 를 만든다.
|
|
324
466
|
*
|
|
325
467
|
* **호출부 규약**: `events` 는 창보다 **넉넉히 앞까지** 담아 넘긴다(예: 창 시작 − 리드타임 상한).
|
|
326
468
|
* 완료된 작업의 시작 이벤트가 창 밖에 있을 수 있기 때문이다. 못 찾은 것은 `unpaired` 로 알린다 —
|
|
327
|
-
* 평균에서
|
|
469
|
+
* 평균에서 오류 없이 빠지면 지표가 거짓이 된다.
|
|
328
470
|
*
|
|
329
471
|
* 시간축은 `eventTime`(ISO) 차분이다. sim 클록이 실제 시각과 오프셋이 있어도 **차분은 정확**하다
|
|
330
472
|
* (고정 오프셋은 상쇄된다). 파싱 불가한 줄은 버린다.
|
|
@@ -352,7 +494,7 @@ function foldKpi(events, window, options = {}) {
|
|
|
352
494
|
* **끝났나는 커널이 답한다** (2026-08-23) — `isOrderTerminal`.
|
|
353
495
|
*
|
|
354
496
|
* 예전에는 여기서 **동의어 목록**으로 추론했다(`completed`·`fulfilled`·`done`·`finished`).
|
|
355
|
-
* 그 방식이 낸 대가가 둘이었고 둘 다
|
|
497
|
+
* 그 방식이 낸 대가가 둘이었고 둘 다 들어온 것이 없었다.
|
|
356
498
|
*
|
|
357
499
|
* ① 원본의 낱말이 목록에 없으면 완료가 0 이 된다. 실제로 그랬다 — 첫 실 시스템의 `FINISHED`
|
|
358
500
|
* 가 빠져 있었고, 그때 목록에 낱말을 더한 것은 진짜 빈 자리(그 커넥터가 자기 상태 표를
|
|
@@ -369,7 +511,7 @@ function foldKpi(events, window, options = {}) {
|
|
|
369
511
|
if (at >= window.fromMs && at <= window.toMs) {
|
|
370
512
|
/*
|
|
371
513
|
* **오더당 한 번만 센다.** 폴링하는 원본은 같은 오더의 종결을 여러 주기에 걸쳐 다시 보낼 수
|
|
372
|
-
* 있고(그것은 결함이 아니라 폴링의 성질이다), 사건마다 세면 처리량이
|
|
514
|
+
* 있고(그것은 결함이 아니라 폴링의 성질이다), 사건마다 세면 처리량이 알리지 않고 부풀려진다.
|
|
373
515
|
* 작업 쪽은 커널의 짝맞춤이 이미 그 규율을 갖고 있다(「완료는 작업당 하나」) — 오더만 없었다.
|
|
374
516
|
*/
|
|
375
517
|
if (done) {
|
|
@@ -379,7 +521,7 @@ function foldKpi(events, window, options = {}) {
|
|
|
379
521
|
completedOrders++;
|
|
380
522
|
}
|
|
381
523
|
else if (!id)
|
|
382
|
-
completedOrders++; // 정체를 모르면 셈에서 빼지 않는다(
|
|
524
|
+
completedOrders++; // 정체를 모르면 셈에서 빼지 않는다(알리지 않고 줄이지 않는다)
|
|
383
525
|
}
|
|
384
526
|
/*
|
|
385
527
|
* **완료로 세지 않은 낱말의 인구조사.** 「못 읽었다」가 아니다 — `picking` 처럼 완료가 아닌
|
|
@@ -421,6 +563,62 @@ function foldKpi(events, window, options = {}) {
|
|
|
421
563
|
};
|
|
422
564
|
})
|
|
423
565
|
.filter(w => Number.isFinite(w.startMs) && Number.isFinite(w.endMs));
|
|
566
|
+
/*
|
|
567
|
+
* 발전 기간 사실 — 커널이 기간을 마감할 때 낸 것이다. 구간 마감과 같은 규칙으로 **창에 온전히 든
|
|
568
|
+
* 것만** 센다(걸친 기간을 반만 세면 합이 창을 넘는다).
|
|
569
|
+
*
|
|
570
|
+
* 관측 구간(`observedFrom`·`observedTo`)을 함께 읽는다 — 값의 근거가 얼마나 덮였는지가 그 둘에 있다.
|
|
571
|
+
*/
|
|
572
|
+
const generationPeriods = events
|
|
573
|
+
.filter(e => e.eventType === twin_kernel_1.ENERGY_EVENT.generationPeriod)
|
|
574
|
+
.map(e => {
|
|
575
|
+
const d = e.payload?.data ?? e.payload ?? {};
|
|
576
|
+
return {
|
|
577
|
+
equipmentId: String(d.equipmentId ?? ''),
|
|
578
|
+
kWh: Number(d.kWh),
|
|
579
|
+
startMs: Date.parse(String(d.periodStart ?? '')),
|
|
580
|
+
endMs: Date.parse(String(d.periodEnd ?? '')),
|
|
581
|
+
observedFromMs: Date.parse(String(d.observedFrom ?? '')),
|
|
582
|
+
observedToMs: Date.parse(String(d.observedTo ?? ''))
|
|
583
|
+
};
|
|
584
|
+
})
|
|
585
|
+
.filter(g => g.equipmentId && Number.isFinite(g.kWh) && Number.isFinite(g.startMs) && Number.isFinite(g.endMs));
|
|
586
|
+
/*
|
|
587
|
+
* 밖에서 마감되어 온 사용 구간 — 구간 마감과 같은 규칙으로 **창에 온전히 든 것만** 센다.
|
|
588
|
+
*/
|
|
589
|
+
const usagePeriods = events
|
|
590
|
+
.filter(e => e.eventType === twin_kernel_1.ENERGY_EVENT.usagePeriod)
|
|
591
|
+
.map(e => {
|
|
592
|
+
const d = e.payload?.data ?? e.payload ?? {};
|
|
593
|
+
return {
|
|
594
|
+
meterId: String(d.meterId ?? ''),
|
|
595
|
+
kWh: Number(d.kWh),
|
|
596
|
+
startMs: Date.parse(String(d.from ?? '')),
|
|
597
|
+
endMs: Date.parse(String(d.to ?? '')),
|
|
598
|
+
unitPrice: Number(d.unitPrice),
|
|
599
|
+
currency: d.currency ? String(d.currency) : undefined,
|
|
600
|
+
basis: d.basis ? String(d.basis) : 'unstated'
|
|
601
|
+
};
|
|
602
|
+
})
|
|
603
|
+
.filter(u => u.meterId && Number.isFinite(u.kWh) && Number.isFinite(u.startMs) && Number.isFinite(u.endMs));
|
|
604
|
+
/* 청구서 — 창에 온전히 든 것 중 가장 늦게 끝난 것 하나. */
|
|
605
|
+
const bills = events
|
|
606
|
+
.filter(e => e.eventType === twin_kernel_1.ENERGY_EVENT.bill)
|
|
607
|
+
.map(e => {
|
|
608
|
+
const d = e.payload?.data ?? e.payload ?? {};
|
|
609
|
+
return {
|
|
610
|
+
from: String(d.from ?? ''),
|
|
611
|
+
to: String(d.to ?? ''),
|
|
612
|
+
startMs: Date.parse(String(d.from ?? '')),
|
|
613
|
+
endMs: Date.parse(String(d.to ?? '')),
|
|
614
|
+
total: Number(d.total),
|
|
615
|
+
energyCharge: Number(d.energyCharge),
|
|
616
|
+
demandCharge: Number(d.demandCharge),
|
|
617
|
+
currency: d.currency ? String(d.currency) : undefined,
|
|
618
|
+
billingDemandKW: Number(d.billingDemandKW)
|
|
619
|
+
};
|
|
620
|
+
})
|
|
621
|
+
.filter(b => Number.isFinite(b.startMs) && Number.isFinite(b.endMs));
|
|
424
622
|
const leads = [];
|
|
425
623
|
const works = [];
|
|
426
624
|
const waits = [];
|
|
@@ -466,18 +664,43 @@ function foldKpi(events, window, options = {}) {
|
|
|
466
664
|
return {
|
|
467
665
|
window: { fromMs: window.fromMs, toMs: window.toMs },
|
|
468
666
|
throughput: { tasks: tasksInWindow, orders: completedOrders },
|
|
469
|
-
|
|
667
|
+
/* 발전만 있는 현장(계량 없는 발전소)도 답이 나와야 한다 — 둘 중 하나만 있어도 블록을 낸다. */
|
|
668
|
+
...(demandWindows.length || generationPeriods.length || usagePeriods.length || bills.length
|
|
470
669
|
? (() => {
|
|
471
670
|
const e = (0, twin_kernel_1.energyOfWindows)(demandWindows, { startMs: window.fromMs, endMs: window.toMs });
|
|
671
|
+
const usage = usageOfPeriods(usagePeriods, { startMs: window.fromMs, endMs: window.toMs });
|
|
672
|
+
/*
|
|
673
|
+
* 어느 회계를 쓸지 정한다 — **더하지 않는다.** 계량 표본에서 우리가 마감한 값이 있으면 그것을
|
|
674
|
+
* 쓰고(강한 근거), 없으면 밖에서 마감되어 온 값을 쓴다. 무엇을 썼는지 함께 낸다.
|
|
675
|
+
*/
|
|
676
|
+
const usedKWh = e.kWh !== undefined ? e.kWh : usage?.kWh;
|
|
677
|
+
const kWhBasis = e.kWh !== undefined ? 'demand-window' : usage ? 'usage-period' : undefined;
|
|
472
678
|
/* 분모는 **완료 오더**다(대당 전력). 창에 완료가 없으면 커널 규칙이 「정의되지 않음」으로 답한다. */
|
|
473
679
|
const i = (0, twin_kernel_1.energyIntensity)({
|
|
474
|
-
kWh:
|
|
680
|
+
kWh: usedKWh,
|
|
475
681
|
energyWindow: e.window,
|
|
476
682
|
denominator: { kind: 'output', value: completedOrders, window: e.window }
|
|
477
683
|
});
|
|
684
|
+
/*
|
|
685
|
+
* 요금은 **구간마다 제 단가로** 매긴 값이 있으면 그것을 쓴다. 단일 단가로 접으면 시간대마다
|
|
686
|
+
* 다른 단가가 사라지고, 「피크를 깎아 얼마를 아끼나」가 그 차이 위에 선다.
|
|
687
|
+
*/
|
|
688
|
+
/* 요금적용전력은 청구서가 먼저다 — 선언은 청구가 오지 않는 현장의 몫이다. */
|
|
689
|
+
const billingDemand = billingDemandOf(bills.filter(b => Number.isFinite(b.billingDemandKW)).map(b => ({ endMs: b.endMs, billingDemandKW: b.billingDemandKW })), options.lastBill, options.tariff?.billingDemandKW);
|
|
690
|
+
const cost = options.tariff
|
|
691
|
+
? (0, twin_kernel_1.electricityCost)({
|
|
692
|
+
kWh: usedKWh,
|
|
693
|
+
peakKW: e.peakKW,
|
|
694
|
+
tariff: { ...options.tariff, ...(billingDemand ? { billingDemandKW: billingDemand.kW } : {}) },
|
|
695
|
+
...(usage?.charge !== undefined ? { energyChargeFromPeriods: usage.charge } : {})
|
|
696
|
+
})
|
|
697
|
+
: undefined;
|
|
478
698
|
return {
|
|
479
699
|
energy: {
|
|
480
|
-
...(
|
|
700
|
+
...(usedKWh !== undefined ? { kWh: usedKWh } : {}),
|
|
701
|
+
...(kWhBasis ? { kWhBasis } : {}),
|
|
702
|
+
...(billingDemand ? { billingDemand } : {}),
|
|
703
|
+
...(usage ? { usage } : {}),
|
|
481
704
|
/* 이 창의 최대수요 — 계약 대비 판정이 보는 수다(전력량과 같은 구간 집합에서 왔다). */
|
|
482
705
|
...(e.peakKW !== undefined ? { peakKW: e.peakKW, peakStartMs: e.peakStartMs } : {}),
|
|
483
706
|
/* 깎인 양은 **같은 구간의 두 수**의 차이다 — 여기서 한 번만 계산해 두 곳이 갈라지지 않게. */
|
|
@@ -493,7 +716,13 @@ function foldKpi(events, window, options = {}) {
|
|
|
493
716
|
...(measuredFeeders(demandWindows, { startMs: window.fromMs, endMs: window.toMs }, e.kWh, options.meterFeeder) ??
|
|
494
717
|
feederShares(e.kWh, utilization, options.resourceFeeder)),
|
|
495
718
|
/* 금액은 같은 창의 전력량·최대수요에서 나온다 — 창이 하나뿐이라 어긋날 수 없다. */
|
|
496
|
-
...(
|
|
719
|
+
...(cost ? { cost } : {}),
|
|
720
|
+
...generatedOfPeriods(generationPeriods, { startMs: window.fromMs, endMs: window.toMs }),
|
|
721
|
+
/* 청구서는 사실이다 — 우리 계산을 덮지 않고 나란히 둔다(§`billOfWindow`). */
|
|
722
|
+
...(() => {
|
|
723
|
+
const b = billOfWindow(bills, { startMs: window.fromMs, endMs: window.toMs }, cost);
|
|
724
|
+
return b ? { bill: b } : {};
|
|
725
|
+
})()
|
|
497
726
|
}
|
|
498
727
|
};
|
|
499
728
|
})()
|
|
@@ -529,7 +758,7 @@ function crossGroups(now, prev) {
|
|
|
529
758
|
}
|
|
530
759
|
/* ── 시간 비교 ──────────────────────────────────────────────────────────────
|
|
531
760
|
* 숫자 하나로는 좋아졌는지 나빠졌는지 알 수 없다("29초" 가 개선인지 악화인지). 같은 길이의 창을 옮겨
|
|
532
|
-
* 한 번 더
|
|
761
|
+
* 한 번 더 계산하면 되므로(폴드는 순수) 값싸다. 창 옮기기와 차이 계산은 계산 규칙이라 여기 있다 —
|
|
533
762
|
* 조회 층에 두면 테스트가 DB 를 끌고 와야 한다.
|
|
534
763
|
*/
|
|
535
764
|
/**
|
|
@@ -553,7 +782,7 @@ function deltaP50(now, prev) {
|
|
|
553
782
|
return now.count > 0 && prev.count > 0 ? now.p50Ms - prev.p50Ms : undefined;
|
|
554
783
|
}
|
|
555
784
|
/**
|
|
556
|
-
* 창을 N 등분해 구간별로
|
|
785
|
+
* 창을 N 등분해 구간별로 처리한다 — **같은 이벤트를 창만 바꿔** 다시 계산한다(조회 추가 없음).
|
|
557
786
|
*
|
|
558
787
|
* 마지막 구간은 나머지를 흡수한다(부동소수 나눗셈으로 끝이 밀리면 마지막 완료가 빠진다).
|
|
559
788
|
* `count <= 1` 이면 쪼갤 것이 없으므로 빈 배열 — 호출부가 "추세 없음" 으로 다룬다.
|