@things-factory/headless-twin 10.1.278 → 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,211 +0,0 @@
|
|
|
1
|
-
import { nameIndex, namesFor } from './name-index.js'
|
|
2
|
-
import { Arg, Ctx, Int, Query, Resolver } from 'type-graphql'
|
|
3
|
-
|
|
4
|
-
import { ScalarObject, getRepository } from '@things-factory/shell'
|
|
5
|
-
|
|
6
|
-
import { TwinInstance } from '../twin-instance/twin-instance.js'
|
|
7
|
-
|
|
8
|
-
const { TWIN_RELATIONS, axisInfo } = require('@operato/ops-contract')
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 재귀 전개 — **자기 축으로 돌아오는 선언을 따라간다.**
|
|
12
|
-
*
|
|
13
|
-
* ── 왜 자재가 자재를 품지 않는가 ───────────────────────────────────────────────
|
|
14
|
-
* 다단 BOM 을 "자재 안에 자재" 로 적으면 같은 부품이 여러 완제품에 들어갈 때마다 복제되고,
|
|
15
|
-
* 수량이 어디 붙는지도 애매해진다. 표준(ISA-95)이 택한 모양은 **자재와 레시피가 번갈아 나오는
|
|
16
|
-
* 그래프**다: 완제품 ←산출— 레시피 —투입→ 부품들, 그리고 그 부품이 또 어느 레시피의 산출이면
|
|
17
|
-
* 거기서 다시 내려간다. 우리 선언(`ops.rel.input`·`ops.rel.output`)이 이미 그 두 홉이다.
|
|
18
|
-
*
|
|
19
|
-
* ── 패턴을 코드가 알지 않는다 ──────────────────────────────────────────────────
|
|
20
|
-
* "BOM 은 산출→투입" 이라고 적어 두면 그 순간 이 파일이 도메인을 알게 된다(ADR-0031 위반).
|
|
21
|
-
* 대신 **선언 그래프에서 자기 축으로 돌아오는 두 홉 순환을 찾는다.** 자재만이 아니라 앞으로
|
|
22
|
-
* 같은 모양을 갖는 어떤 축이든 그대로 펼쳐진다.
|
|
23
|
-
*
|
|
24
|
-
* ── 알리지 않고 고르지 않는다 ───────────────────────────────────────────────────────
|
|
25
|
-
* 순환이 여럿이면 **아무거나 집지 않는다.** 후보를 돌려주고 부르는 쪽이 고르게 한다 — 한쪽을
|
|
26
|
-
* 집으면 역전개(누가 나를 쓰나)를 전개(내가 무엇으로 되나)로 보여 주고도 아무도 모른다.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/** 자기 축으로 돌아오는 두 홉 — `axis ←down(via)— through —up(via)→ axis`. */
|
|
30
|
-
interface WalkPattern {
|
|
31
|
-
/** 중간에 거치는 축(레시피 등). */
|
|
32
|
-
through: string
|
|
33
|
-
/** 나로 들어오는 홉 — "나를 이것의 산출로 삼는" 쪽. */
|
|
34
|
-
inVia: string
|
|
35
|
-
/** 거기서 다시 나가는 홉 — "그것이 투입하는" 쪽. */
|
|
36
|
-
outVia: string
|
|
37
|
-
inField: string
|
|
38
|
-
outField: string
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** 선언 그래프에서 이 축으로 돌아오는 순환들을 찾는다. */
|
|
42
|
-
function patternsFor(axis: string): WalkPattern[] {
|
|
43
|
-
const toMe = TWIN_RELATIONS.filter((r: any) => r.target?.kind === 'axis' && r.target.axis === axis)
|
|
44
|
-
const out: WalkPattern[] = []
|
|
45
|
-
for (const a of toMe)
|
|
46
|
-
for (const b of toMe)
|
|
47
|
-
if (a !== b && a.from === b.from)
|
|
48
|
-
out.push({ through: a.from, inVia: a.via, outVia: b.via, inField: a.field, outField: b.field })
|
|
49
|
-
return out
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const at = (o: any, path: string) => path.split('.').reduce((a: any, k: string) => (a == null ? undefined : a[k]), o)
|
|
53
|
-
const idOf = (o: any): string | null => (typeof o === 'string' ? o : o?.id ?? o?.key ?? o?.gtin ?? null)
|
|
54
|
-
|
|
55
|
-
/** `inputs[].material` — 배열을 지나는 선언 경로. 값과 **그 값을 담은 객체**를 함께 돌려준다(수량이 거기 있다). */
|
|
56
|
-
function entriesAt(obj: any, field: string): { value: any; holder: any }[] {
|
|
57
|
-
let cur: { value: any; holder: any }[] = [{ value: obj, holder: obj }]
|
|
58
|
-
for (const seg of field.split('.')) {
|
|
59
|
-
const key = seg.endsWith('[]') ? seg.slice(0, -2) : seg
|
|
60
|
-
const next: { value: any; holder: any }[] = []
|
|
61
|
-
for (const c of cur) {
|
|
62
|
-
const v = c.value?.[key]
|
|
63
|
-
if (v == null) continue
|
|
64
|
-
if (Array.isArray(v)) for (const x of v) next.push({ value: x, holder: x })
|
|
65
|
-
else next.push({ value: v, holder: c.value })
|
|
66
|
-
}
|
|
67
|
-
cur = next
|
|
68
|
-
}
|
|
69
|
-
return cur
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** 이 홉이 실어 나르는 수량 — 선언에 있으면 쓰고, 없으면 **없다고 한다**(1 로 메우지 않는다). */
|
|
73
|
-
function qtyOf(holder: any): number | null {
|
|
74
|
-
const q = holder?.qty ?? holder?.quantity
|
|
75
|
-
return typeof q === 'number' ? q : null
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
@Resolver()
|
|
79
|
-
export class TwinModelTreeQuery {
|
|
80
|
-
@Query(returns => ScalarObject, {
|
|
81
|
-
nullable: true,
|
|
82
|
-
description:
|
|
83
|
-
'Recursively expand an item through a declared two-hop cycle (e.g. a multi-level BOM: product ←produced-by— recipe —consumes→ parts). The pattern is derived from the kernel relation declarations, never hardcoded. Reports the pattern used, any cycles found, and whether depth or item caps truncated the walk.'
|
|
84
|
-
})
|
|
85
|
-
async twinModelTree(
|
|
86
|
-
@Arg('instanceId') instanceId: string,
|
|
87
|
-
@Arg('axis') axis: string,
|
|
88
|
-
@Arg('itemId') itemId: string,
|
|
89
|
-
@Ctx() context: ResolverContext,
|
|
90
|
-
@Arg('inVia', { nullable: true }) inVia?: string,
|
|
91
|
-
@Arg('outVia', { nullable: true }) outVia?: string,
|
|
92
|
-
@Arg('maxDepth', type => Int, { nullable: true }) maxDepth?: number,
|
|
93
|
-
@Arg('maxItems', type => Int, { nullable: true }) maxItems?: number
|
|
94
|
-
): Promise<any | null> {
|
|
95
|
-
const domainId = context.state.domain.id
|
|
96
|
-
const info = axisInfo(axis)
|
|
97
|
-
if (!info) throw new Error(`unknown concept axis: "${axis}" — the kernel catalog does not declare it`)
|
|
98
|
-
|
|
99
|
-
const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })
|
|
100
|
-
if (!inst) return null
|
|
101
|
-
|
|
102
|
-
const all = patternsFor(axis)
|
|
103
|
-
if (!all.length) return { axis, itemId, patterns: [], items: [], edges: [], reason: 'no-recursive-relation' }
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const chosen = inVia && outVia ? all.find(p => p.inVia === inVia && p.outVia === outVia) : all.length === 1 ? all[0] : undefined
|
|
107
|
-
if (!chosen)
|
|
108
|
-
/* 여럿인데 안 고르면 **아무것도 펼치지 않는다.** 한쪽을 집으면 역전개를 전개로 보여 주고도
|
|
109
|
-
아무도 모른다 — 방향이 뒤집힌 BOM 은 틀린 답이 아니라 반대의 답이다. */
|
|
110
|
-
return { axis, itemId, patterns: all, items: [], edges: [], reason: 'ambiguous-pattern' }
|
|
111
|
-
|
|
112
|
-
/*
|
|
113
|
-
* ── ★ **선언에 없는 축은 펼칠 것이 없다** (2026-08-24 실측으로 터짐) ────────
|
|
114
|
-
*
|
|
115
|
-
* 이 전개는 **트윈 모델의 선언**을 읽는다(`axisInfo(...).path` 로 모델 안을 찾아 들어간다). 그런데
|
|
116
|
-
* 커널 카탈로그의 축 중 셋은 **선언되는 것이 아니라 일어나는 것**이다 — `orders`·`tasks`·`items`
|
|
117
|
-
* 는 사건이 만들고 끝나면 사라진다. 모델이 그 목록을 가질 수 없으므로 `path` 가 비어 있다.
|
|
118
|
-
*
|
|
119
|
-
* 그래서 그런 축을 지나려 하면 `at(model, undefined)` 에서 터졌다:
|
|
120
|
-
*
|
|
121
|
-
* Cannot read properties of undefined (reading 'split')
|
|
122
|
-
*
|
|
123
|
-
* ★ **터진 것은 요청한 축이 아니라 「거쳐 가는 축」이다.** `locations` 를 물으면 그 순환이
|
|
124
|
-
* `tasks` 를 거치는데(작업이 `from`·`at` 으로 자리를 두 번 가리킨다) 그 `tasks` 에 경로가 없다.
|
|
125
|
-
* 그래서 요청한 축만 지켜서는 막히지 않는다 — 둘 다 본다.
|
|
126
|
-
*
|
|
127
|
-
* ── 터지지 않게 하는 것만으로는 모자라다 ──────────────────────────────────
|
|
128
|
-
* 빈 트리를 돌려주면 화면이 **「이어진 것이 없다」**로 읽는다. 그것은 거짓이다 — 작업은 자리를
|
|
129
|
-
* 가리키고 있고, 다만 **이 질의가 그것을 아는 곳이 아니다**(그 관계는 상태와 저널이 안다).
|
|
130
|
-
* 그래서 이유를 말한다. 왜 못 하는지 말하지 않는 빈 화면이 이 저장소가 반복해 고친 결함이다.
|
|
131
|
-
*/
|
|
132
|
-
if (!info.path || !axisInfo(chosen.through)?.path)
|
|
133
|
-
return { axis, itemId, patterns: all, items: [], edges: [], reason: 'not-declared-in-model' }
|
|
134
|
-
|
|
135
|
-
const model = inst.model ?? {}
|
|
136
|
-
const throughInfo = axisInfo(chosen.through)
|
|
137
|
-
const listOf = (i: any) => {
|
|
138
|
-
const raw = i ? at(model, i.path) : undefined
|
|
139
|
-
return Array.isArray(raw) ? raw : raw ? [raw] : []
|
|
140
|
-
}
|
|
141
|
-
const throughAll = listOf(throughInfo)
|
|
142
|
-
const mineAll = listOf(info)
|
|
143
|
-
const mineIds = new Set(mineAll.map(idOf).filter(Boolean) as string[])
|
|
144
|
-
|
|
145
|
-
const depthCap = Math.min(Math.max(maxDepth ?? 6, 1), 12)
|
|
146
|
-
const itemCap = Math.min(Math.max(maxItems ?? 200, 1), 2000)
|
|
147
|
-
|
|
148
|
-
const items: any[] = [{ id: itemId, axis, depth: 0, qty: 1, known: mineIds.has(itemId) }]
|
|
149
|
-
const edges: any[] = []
|
|
150
|
-
const seen = new Set<string>([itemId])
|
|
151
|
-
const cycles: string[] = []
|
|
152
|
-
let depthTruncated = false
|
|
153
|
-
let itemTruncated = false
|
|
154
|
-
|
|
155
|
-
/* 너비 우선 — 깊이 상한에서 끊기면 **얕은 층은 온전히** 남는다(깊이 우선이면 한 가지만 깊게 파고 끊긴다). */
|
|
156
|
-
let frontier: { id: string; depth: number; qty: number | null }[] = [{ id: itemId, depth: 0, qty: 1 }]
|
|
157
|
-
while (frontier.length) {
|
|
158
|
-
const nextFrontier: typeof frontier = []
|
|
159
|
-
for (const cur of frontier) {
|
|
160
|
-
if (cur.depth >= depthCap) { depthTruncated = true; continue }
|
|
161
|
-
/* 나를 만들어 내는 중간 항목들(레시피)을 찾는다 — 선언된 홉을 따라. */
|
|
162
|
-
for (const t of throughAll) {
|
|
163
|
-
const producesMe = entriesAt(t, chosen.inField).some(e => String(idOf(e.value) ?? e.value) === cur.id)
|
|
164
|
-
if (!producesMe) continue
|
|
165
|
-
for (const e of entriesAt(t, chosen.outField)) {
|
|
166
|
-
const childId = String(idOf(e.value) ?? e.value)
|
|
167
|
-
const step = qtyOf(e.holder)
|
|
168
|
-
/* 수량을 모르면 **곱하지 않는다.** 1 로 메우면 "1개 필요" 라는 사실 주장이 되고,
|
|
169
|
-
윗단에서 곱해진 값이 전부 거짓이 된다. */
|
|
170
|
-
const qty = cur.qty != null && step != null ? cur.qty * step : null
|
|
171
|
-
edges.push({ from: cur.id, to: childId, through: idOf(t), depth: cur.depth + 1, step, qty })
|
|
172
|
-
|
|
173
|
-
if (seen.has(childId)) {
|
|
174
|
-
/* 이미 지난 항목으로 돌아왔다 — 사이클이거나 공유 부품이다. 어느 쪽이든 **다시 파지
|
|
175
|
-
않고 말한다.** 파고 들어가면 돌아 나오지 못한다. */
|
|
176
|
-
if (edges.some(x => x.to === cur.id && x.from === childId)) cycles.push(`${cur.id} ↔ ${childId}`)
|
|
177
|
-
continue
|
|
178
|
-
}
|
|
179
|
-
if (items.length >= itemCap) { itemTruncated = true; continue }
|
|
180
|
-
seen.add(childId)
|
|
181
|
-
items.push({ id: childId, axis, depth: cur.depth + 1, qty, known: mineIds.has(childId) })
|
|
182
|
-
nextFrontier.push({ id: childId, depth: cur.depth + 1, qty })
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
frontier = nextFrontier
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
axis,
|
|
191
|
-
itemId,
|
|
192
|
-
/* 어떤 순환을 따라 펼쳤는지 **밝힌다** — 방향이 뒤집힌 전개는 틀린 답이 아니라 반대의 답이라
|
|
193
|
-
화면만 보고는 구별되지 않는다. */
|
|
194
|
-
pattern: chosen,
|
|
195
|
-
patterns: all,
|
|
196
|
-
items,
|
|
197
|
-
edges,
|
|
198
|
-
/* 수량을 하나라도 모르면 아래 합계가 성립하지 않는다는 사실을 그대로 낸다. */
|
|
199
|
-
/*
|
|
200
|
-
* **이름을 함께 낸다** (2026-08-22). 나무의 줄이 id 만 보이면 사용자는 그 노드가 무엇인지 알 수
|
|
201
|
-
* 없다 — 사용자의 말: 「각 노드의 식별자가 반복되어서 이해가 어렵다. 식별자와 이름이 보이면.」
|
|
202
|
-
* 목록·항목 화면이 쓰는 것과 **같은 표**를 쓴다(`name-index`) — 두 벌이면 한쪽만 고쳐진다.
|
|
203
|
-
*/
|
|
204
|
-
names: namesFor(items, nameIndex(inst.model ?? {})),
|
|
205
|
-
qtyIncomplete: edges.some(e => e.step == null),
|
|
206
|
-
cycles: [...new Set(cycles)],
|
|
207
|
-
truncated: { depth: depthTruncated, items: itemTruncated, depthCap, itemCap },
|
|
208
|
-
basis: 'document'
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
|
2
|
-
import { ObjectType, Field, ID, Int } from 'type-graphql'
|
|
3
|
-
|
|
4
|
-
import { Domain, ScalarObject } from '@things-factory/shell'
|
|
5
|
-
|
|
6
|
-
import { TwinInstance } from '../twin-instance/twin-instance.js'
|
|
7
|
-
|
|
8
|
-
/*
|
|
9
|
-
* TwinOperation — 이 트윈이 반영하는 **공정 명세**. ISA-95 `OperationsSegment`.
|
|
10
|
-
* 이 현장에서 각 작업이 **어디서·무엇으로·얼마나 걸리나**(선언값).
|
|
11
|
-
*
|
|
12
|
-
* ── 왜 이 표가 인스펙션의 중심인가 ──────────────────────────────────────────
|
|
13
|
-
* 인스펙션 화면의 존재 이유는 `선언 | 관측` 두 열이고(`plans/twin-inspection.md` §2.4),
|
|
14
|
-
* 그 첫 열이 여기서 온다. 둘째 열은 저널에서 계산된다(`kpi-fold.workTime`).
|
|
15
|
-
* 실적은 보이는데 기준이 안 보이면 "절단이 5분 걸렸다" 를 보고도 빠른지 느린지 알 수 없다.
|
|
16
|
-
*
|
|
17
|
-
* 자리·설비와 같은 규율 — **원본에서 온 캐시**, `sourceRef`·`ingestedAt` 필수,
|
|
18
|
-
* 쓰기 경로는 인제스트 하나(`twin-location.ts` 머리말).
|
|
19
|
-
*/
|
|
20
|
-
@Entity({ name: 'twin_operations' })
|
|
21
|
-
@Index('ix_twin_operation_0', (e: TwinOperation) => [e.domain, e.instance, e.operationKey], { unique: true })
|
|
22
|
-
@ObjectType({ description: 'An operation spec reflected into the twin (ISA-95 OperationsSegment): where it runs, with what, and how long the source says it takes.' })
|
|
23
|
-
export class TwinOperation {
|
|
24
|
-
@PrimaryGeneratedColumn('uuid')
|
|
25
|
-
@Field(type => ID)
|
|
26
|
-
readonly id: string
|
|
27
|
-
|
|
28
|
-
@ManyToOne(type => Domain)
|
|
29
|
-
@Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })
|
|
30
|
-
domain?: Domain
|
|
31
|
-
|
|
32
|
-
@RelationId((e: TwinOperation) => e.domain)
|
|
33
|
-
domainId?: string
|
|
34
|
-
|
|
35
|
-
@ManyToOne(type => TwinInstance, { onDelete: 'CASCADE' })
|
|
36
|
-
@Field(type => TwinInstance, { nullable: true, description: 'Owning twin instance.' })
|
|
37
|
-
instance?: TwinInstance
|
|
38
|
-
|
|
39
|
-
@RelationId((e: TwinOperation) => e.instance)
|
|
40
|
-
instanceRowId?: string
|
|
41
|
-
|
|
42
|
-
/** 커널 계약의 `OperationDef.key` 그대로. 라우트의 단계가 이 키로 가리킨다. */
|
|
43
|
-
@Column()
|
|
44
|
-
@Field({ description: 'Operation key as declared by the source (kernel OperationDef.key). Route steps reference this.' })
|
|
45
|
-
operationKey: string
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* **사람이 부르는 이름** — 프레임워크 엔티티 규약의 `name`/`description`.
|
|
49
|
-
*
|
|
50
|
-
* ── 왜 이것이 빠져 있었고, 무엇이 망가졌나 ────────────────────────────────────
|
|
51
|
-
* 투영이 마스터의 `name` 을 버리고 있었다. 그래서 행에는 id 만 남고, 화면은 이름을 만들 재료가
|
|
52
|
-
* 없어 `cut-station` 을 그대로 찍었다 — 그 결함이 목록·표·관계 그림마다 따로 나타나서 표면을
|
|
53
|
-
* 하나씩 고치게 만들었다. 표면의 문제가 아니라 **행에 이름이 없던 문제**다.
|
|
54
|
-
*
|
|
55
|
-
* 원본이 이름을 말하지 않으면 비운다(id 를 이름으로 베끼지 않는다 — 그러면 "이름이 있다" 는
|
|
56
|
-
* 거짓이 되고, 화면이 이름 없음을 알아볼 수 없게 된다).
|
|
57
|
-
*/
|
|
58
|
-
@Column({ nullable: true })
|
|
59
|
-
@Field({ nullable: true, description: 'Human name as declared by the source. Empty when the source does not name it (never copied from the id).' })
|
|
60
|
-
name?: string
|
|
61
|
-
|
|
62
|
-
@Column({ nullable: true })
|
|
63
|
-
@Field({ nullable: true, description: 'Longer description when the source provides one.' })
|
|
64
|
-
description?: string
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@Column({ nullable: true })
|
|
68
|
-
@Field({ nullable: true, description: "Intent: 'transport' | 'process' | 'dwell'." })
|
|
69
|
-
intent?: string
|
|
70
|
-
|
|
71
|
-
/*
|
|
72
|
-
* 어디서·무엇으로 — 자리·설비의 **항목이 아니라 타입**을 가리킨다("절단은 cut-station 에서 수행된다").
|
|
73
|
-
* 그래서 FK 가 아니다. 화면은 이것을 "그 타입의 자리·설비 목록" 으로 푼다(관계 선언의 `type` 대상).
|
|
74
|
-
*/
|
|
75
|
-
@Column({ nullable: true })
|
|
76
|
-
@Field({ nullable: true, description: 'Location type this operation runs at (a catalog type key, not an item reference).' })
|
|
77
|
-
locationType?: string
|
|
78
|
-
|
|
79
|
-
@Column({ nullable: true })
|
|
80
|
-
@Field({ nullable: true, description: 'Resource type that performs it (a catalog type key, not an item reference).' })
|
|
81
|
-
resourceType?: string
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* 소요시간 — **ISO 8601 기간 문자열이 정본**(`PT1H10M`).
|
|
85
|
-
*
|
|
86
|
-
* 분으로 저장하면 `PT1H10M30S` 의 초가 사라지고 그 손실은 들어온 것이 없다. 사람이 읽을 분은
|
|
87
|
-
* 화면이 곁들여 보여 주고, 못 읽는 값은 `—` 로 낸다(0 으로 채우면 "즉시 끝나는 공정" 이라는 거짓).
|
|
88
|
-
*/
|
|
89
|
-
@Column({ nullable: true })
|
|
90
|
-
@Field({ nullable: true, description: 'Declared duration as an ISO 8601 period (e.g. PT1H10M). The string is canonical — storing minutes would silently drop seconds.' })
|
|
91
|
-
duration?: string
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* 변동성·파라미터(수율·셋업)는 형이 도메인마다 달라 **원형 그대로** 싣는다.
|
|
95
|
-
* 여기를 컬럼으로 펴려면 커널이 그 형을 먼저 고정해야 한다 — 아직 아니다.
|
|
96
|
-
*/
|
|
97
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
98
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Declared variability (distribution/min/max/mode) as given by the source.' })
|
|
99
|
-
variability?: any
|
|
100
|
-
|
|
101
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
102
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Declared parameters (yield, setup duration…) as given by the source.' })
|
|
103
|
-
parameters?: any
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* **네 자원 명세 — 선언한 것만 제약이 된다.**
|
|
107
|
-
*
|
|
108
|
-
* ISA-95 는 한 공정이 무엇을 필요로 하는지를 넷으로 말한다: 설비(`resourceType`)·인원·자산·자재.
|
|
109
|
-
* 커널도 그 넷을 그대로 본다 — 선언이 있으면 잡아야 작업이 시작되고, 없으면 그 자원을 보지 않는다.
|
|
110
|
-
*
|
|
111
|
-
* 이 셋이 투영에서 **떨어져 있었다.** 그래서 조회 화면의 "원본이 말한 값" 열에 넷 중 하나만
|
|
112
|
-
* 나왔고, 사람이 필요한 공정을 보고도 **사람이 필요 없다고 결론 내게** 되어 있었다. 원본이 말한
|
|
113
|
-
* 것을 화면이 말하지 않으면 그 화면은 원본을 반영하는 것이 아니다.
|
|
114
|
-
*
|
|
115
|
-
* 모양은 커널 계약 그대로 싣는다 — 인제스트 경계에서 모양을 바꾸면 그 자리에서 방언이 생긴다.
|
|
116
|
-
*/
|
|
117
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
118
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Personnel this operation requires (ISA-95 PersonnelSpecification): class + quantity. Absent means the operation runs without people.' })
|
|
119
|
-
personnelSpecification?: any
|
|
120
|
-
|
|
121
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
122
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Physical assets this operation requires (ISA-95 PhysicalAssetSpecification). Absent means no asset constraint — an empty pallet is never the reason a job waits.' })
|
|
123
|
-
physicalAssetSpecification?: any
|
|
124
|
-
|
|
125
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
126
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Materials this operation consumes or produces (ISA-95 MaterialSpecification). Absent means material shortage never shows up in the forecast for this step.' })
|
|
127
|
-
materialSpecification?: any
|
|
128
|
-
|
|
129
|
-
/** 라우트 안에서의 순서 — 라우트가 이 공정을 몇 번째로 부르나(라우트 표가 서면 그리로 옮긴다). */
|
|
130
|
-
@Column({ type: 'int', nullable: true })
|
|
131
|
-
@Field(type => Int, { nullable: true, description: 'Sequence within its route, when the source declares one.' })
|
|
132
|
-
seq?: number
|
|
133
|
-
|
|
134
|
-
/* ── 캐시라는 사실을 구조로 (ADR-0032-D) ── */
|
|
135
|
-
@Column()
|
|
136
|
-
@Field({ description: 'Which reference (source system) this row came from. Required.' })
|
|
137
|
-
sourceRef: string
|
|
138
|
-
|
|
139
|
-
/*
|
|
140
|
-
* **타입 이름을 적지 않는다** (2026-08-19 Postgres 부팅 실패로 고침).
|
|
141
|
-
*
|
|
142
|
-
* `datetime` 은 sqlite·MySQL 의 이름이고 Postgres 는 `timestamp` 만 안다 — 거꾸로 `timestamp` 는
|
|
143
|
-
* sqlite 가 모른다. **다섯 드라이버에 다 통하는 이름이 없다.** 그래서 이름 고르는 일을 TypeORM 에
|
|
144
|
-
* 맡긴다(`emitDecoratorMetadata` 가 켜져 있어 `Date` 에서 드라이버별 타입을 고른다).
|
|
145
|
-
*/
|
|
146
|
-
@Column()
|
|
147
|
-
@Field({ description: 'When this row was projected from the source.' })
|
|
148
|
-
ingestedAt: Date
|
|
149
|
-
|
|
150
|
-
@CreateDateColumn()
|
|
151
|
-
@Field({ nullable: true })
|
|
152
|
-
createdAt?: Date
|
|
153
|
-
|
|
154
|
-
@UpdateDateColumn()
|
|
155
|
-
@Field({ nullable: true })
|
|
156
|
-
updatedAt?: Date
|
|
157
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { Arg, Ctx, Query, Resolver } from 'type-graphql'
|
|
2
|
-
|
|
3
|
-
import { getRepository, ScalarObject } from '@things-factory/shell'
|
|
4
|
-
|
|
5
|
-
import { TwinEngine } from '../../engine/index.js'
|
|
6
|
-
import { assessSuite, SUITE_SPEC, type SuiteFacts } from '../../engine/integration-runner.js'
|
|
7
|
-
import { readSpecCoverage } from '../../engine/spec-coverage.js'
|
|
8
|
-
import { capabilitiesOf, getAdapter } from '../reference/reference-adapter.js'
|
|
9
|
-
import { TwinEvent } from '../twin-event/twin-event.js'
|
|
10
|
-
import { anyJournalRow, countUpTo } from '../twin-event/journal-count.js'
|
|
11
|
-
import { TwinInstance } from '../twin-instance/twin-instance.js'
|
|
12
|
-
import { TwinReference } from '../reference/twin-reference.js'
|
|
13
|
-
|
|
14
|
-
/*
|
|
15
|
-
* 도입 단계 — **「이 트윈은 어디까지 증명됐나」.**
|
|
16
|
-
*
|
|
17
|
-
* `twinIngestHealth` 와 묻는 것이 다르다: 그쪽은 「지금 현장과 맞춰지고 있나」(피드의 건강)이고,
|
|
18
|
-
* 여기는 「구조·라이브·예측·폐루프 중 어디까지 **증거로** 섰나」다. 체크리스트가 아니라 판정이므로
|
|
19
|
-
* 사람이 체크해서 초록으로 만들 수 없다.
|
|
20
|
-
*
|
|
21
|
-
* **접속 프로브는 여기서 돌리지 않는다.** 조회마다 고객 시스템을 두드리면 화면을 열 때마다 남의
|
|
22
|
-
* 운영계에 부하가 간다. 그래서 `connectOk` 는 `null`(안 돌렸다)이고, 계획의 첫 칸이 접속 확인이 된다.
|
|
23
|
-
*/
|
|
24
|
-
@Resolver()
|
|
25
|
-
export class TwinReadinessQuery {
|
|
26
|
-
@Query(returns => ScalarObject, {
|
|
27
|
-
nullable: true,
|
|
28
|
-
description:
|
|
29
|
-
'Which adoption stage this twin has actually reached, judged from evidence rather than a checklist: structure, live, forecast, closed-loop. Each stage reports what blocks it and which signals could not be measured at all — an unmeasured signal never counts as achieved, so a half-run suite cannot claim green. Probes that do not apply to this twin (live probes on a simulation, mapping-warning probes on a template-built twin) come back as notApplicable with a reason, which is neither a pass nor a gap. `forbiddenClaims` lists the claims that must not be made yet (realtime, prediction, automatic control). The connection probe is not run here because a read query should not hit the source system on every page load, so it appears in `planned` as the next step to take. Null if the instance is not in the current domain.'
|
|
30
|
-
})
|
|
31
|
-
async twinAdoptionPath(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any> {
|
|
32
|
-
const domainId = context.state.domain.id
|
|
33
|
-
if (!TwinEngine.owns(domainId, instanceId) && !(await TwinEngine.ownsRegistered(domainId, instanceId))) return null
|
|
34
|
-
|
|
35
|
-
const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })
|
|
36
|
-
if (!inst) return null
|
|
37
|
-
const ref = await getRepository(TwinReference)
|
|
38
|
-
.findOne({ where: { domain: { id: domainId }, source: instanceId } })
|
|
39
|
-
.catch(() => null)
|
|
40
|
-
|
|
41
|
-
const mode = TwinEngine.modeOf(domainId, instanceId)
|
|
42
|
-
const snapshot = TwinEngine.owns(domainId, instanceId) ? TwinEngine.snapshot(domainId, instanceId) : undefined
|
|
43
|
-
const events = getRepository(TwinEvent)
|
|
44
|
-
|
|
45
|
-
/*
|
|
46
|
-
* 저널에서 센다 — **재시작에도 남는 자리**다. 인메모리 계기로 세면 재기동마다 0 이 되고, 그 0 이
|
|
47
|
-
* 「세었는데 반출이 없었다」로 읽혀 라이브 단계를 거짓으로 막는다.
|
|
48
|
-
*
|
|
49
|
-
* `action` 승격 전에 기록된 행은 세어지지 않는다. 그래서 반출이 **한 건도 없고** 승격 이후 유입도
|
|
50
|
-
* 없으면 `null`(모른다)로 낸다 — 옛 저널을 「반출 0건」으로 단정하지 않는다.
|
|
51
|
-
*/
|
|
52
|
-
/*
|
|
53
|
-
* **상한까지만 센다** (2026-08-22 실측). 예전에는 넷을 전부 세었고, 저널 358만 행인 트윈에서 한 번이
|
|
54
|
-
* 5.32초라 이 화면 하나가 20초를 썼다. 판정에 쓰이는 것은 문턱(≥1)이므로 상한까지의 수로 충분하고,
|
|
55
|
-
* 승격 여부는 **한 건만 찾으면** 답이 난다(수가 필요 없다).
|
|
56
|
-
*/
|
|
57
|
-
const scope = { domain: { id: domainId }, instanceId }
|
|
58
|
-
const journal = await countUpTo(events, scope)
|
|
59
|
-
const removalCount = await countUpTo(events, { ...scope, action: 'DELETE' })
|
|
60
|
-
const journalTotal = journal.count
|
|
61
|
-
const removals = removalCount.count
|
|
62
|
-
const anyPromoted =
|
|
63
|
-
removals > 0 ||
|
|
64
|
-
(await anyJournalRow(events, { ...scope, action: 'OBSERVE' })) ||
|
|
65
|
-
(await anyJournalRow(events, { ...scope, action: 'ADD' }))
|
|
66
|
-
|
|
67
|
-
const modelLocations = Array.isArray((inst.model as any)?.locations) ? (inst.model as any).locations.length : null
|
|
68
|
-
|
|
69
|
-
const facts: SuiteFacts = {
|
|
70
|
-
subject: mode === 'live' ? 'live' : mode === 'sim' ? 'sim' : 'unknown',
|
|
71
|
-
fromReference: !!ref,
|
|
72
|
-
adapterCapabilities: ref?.adapterType ? capabilitiesOf(getAdapter(ref.adapterType)) : [],
|
|
73
|
-
connectOk: null, // 조회에서 남의 운영계를 두드리지 않는다
|
|
74
|
-
/* 이 레퍼런스가 트윈을 세운 사이트 수 — 발견의 결과다(발견 자체를 다시 돌리지 않는다). */
|
|
75
|
-
siteCount: ref ? ((ref.scopeSpec as any)?.produced?.length ?? null) : null,
|
|
76
|
-
locationCount: snapshot?.locations?.length ?? modelLocations,
|
|
77
|
-
itemCount: snapshot?.items?.length ?? null,
|
|
78
|
-
lastWarningCount: ref?.lastWarningCount ?? null,
|
|
79
|
-
journalTotal,
|
|
80
|
-
/* 승격 이후 유입이 하나도 없으면 세지 못한 것이다 — 0 으로 단정하지 않는다. */
|
|
81
|
-
removalsJournaled: anyPromoted ? removals : null,
|
|
82
|
-
specCoverage: (() => {
|
|
83
|
-
const c: any = snapshot ? readSpecCoverage(snapshot) : null
|
|
84
|
-
if (!c?.operations?.length) return null
|
|
85
|
-
const total = c.operations.length
|
|
86
|
-
const declared = c.operations.filter((o: any) => o.duration === 'declared' || o.duration === 'measured').length
|
|
87
|
-
return { declared, total }
|
|
88
|
-
})(),
|
|
89
|
-
forecastRan: null, // 예측 실행 이력을 남기는 자리가 아직 없다 — 모른다고 말한다
|
|
90
|
-
feed: 'unknown'
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const assessment = assessSuite(facts)
|
|
94
|
-
return { instanceId, ...assessment, spec: SUITE_SPEC, facts }
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* What an area id is — the host's answer for `external: 'space.area'`.
|
|
3
|
-
*
|
|
4
|
-
* The contract declares a location's parent as another location or, when no location has that id, an area of the
|
|
5
|
-
* space (`axis-or-external`), and says the host resolves the external half. Nothing registered a resolver, so on
|
|
6
|
-
* 2026-09-18 every location in the running twin showed its parent as "no component can resolve this relation" —
|
|
7
|
-
* the areas were in this package's own table all along.
|
|
8
|
-
*
|
|
9
|
-
* The lookup is (domain, space, areaId), the table's own unique key: an `areaId` is unique inside a space, so a
|
|
10
|
-
* tenant can hold the same id in two spaces. The space comes from the twin the relation belongs to, which is why
|
|
11
|
-
* `resolve` is given the instance (external-resolver.ts `ExternalResolveContext`). Looking up by tenant alone
|
|
12
|
-
* would answer another space's name as this location's parent.
|
|
13
|
-
*
|
|
14
|
-
* No `href`: the screen that opens an area belongs to the product app, and putting its route here would fix a
|
|
15
|
-
* product screen's address in this package. With no href the screen shows the name and makes no link — that is
|
|
16
|
-
* what the field is for (no dead links). A route is registered the day a screen needs it.
|
|
17
|
-
*/
|
|
18
|
-
import { getRepository } from '@things-factory/shell'
|
|
19
|
-
import { In } from 'typeorm'
|
|
20
|
-
|
|
21
|
-
import { registerExternalResolver, type ExternalRef, type ExternalResolveContext } from '../twin-model/external-resolver.js'
|
|
22
|
-
import { TwinInstance } from '../twin-instance/twin-instance.js'
|
|
23
|
-
import { TwinSpace } from './twin-space.js'
|
|
24
|
-
import { TwinArea } from './twin-area.js'
|
|
25
|
-
|
|
26
|
-
/** The contract's word for this target. Must match `target.entity` or it attaches to no relation. */
|
|
27
|
-
export const SPACE_AREA_ENTITY = 'space.area'
|
|
28
|
-
|
|
29
|
-
export async function resolveAreas(
|
|
30
|
-
domainId: string,
|
|
31
|
-
ids: readonly string[],
|
|
32
|
-
context: ExternalResolveContext,
|
|
33
|
-
warn?: (msg: string) => void
|
|
34
|
-
): Promise<ExternalRef[]> {
|
|
35
|
-
const wanted = [...new Set(ids.map(String).filter(Boolean))]
|
|
36
|
-
if (!wanted.length) return []
|
|
37
|
-
|
|
38
|
-
/* Which space is this twin in? A twin with no space has no areas to point at — every id is then missing. */
|
|
39
|
-
const inst = await getRepository(TwinInstance).findOne({
|
|
40
|
-
where: { domain: { id: domainId } as any, instanceId: context.instanceId }
|
|
41
|
-
})
|
|
42
|
-
const spaceId = inst?.spaceId
|
|
43
|
-
if (!spaceId) {
|
|
44
|
-
warn?.(`[area-resolver] twin "${context.instanceId}" is in no space — its parent ids cannot be areas`)
|
|
45
|
-
return wanted.map(id => ({ id, missing: true }))
|
|
46
|
-
}
|
|
47
|
-
const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId } as any, spaceId } })
|
|
48
|
-
if (!space) {
|
|
49
|
-
warn?.(`[area-resolver] space "${spaceId}" of twin "${context.instanceId}" is not in this tenant`)
|
|
50
|
-
return wanted.map(id => ({ id, missing: true }))
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const rows = await getRepository(TwinArea).find({
|
|
54
|
-
where: { domain: { id: domainId } as any, space: { id: space.id } as any, areaId: In(wanted) }
|
|
55
|
-
})
|
|
56
|
-
const byId = new Map(rows.map(r => [r.areaId, r]))
|
|
57
|
-
|
|
58
|
-
/* An id that is in no area of this space is said to be missing — it is not dropped from the answer. */
|
|
59
|
-
return wanted.map(id => {
|
|
60
|
-
const area = byId.get(id)
|
|
61
|
-
if (!area) return { id, missing: true }
|
|
62
|
-
return area.name ? { id, name: area.name } : { id }
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Registered at boot, once — the same shape as the reference link resolver. */
|
|
67
|
-
export function installAreaResolver(warn?: (msg: string) => void): void {
|
|
68
|
-
registerExternalResolver(
|
|
69
|
-
{
|
|
70
|
-
entity: SPACE_AREA_ENTITY,
|
|
71
|
-
resolve: (domainId, ids, context) => resolveAreas(domainId, ids, context, warn)
|
|
72
|
-
},
|
|
73
|
-
warn
|
|
74
|
-
)
|
|
75
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { TwinSpace } from './twin-space.js'
|
|
2
|
-
import { TwinSpaceRepresentation } from './twin-space-representation.js'
|
|
3
|
-
import { TwinSpaceArea } from './twin-space-area.js'
|
|
4
|
-
import { TwinArea } from './twin-area.js'
|
|
5
|
-
import { TwinSpaceResolver } from './twin-space-resolver.js'
|
|
6
|
-
|
|
7
|
-
export const entities = [TwinSpace, TwinSpaceRepresentation, TwinSpaceArea, TwinArea]
|
|
8
|
-
export const resolvers = [TwinSpaceResolver]
|