@things-factory/headless-twin 10.0.13 → 10.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist-server/engine/ingest-health.d.ts +41 -0
  2. package/dist-server/engine/ingest-health.js +48 -0
  3. package/dist-server/engine/ingest-health.js.map +1 -1
  4. package/dist-server/engine/twin-engine.d.ts +34 -0
  5. package/dist-server/engine/twin-engine.js +180 -6
  6. package/dist-server/engine/twin-engine.js.map +1 -1
  7. package/dist-server/service/reference/reference-adapter.d.ts +26 -0
  8. package/dist-server/service/reference/reference-adapter.js.map +1 -1
  9. package/dist-server/service/reference/reference-assessment.d.ts +11 -1
  10. package/dist-server/service/reference/reference-assessment.js +22 -2
  11. package/dist-server/service/reference/reference-assessment.js.map +1 -1
  12. package/dist-server/service/reference/reference-live.js +18 -0
  13. package/dist-server/service/reference/reference-live.js.map +1 -1
  14. package/dist-server/service/reference/reference-master.d.ts +12 -2
  15. package/dist-server/service/reference/reference-master.js.map +1 -1
  16. package/dist-server/service/twin-forecast/twin-forecast-query.js +24 -1
  17. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
  18. package/dist-server/service/twin-model/epcis-coverage.js +27 -0
  19. package/dist-server/service/twin-model/epcis-coverage.js.map +1 -1
  20. package/dist-server/service/twin-model/isa95-coverage.js +85 -5
  21. package/dist-server/service/twin-model/isa95-coverage.js.map +1 -1
  22. package/dist-server/service/twin-model/item-ref.d.ts +3 -3
  23. package/dist-server/service/twin-model/item-ref.js +4 -4
  24. package/dist-server/service/twin-model/item-ref.js.map +1 -1
  25. package/package.json +3 -3
  26. package/server/engine/ingest-health.ts +78 -0
  27. package/server/engine/twin-engine.ts +199 -6
  28. package/server/service/reference/reference-adapter.ts +23 -0
  29. package/server/service/reference/reference-assessment.ts +39 -4
  30. package/server/service/reference/reference-live.ts +20 -0
  31. package/server/service/reference/reference-master.ts +12 -2
  32. package/server/service/twin-forecast/twin-forecast-query.ts +27 -1
  33. package/server/service/twin-model/epcis-coverage.ts +27 -0
  34. package/server/service/twin-model/isa95-coverage.ts +85 -5
  35. package/server/service/twin-model/item-ref.ts +4 -4
  36. package/test/checkpoint-refuses-empty.test.ts +103 -0
  37. package/test/cursor-stall-not-read-failure.test.ts +126 -0
  38. package/test/item-ref.test.ts +3 -3
  39. package/test/mirror-resumes-from-checkpoint.test.ts +192 -0
  40. package/test/revision-axis.test.ts +13 -2
  41. package/test/status-tally.test.ts +3 -3
  42. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"twin-engine.js","sourceRoot":"","sources":["../../server/engine/twin-engine.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * TwinEngine — operato-twin 커널 인스턴스를 things-factory 위에서 호스팅.\n * integration-base 의 ScenarioEngine 패턴 미러: 메모리 인스턴스 맵 + 백그라운드 tick + pubsub 상태 발행.\n *\n * 커널(zero-dep, ESM+CJS 이중배포)은 CJS require 로 로드(Node 20 CommonJS 소비 — require(ESM) 회피). (vocabulary-guard: allow — Node 런타임 버전 표기)\n * 커널은 결정적 논리 연산 코어 — 이 host 가 전송(pubsub)·영속(TypeORM)·스케줄(tick)·복구(replay)만 얇게 래핑.\n * (설계 SoT: operato-twin/design/integration/things-factory-host.md)\n */\n\nimport { twinLog, twinWarn, twinError } from './log.js'\nimport { pubsub, getRepository, Domain } from '@things-factory/shell'\n/* 저널을 자를 조건은 SQL 이 안다 — 관용구만 쓴다(원시 SQL 은 5개 드라이버에서 갈라진다). */\nimport { And, IsNull, LessThanOrEqual, MoreThan } from 'typeorm'\nimport { cacheService } from '@things-factory/cache-service'\n\nimport type { ReducerCheckpoint } from '@operato/twin-kernel'\nimport type { OeeCheckpoint } from './oee-accumulator.js'\nimport { TwinEvent } from '../service/twin-event/twin-event.js'\nimport { twinEventKeys } from '../service/twin-event/twin-event-keys.js'\nimport { planLiveContinuity, planWarmStart, unwrapState } from './warm-start.js'\nimport { applyDeclarationLayers } from './local-declarations.js'\nimport { isOfDomain, parseRuntimeKey, runtimeKey } from './runtime-key.js'\nimport { routeCommand } from './command-routing.js'\nimport { TwinInstance } from '../service/twin-instance/twin-instance.js'\n/* 자극의 집은 원본이다(ADR-0029) — 그 행을 읽고 쓴다. */\nimport { TwinReference } from '../service/reference/twin-reference.js'\nimport { TwinStructure } from '../service/twin-structure/twin-structure.js'\nimport { TwinSpace } from '../service/twin-space/twin-space.js'\nimport { utcOffsetOf } from '../service/reference/reference-master.js'\nimport { TwinSpaceRepresentation } from '../service/twin-space/twin-space-representation.js'\nimport { TwinSpaceArea } from '../service/twin-space/twin-space-area.js'\nimport { TwinArea } from '../service/twin-space/twin-area.js'\nimport { masterToTwin, type ReferenceMaster } from '../service/reference/reference-master.js'\nimport { resolveIngestSpace } from '../service/reference/ingest-space.js'\nimport { type IngestWarning, describeWarnings, unresolvedReference, projectionFailed, structureAdopted, generationWithoutTimeZone } from '../service/reference/reference-master.js'\nimport { projectStructure } from '../service/twin-model/project-structure.js'\nimport { buildTravelEstimator, chainEstimators } from './travel-estimator.js'\nimport { buildMeasuredEstimator } from './measured-estimator.js'\nimport { buildYieldEstimator } from './measured-yield.js'\nimport { planStimulus, withStimulus } from './declared-stimulus.js'\nimport { readRestartPolicy, type RestartPolicy } from './restart-policy.js'\nimport { describeModelBasis, type ModelBasis } from './model-basis.js'\nimport { computeTwinKpi } from './kpi-query.js'\nimport { createHash } from 'node:crypto'\n\nimport { buildEntityDeltas } from '@things-factory/headless-twin/dist-shared/entity-delta.js'\nimport { fleetLoad, judgeCycle, loadSummary, newLoadMeter, recordFork, recordPhase, slowTickMessage, type LoadMeter, type LoadPhase } from './load-meter.js'\nimport { loopLag } from './loop-lag.js'\nimport { touchedItemKeys } from '@things-factory/headless-twin/dist-shared/touched-items.js'\nimport { diffStructures, type StructureDiff } from './structure-diff.js'\nimport { OeeAccumulator, withLiveOee } from './oee-accumulator.js'\nimport { withLiveAttentions } from './live-attentions.js'\nimport { digestAttentions, mergeLensAttentions } from './attention-digest.js'\n\nimport { liveFeedStateOf } from './live-feed-registry.js'\nimport {\n ingestHealth,\n newIngestLedger,\n recordIngest,\n recordReadFailure,\n clearReadFailure,\n rollIngestWindow,\n /* 별칭 — 같은 이름의 정적 메서드와 헷갈리지 않게(그 메서드가 이것을 부른다). */\n recordJournalWrite as recordLedgerWrite,\n type IngestHealthView,\n type IngestLedger,\n type IngestWindow\n} from './ingest-health.js'\nimport { EMS_PROPERTY } from '@operato/twin-kernel'\nimport type { TwinKernel, TwinModelDef, StructureShift, SubscriptionMessage, TwinRuntime as TwinRuntimeType, CanonicalEnvelope } from '@operato/twin-kernel'\n\n/* 커널 런타임 로드 — CJS 번들(dist-cjs). 타입은 위 import type 로. replay = 이벤트열→상태 재구성(복구·시간여행). */\nconst { WmsKernel, YmsKernel, MesKernel, EmsKernel, TwinRuntime, StateProjector, replay, replayFrom, replayWithCheckpoint, replaySegments, readBoardLocations, readBoardEquipment, DOMAIN_CATALOG, OP_EVENT, validateScenario } = require('@operato/twin-kernel')\n\nconst KERNELS: Record<string, any> = { wms: WmsKernel, yms: YmsKernel, mes: MesKernel, ems: EmsKernel }\n\n/**\n * 시각축을 구할 때 한 번에 띄우는 트윈 수.\n *\n * 트윈마다 왕복이 둘이라, 공간에 트윈이 수백이면 동시 왕복도 수백이 된다 — 커넥션 풀이 마르면 이\n * 함수 하나 때문에 다른 질의가 줄을 선다. 20이면 왕복 40개로 지연은 감추면서 풀은 남는다.\n */\nconst TIME_RANGE_FANOUT = 20\n\n/**\n * DB 가 준 시각을 epoch ms 로 — **모양이 드라이버마다 다르다.**\n *\n * 집계(MIN/MAX)의 반환은 드라이버가 정한다: sqlite 는 문자열, pg·mysql·mssql 은 `Date`. 엔티티\n * 하이드레이션을 건너뛰면 TypeORM 의 날짜 변환도 함께 건너뛰므로 받는 쪽에서 한 번 정규화한다.\n *\n * ── 시간대를 잃지 않는다 (시험이 잡았다) ────────────────────────────────────\n * 처음에 `Date.parse(String(v))` 로 두었더니 **9시간이 밀렸다.** sqlite 는 UTC 로 저장한 값을\n * `2026-01-15 09:00:00.000` 처럼 **시간대 표시 없이** 돌려주는데, 그 형태를 `Date.parse` 는 **로컬\n * 시각**으로 읽는다(여기가 KST 라 UTC 00:00 이 됐다). 원래 코드가 이 함정을 피한 것은 TypeORM 이\n * 하이드레이션에서 먼저 `Date` 로 바꿔 줬기 때문이다 — 그 단계를 건너뛴 대가를 여기서 치른다.\n *\n * 그래서 시간대 표시가 **없는 문자열은 UTC 로 읽는다**(TypeORM 이 UTC 로 적으므로). 표시가 있으면\n * 그대로 믿고, `Date` 는 손대지 않는다.\n *\n * 읽을 수 없는 값은 **없음(`null`)** 이다 — 0 으로 떨어뜨리면 1970년이 시각축의 시작이 된다.\n */\nfunction parseTime(v: unknown): number | null {\n if (v == null) return null\n if (v instanceof Date) return Number.isFinite(v.getTime()) ? v.getTime() : null\n\n const s = String(v).trim()\n if (!s) return null\n /* 끝에 `Z` 나 `±hh:mm` 이 붙어 있으면 시간대를 아는 문자열이다 — 그대로 믿는다. */\n const zoned = /(?:Z|[+-]\\d{2}:?\\d{2})$/.test(s)\n const t = Date.parse(zoned ? s : `${s.replace(' ', 'T')}Z`)\n return Number.isFinite(t) ? t : null\n}\n\n/**\n * 종류 문자열 → 커널. **모르는 값이면 오류를 낸다.**\n *\n * 예전에는 표를 찾고 없으면 WmsKernel 로 떨어졌다. `kind` 는 검증 없는 자유 문자열(`@Arg('kind') kind: string`)\n * 이라 오타 하나·대소문자 하나로 야드/생산 트윈이 **조용히 창고 커널로 돌았다.** 오류가 없으니 화면에는\n * 트윈이 정상으로 보이고, 안에서 도는 규칙만 다른 도메인의 것이다. 예측 경로가 가장 나쁘다 —\n * 야드의 미래를 창고 규칙으로 실행해 놓고 숫자만 뜬다.\n *\n * 틀린 공장을 조용히 띄우는 것보다 뜨지 않는 편이 낫다.\n */\nfunction kernelFor(kind: string): any {\n const K = KERNELS[kind]\n if (!K) throw new Error(`unknown twin kind \"${kind}\" — expected one of ${Object.keys(KERNELS).join(' | ')}`)\n return K\n}\n\n/** `observe()` 를 갖지 않은 커널을 만난 적이 있는가 — 경고를 한 번만 낸다(틱마다 쏟지 않는다). */\nlet observeUnavailableWarned = false\n\n/**\n * **이 커널의 진실이 원본에서 온다고 선언한다** — 그리고 선언이 닿지 않았으면 말한다.\n *\n * ── 무엇이 틀렸나 (2026-08-21) ──────────────────────────────────────────────\n * 예전에는 `kernel.observe?.()` 였다. 옵셔널 호출이라 **메서드가 없으면 조용히 아무것도 하지 않는다.**\n * 설치된 커널 0.7.39 에는 그 메서드가 없으므로, 지금 배포본에서는 미러가 관측 구동으로 선언되지\n * 않는다 — 그런데 코드를 읽으면 선언한 것처럼 보인다.\n *\n * 그 차이가 실제 거동을 가른다: 관측 구동은 원본의 빈틈을 받아들이고 세지만, 시뮬로 오인된 미러는\n * **멈춘다.** 즉 「관용이 켜진 줄 알았는데 안 켜져 있다」가 조용히 지나가고, 장애가 났을 때 원인이\n * 커널에 있는 것처럼 보인다 — 원인은 버전이다.\n *\n * 그래서 옵셔널 호출을 없애고, 없으면 **한 번 경고한다.** 커널이 배포되면 이 경고는 사라진다.\n */\nfunction declareObserved(kernel: any, what: string): void {\n if (typeof kernel?.observe === 'function') {\n kernel.observe()\n return\n }\n if (observeUnavailableWarned) return\n observeUnavailableWarned = true\n twinWarn(\n `[twin-engine] ${what}: kernel has no observe() — this mirror is not declared observation-driven. ` +\n 'Source gaps will stop it instead of being tolerated and counted. Deploy a kernel that provides observe().'\n )\n}\n\n/* 라이브 처리량 계측(모니터) — 유입/브로드캐스팅/저널률·백로그. 실 동기 인터페이스 부하를 읽는 일급 지표. */\ninterface TwinMetrics {\n ingestedTotal: number // 누적 유입 이벤트\n broadcastTotal: number // 누적 브로드캐스팅 횟수\n journaledTotal: number // 누적 저널 기록 이벤트\n ingestRate: number // 최근 유입률(ev/s)\n broadcastRate: number // 최근 브로드캐스팅률(회/s)\n journalRate: number // 최근 저널률(ev/s)\n /**\n * **지금 대기 중인** 저널 건수 — 아직 DB 로 나가지 않은 것.\n *\n * ── 무엇이 틀렸었나 (2026-08-21) ──────────────────────────────────────────\n * 예전에는 「마지막 flush 에서 쓴 건수」를 여기 넣었다. 그런데 200ms 마다 모아 한 문으로 넣는 것은\n * **정상 동작**이다(그렇게 만든 것이 어제 고친 성능 작업이다). 그래서 정상적으로 10건을 쓴 직후\n * 화면에 「밀림 10」 경고가 떴고, 다음 flush 까지 그 값이 남았다 — 큐는 이미 0 인데도.\n *\n * 운영자에게 그것은 「저장이 10건 밀려 있다」로 읽힌다. 거짓 경보는 참 경보를 죽인다.\n *\n * 이제 이 값은 **지금 남아 있는 것**이다: 다 나갔으면 0 이고, 정말로 쌓이는 중이면 그 수가 자란다.\n */\n backlog: number\n // 창(window) 집계용 내부 누적\n _accIngest: number\n _accBroadcast: number\n _accJournal: number\n _windowStartMs: number\n}\n\n/*\n * 재기동 정책은 **선언이고 기본값이 없다** — 정의·판정은 `engine/restart-policy.ts` 가 든다(ADR-0029 §2).\n *\n * 예전에는 여기에 `DEFAULT_REALITY_MODE = 'sim-experiment'` 가 있었고, 미선언이 조용히 **저널 초기화**로\n * 떨어졌다. 그 관용은 값이 하나 어긋나는 순간 이력을 지우는 길이 된다 — 그래서 없앴다.\n */\nexport type { RestartPolicy } from './restart-policy.js'\n\n/* 인메모리 라이브 런타임 홀더(영속 엔티티 TwinInstance 와 구분). */\ninterface InstanceRuntime {\n /** 부하 계기판 — 작업별 소요. 시뮬·라이브 모두 붙는다(누가 루프를 점유하는지 보려면 둘 다 필요하다). */\n load?: LoadMeter\n /** 현실 출처 선언(§0 프레임 ①). 부팅 거동(reset/resume/resync)의 근거. */\n restartPolicy?: RestartPolicy\n id: string\n domainId: string\n domain?: any // 라이브 바인딩(data 채널)용 Domain 객체(subdomain 필터). start 시 비동기 해석.\n runtime?: TwinRuntimeType // sim: 커널 런타임(tick/subscribe/dispatch). live 는 projector 사용.\n kernel?: any // sim: ForecastTwin(fork/getSnapshot/tick/scenario). live 미사용.\n mode?: 'sim' | 'live' // 상태 드라이버 — sim=커널 tick / live=projector 미러(face2-inbound-live). 미지정=sim.\n /** 이 트윈이 선 현장 — 같은 현장의 트윈끼리 서로의 설비 상태를 읽을 수 있게 하는 열쇠. */\n spaceId?: string\n /**\n * live 의 상태 접근 어댑터 — 이제 **관측 모드 커널**을 가리킨다(`kernel` 과 같은 것).\n * 이름은 소비처 호환으로 남았고, P3 에서 커널 어휘로 정리하면 사라진다.\n */\n projector?: any\n oee?: OeeAccumulator // live: OEE 계산 층(이벤트 누적 → equipment payload 보강). sim 은 커널이 계산.\n unsub: () => void\n /**\n * 방금 인입한 봉투들 — 커널이 그것을 재방출할 때 **저널에 두 번 적지 않기** 위한 표시.\n * 라이브만 쓴다(sim 은 커널이 스스로 낸 것만 흘린다). 약한 참조라 따로 비울 것이 없다.\n */\n applying?: WeakSet<object>\n timer?: any\n /** 엔티티별 마지막 발행 시그니처 — 값이 바뀐 엔티티만 재발행(무변화 반복 push 방지). */\n entitySigs?: Map<string, string>\n /** live 브로드캐스팅 병합(ingest-scale §4.4) — ingest 마다 브로드캐스팅하지 않고 dirty 표시 → coalescer tick 이 주기 브로드캐스팅. */\n dirty?: boolean\n /**\n * 이 창에 **건드린 물품 태그** — 브로드캐스팅이 그것만 만든다.\n *\n * `undefined` 는 「말할 수 없다」다(낯선 사건이 하나라도 왔다) → 전부 만든다. 빈 집합은 「물품은\n * 하나도 건드리지 않았다」이고, 그 둘은 다른 사실이다.\n */\n dirtyItems?: Set<string>\n /** 다음 브로드캐스팅에서 전부 만들어야 하나 — 주기마다 한 번은 그물로 전부 만든다. */\n fullBroadcastDue?: boolean\n /** 전부 만들기까지 남은 창 수. */\n fullBroadcastCountdown?: number\n /** live 저널 결선 — ingest 이벤트를 모았다가 coalescer tick 에서 배치 기록(이벤트마다 DB write 금지). */\n pendingJournal?: any[]\n /** live 저널 revision 카운터(sim 의 delta revision 대응 — 시간여행·히스토리 노브 앵커). */\n revision?: number\n /** live 처리량 계측(모니터, ④-1). */\n metrics?: TwinMetrics\n}\n\n/**\n * 트윈이 **스스로 멈춘 이유** — 문장이 아니라 코드다.\n *\n * 서버가 만든 영어 문장을 그대로 실으면 한국어·일본어 화면에 그 영어가 뜬다. 이 시스템은 거절 메시지에서\n * 같은 결론에 이르렀다(코드+파라미터를 내고 화면이 옮긴다). `reason` 만은 원문 그대로다 — 커널·런타임이\n * 낸 오류 문구는 옮길 수 있는 어휘가 아니고, 옮기려 들면 원인을 잃는다.\n */\nexport interface StopNote {\n code: 'starved' | 'tick-failed'\n params: Record<string, string | number>\n}\n\nexport class TwinEngine {\n /*\n * 기동 중인 런타임 — **키는 `runtimeKey(domainId, instanceId)`** 다(`runtime-key.ts` 에 이유).\n *\n * 예전엔 `instanceId` 하나로 키를 잡았다. 그런데 정체성은 `(domain, instanceId)` 이고 DB 유일성도\n * 그쪽이라, 두 테넌트가 같은 id 를 쓰면(레퍼런스 경로가 소스 이름을 id 로 쓴다) 한 자리를 다퉜다.\n * **엔진 밖에서 이 맵을 직접 색인하지 않는다** — `owns`·`runtime`·`kernel` 같은 접근자를 쓴다.\n */\n static instances: Record<string, InstanceRuntime> = {}\n /** 라이브 런타임이 없을 때(복구 후 미기동) 저널에서 재구성한 상태 캐시. */\n /** 웜스타트 씨앗 — `instances` 와 **같은 키**(겹치면 남의 스냅샷으로 재고가 섞인다). */\n static recovered: Record<string, any> = {}\n static TICK_MS = 1000\n\n /*\n * ── 굶김 안전망 (2026-08-14) ──────────────────────────────────────────────\n * 시뮬 틱은 **메인 이벤트 루프**에서 돈다. 그래서 한 트윈의 틱이 길어지면 그 시간만큼 호스트 전체가\n * 멈춘다 — HTTP·구독·다른 트윈의 틱까지. 실측으로 `order-check` 의 틱 하나가 34.9초였고, 그 사이\n * 구독자가 아무것도 빼내지 못해 pubsub 이 넘쳐 프로세스가 죽었다.\n *\n * 브로드캐스팅 반복은 걷어냈지만(`flushLiveBroadcasts` 로 병합) **커널 틱 자체는 여전히 메인 루프에 있다.**\n * 근본 해결은 분산이고 그것은 이연됐다 — 그때까지의 안전망이 이 셋이다.\n *\n * 판정을 예산(500ms)이 아니라 **굶김 문턱**으로 따로 둔다: 조금 느린 트윈은 계기판이 말하게 두고\n * (경고), 호스트를 굶기는 트윈만 멈춘다. 한 번으로 멈추지 않는다 — 웜스타트 직후의 첫 틱은 원래\n * 무겁다(복구한 상태를 처음 접는다). **연속**으로 이어질 때가 구조적으로 느린 것이다.\n */\n /*\n * ── 틱을 **한 순간에 몰지 않는다** (2026-08-21 실측) ────────────────────────\n * 트윈마다 `setInterval(TICK_MS)` 를 부팅 때 나란히 세우면, 스무 개가 **같은 밀리초에** 깨어난다.\n * 각자의 틱이 짧아도(실측: 물품 2,400 개에서 0.23ms) 그 순간에는 스무 개가 한 줄로 붙어 실행되고,\n * 그 사이 도착한 HTTP 요청은 전부 뒤에서 기다린다. 초당 한 번의 정체가 「누를 때마다 걸린다」로\n * 나타나는 자리다.\n *\n * 그래서 첫 발화만 간격 안에서 **고르게 흩는다** — 총 작업량은 같고 한 순간의 최대치만 낮아진다.\n * 트윈이 간격보다 많아지면 다시 겹치므로, 그때는 이 흩기가 아니라 분산이 답이다(이연됨).\n */\n /** 부팅 때 트윈 하나를 되살린 뒤 루프를 비워 주는 시간(ms) — 그 사이 도착한 요청이 처리된다. */\n static BOOT_YIELD_MS = 25\n private static tickPhase = 0\n /**\n * 흩어진 첫 발화 뒤 주기 틱. **핸들은 항상 진짜 타이머**다 — 정지하는 쪽이 `clearInterval(inst.timer)`\n * 하나로 끝내야 하므로, 첫 발화 전에는 그 `setTimeout` 을, 이후에는 `setInterval` 을 같은 자리에 둔다\n * (감싼 객체를 주면 `clearInterval` 이 아무 일도 하지 않고 트윈이 멈추지 않는다 — 조용한 결함이 된다).\n */\n private static startTickTimer(fn: () => void, hold: (t: any) => void): any {\n const spread = Math.max(1, Math.round(this.TICK_MS / 20))\n const offset = (this.tickPhase = (this.tickPhase + spread) % this.TICK_MS)\n const first = setTimeout(() => {\n const interval = setInterval(fn, this.TICK_MS)\n if (typeof interval?.unref === 'function') interval.unref()\n hold(interval) // 정지 경로가 지울 대상을 바꿔 준다\n fn()\n }, offset)\n if (typeof first?.unref === 'function') first.unref()\n return first\n }\n\n /** 굶김 문턱 — 틱 간격의 배수(1초 간격이면 5초). 이 시간만큼 호스트가 멈춘다. */\n static STARVE_FACTOR = 5\n /** 연속 몇 번이면 멈추나 — 3번이면 15초를 굶긴 셈이고, 그건 우연이 아니다. */\n static STARVE_STREAK = 3\n private static starveStreak = new Map<string, number>()\n /**\n * 왜 멈췄나 — **화면이 그대로 말할 수 있게.** 스스로 멈춘 트윈이 이유 없이 「정지」로만 보이면\n * 사람은 자기가 멈춘 줄 안다. 메모리에만 둔다(재기동하면 사라진다 — 그때는 「모른다」가 사실이다).\n */\n private static stopNotes = new Map<string, StopNote>()\n\n /* 최신 스냅샷 영속(warm-start) — 재기동 시 저널 fold-from-0 replay 대신 마지막 라이브 스냅샷으로 복원.\n * 프레임워크 공통 cache-service(@things-factory/cache-service) 재사용(재발명 금지, framework-leverage §4).\n * 저널은 그대로 진실(시간여행/history replay 무변경) — 캐시는 display-only 웜스타트 최적화. */\n static SNAPSHOT_CACHE_ID = 'twin-snapshot'\n /*\n * ── 재개점 **사슬** — 과거를 물었을 때 목표 직전에서 접기 위해 (2026-08-18) ──\n *\n * 최신 재개점 하나로는 시간여행을 도울 수 없다: 그것은 언제나 목표보다 **뒤**에 있다. 그래서 지점을\n * 여러 개 남긴다. 다만 그것들은 각각 상태 전체를 들고 있어 무겁다 — 한 행에 몰아 넣으면 거대한\n * JSON 이 되므로 **지점마다 따로 두고 색인을 둔다**(cache-service 는 해시 키 조회라 열거가 안 된다).\n *\n * 간격은 리비전 눈금으로 잡는다(`CHAIN_STRIDE`): 눈금을 넘을 때만 한 지점을 남기므로, 저널이 빠르게\n * 자라는 트윈에서도 지점 수가 폭발하지 않는다. 오래된 것부터 버리고 최근 `CHAIN_KEEP` 개만 든다 —\n * 과거로 깊이 갈수록 지점이 없어 0부터 접는 것은 **알려진 한계**다(무한 보관보다 정직하다).\n */\n static CHAIN_CACHE_ID = 'twin-fold-chain'\n static CHAIN_INDEX_CACHE_ID = 'twin-fold-chain-index'\n static CHAIN_STRIDE = 5000 // 리비전 눈금 — 이 간격을 넘을 때만 한 지점을 남긴다\n static CHAIN_KEEP = 5 // 최근 몇 지점을 들고 있나(그보다 과거는 0부터 접는다)\n static SNAPSHOT_TTL_S = 7 * 24 * 3600 // 7일 — 정상 다운타임 생존, 만료 시 저널 replay 폴백\n static CHECKPOINT_MS = 20000 // 체크포인트 주기(핫 브로드캐스트 경로와 분리, O(state) 스로틀)\n /**\n * **저널 보존 — 지우는 것은 선언이 있을 때만 한다.**\n *\n * ── 왜 필요한가 (2026-08-22 실측) ─────────────────────────────────────────\n * 개발 저널이 시간당 **581,794행 · 0.85GB** 로 자랐다(하루 20GB). 데모 MES 트윈 셋이 전체의 **97%**\n * 를 만들고 지우는 것이 없었다. 오늘 고친 것들은 「그 크기에서도 질의가 빠르게」이고, **크기 자체를\n * 줄이는 것은 아무것도 없었다.** 그러면 며칠마다 같은 자리로 돌아온다.\n *\n * ── 그런데 저널을 지우는 것은 사실을 잃는 일이다 ──────────────────────────\n * 그래서 세 규율을 지킨다.\n *\n * ① **선언이 없으면 아무것도 지우지 않는다.** 기본값은 없음이다 — 조용히 지우는 편이 조용히 쌓는\n * 것보다 나쁘다. 지우는 것은 사람이 정한다.\n * ② **체크포인트가 대신할 수 있는 만큼만.** 스냅샷이 없거나 그 리비전을 넘는 자리는 건드리지 않는다.\n * 주석이 「만료 시 저널 replay 폴백」이라고 적어 둔 그대로 — 스냅샷이 사라지면 저널이 **유일한**\n * 복구 수단이므로, 둘을 함께 잃으면 그 트윈의 상태는 되돌릴 수 없다.\n * ③ **지운 것을 말한다.** 몇 건을 어느 시각까지 지웠는지 로그에 남긴다. 조용히 줄어든 저널은\n * 「없었던 일」과 구별되지 않는다.\n *\n * 그리고 보존 기간은 **스냅샷 TTL(7일)보다 짧을 수 없다.** 더 짧으면 스냅샷이 살아 있는데 그것이\n * 가리키는 앞쪽 저널이 없는 구간이 생기고, 시간여행·계보 추적이 그 구간에서 조용히 빈다.\n */\n static JOURNAL_RETENTION_DAYS?: number = undefined\n /**\n * **도메인마다 다른 보존 기간을 앱이 답한다** — 엔진은 그 값이 어디서 오는지 모른다.\n *\n * 보존 기간은 테넌트의 정책이다: 한 고객은 30일이 필요하고 다른 고객은 7일이면 된다. 그런데 엔진이\n * `Setting` 을 읽게 만들면 **엔진이 화면 관심사를 알게 된다** — 방향이 거꾸로다(엔진은 커널의 호스트이고\n * 그 위에 어떤 화면이 있는지 몰라야 한다).\n *\n * 그래서 시임을 둔다. 앱이 이 함수를 심고, 그 안에서 `Setting` 이든 다른 무엇이든 읽는다. 심지 않으면\n * `JOURNAL_RETENTION_DAYS`(설정 파일에서 온 프로세스 기본값)가 답한다.\n *\n * `undefined` 를 돌려주면 **그 도메인은 지우지 않는다** — 「모른다」를 「지워도 된다」로 읽지 않는다.\n */\n static retentionDaysOf?: (domainId: string) => Promise<number | undefined>\n static RETENTION_SWEEP_MS = 10 * 60 * 1000 // 10분마다 한 번 — 지우는 일은 급하지 않다\n private static retentionTimer?: any\n private static checkpointTimer?: any\n\n /** 최신 스냅샷을 cache-service 에 체크포인트(도메인+instanceId 키). display-only·비차단·오류흡수. */\n static async persistSnapshot(domainId: string, instanceId: string): Promise<void> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n if (!inst) return\n /*\n * **봉투가 아니라 상태를 저장한다.** `snapshot()` 은 시뮬에서 `runtime.resync()` 봉투를 주는데,\n * 그것을 다시 `{revision, state}` 로 감싸 넣어 왔다 → 꺼낸 값에 축이 하나도 없어 웜스타트가\n * 조용히 넘어갔다(저널에 수천 건이 있어도 트윈이 빈 채로 떴다).\n */\n const state = unwrapState(this.snapshot(domainId, instanceId))\n if (!state) return\n const revision = inst.revision ?? state.revision ?? 0\n /* 구조 리비전도 함께 — 읽는 쪽이 \"이 상태가 지금의 공장인가\" 를 가릴 수 있어야 한다. */\n const { structureRev } = await this.tipOf(domainId, instanceId).catch(() => ({ structureRev: null }) as any)\n await cacheService.setInCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId }, { revision, state, structureRev }, this.SNAPSHOT_TTL_S)\n }\n\n /**\n * 접기의 **재개점** — 리듀서 내부 상태 전부 + 가동 누적기.\n *\n * 스냅샷(`state`)은 소비처가 보는 값이라 이어 접기의 씨앗이 되지 못한다(보류된 담김·집합·반영 못 한\n * 사건 집계가 없다 — 그 상태로 뒤를 접으면 0부터 접은 결과와 조용히 달라진다). 그래서 씨앗은 따로 든다.\n */\n private static readonly FOLD_NOTE = 'reducer + oee checkpoint — the seed for folding only the tail'\n\n /** 체크포인트된 최신 스냅샷 로드(없으면 null). getFromCache 는 CacheStore 엔티티를 반환 → 페이로드는 .value. */\n static async loadSnapshot(\n domainId: string,\n instanceId: string\n ): Promise<{ revision: number; state: any; structureRev?: number | null; fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } } | null> {\n const entry = await cacheService.getFromCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId })\n return (entry as any)?.value ?? null\n }\n\n /**\n * 접은 상태를 스냅샷으로 남긴다 — **라이브가 아니어도.**\n *\n * `persistSnapshot` 은 기동 중인 인스턴스에서만 뜬다(메모리가 진실이므로 옳다). 그런데 **멈춘**\n * 트윈을 조회할 때마다 저널을 전량 다시 접고 있었다(23,731건짜리 트윈에서 4.6초). 그 폴드의 결과를\n * 남겨 두면 **처음 한 번만 느리다.**\n *\n * `structureRev` 를 함께 적는다: 이벤트가 하나도 안 늘어도 구조를 갈아치우면(재프로비저닝) 그\n * 상태는 낡은 것이다. 리비전만 보면 새 설비가 없는 옛 상태를 \"지금\" 으로 내게 된다.\n */\n static async saveFoldedSnapshot(\n domainId: string,\n instanceId: string,\n value: { revision: number; state: any; structureRev?: number | null; fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } }\n ): Promise<void> {\n if (!value?.state) return\n await cacheService\n .setInCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId }, value, this.SNAPSHOT_TTL_S)\n .catch((err: any) => twinError(`[twin-engine] snapshot save fail \"${instanceId}\"`, err?.message ?? err))\n }\n\n\n /** 사슬 색인 — 어떤 리비전 지점을 들고 있나(최신순 아님, 오름차순). */\n private static async chainIndex(domainId: string, instanceId: string): Promise<number[]> {\n const entry = await cacheService.getFromCache(this.CHAIN_INDEX_CACHE_ID, { domainId, instanceId }).catch(() => null)\n const revs = (entry as any)?.value?.revisions\n return Array.isArray(revs) ? revs.filter((r: any) => Number.isFinite(r)).sort((a: number, b: number) => a - b) : []\n }\n\n /**\n * 목표 이전의 **가장 가까운 지점**을 고른다 — 없으면 `null`(0부터 접는다).\n *\n * 시각으로 물었으면 그 지점의 마지막 사실 시각이 목표 이내여야 한다(리비전만 보면 목표보다 뒤의\n * 사실이 씨앗에 섞인다). 구조가 바뀐 트윈에서는 쓰지 않는다 — 마디를 건너뛴 씨앗은 그 경계의\n * 판정을 잃는다(그 경우는 0부터 접는 것이 옳다).\n */\n private static async chainSeedFor(\n domainId: string,\n instanceId: string,\n target: { revision?: number; timeMs?: number }\n ): Promise<{ revision: number; eventTime?: string; structureRev?: number | null; fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } } | null> {\n const revs = await this.chainIndex(domainId, instanceId)\n if (!revs.length) return null\n for (const revision of [...revs].reverse()) {\n if (target.revision != null && revision > target.revision) continue\n const entry = await cacheService.getFromCache(this.CHAIN_CACHE_ID, { domainId, instanceId, revision }).catch(() => null)\n const value = (entry as any)?.value\n if (!value?.fold?.reducer) continue\n if (target.timeMs != null) {\n const t = value.eventTime ? Date.parse(String(value.eventTime)) : NaN\n /* 시각을 모르는 지점은 쓰지 않는다 — 목표 이내인지 가릴 수 없다(짐작하지 않는다). */\n if (!Number.isFinite(t) || t > target.timeMs) continue\n }\n return value\n }\n return null\n }\n\n /** 눈금을 넘었으면 한 지점을 남긴다 — 오래된 것은 버린다(색인도 함께 줄인다). */\n private static async keepChainPoint(\n domainId: string,\n instanceId: string,\n /*\n * **보기(state)는 담지 않는다** (2026-08-18 실측으로 고침).\n *\n * 처음에는 상태까지 담았더니 지점 하나가 **11.4 MB** 였다(27만 건 트윈). 사슬이 필요한 것은 씨앗\n * (재개점)뿐이고, 소비처가 보는 값은 그 씨앗에서 다시 만들어진다 — 같은 사실을 두 번 저장하지 않는다.\n */\n value: { revision: number; eventTime?: string; structureRev?: number | null; fold: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } }\n ): Promise<void> {\n const revs = await this.chainIndex(domainId, instanceId)\n const newest = revs.length ? revs[revs.length - 1] : -Infinity\n if (value.revision - newest < this.CHAIN_STRIDE) return // 아직 눈금을 넘지 않았다\n const next = [...revs, value.revision].slice(-this.CHAIN_KEEP)\n const dropped = revs.filter(r => !next.includes(r))\n await cacheService.setInCache(this.CHAIN_CACHE_ID, { domainId, instanceId, revision: value.revision }, value, this.SNAPSHOT_TTL_S)\n await cacheService.setInCache(this.CHAIN_INDEX_CACHE_ID, { domainId, instanceId }, { revisions: next }, this.SNAPSHOT_TTL_S)\n /*\n * 버린 지점은 **색인에서만** 빠진다 — 공용 캐시에 삭제 API 가 없다(`ICacheService` 는 get·set·\n * clearStaleCache 뿐이다). 그래서 값은 TTL(7일)까지 남는다: 아무도 닿지 못하지만 자리는 차지한다.\n * 지금 규모에서 감당할 수 있는 낭비이고, 공용 모듈에 삭제를 여는 것은 다른 소비처까지 함께 볼\n * 일이라 여기서 몰래 하지 않는다 — **알려진 한계로 적어 둔다.**\n */\n if (dropped.length) console.info(`[twin-engine] \"${instanceId}\" fold chain dropped ${dropped.join(', ')} from the index (values expire with the cache TTL).`)\n }\n\n /** 이 트윈 저널의 끝 리비전 · 최신 구조 리비전 — 스냅샷이 지금의 사실인지 가리는 두 값. */\n private static async tipOf(domainId: string, instanceId: string): Promise<{ revision: number; structureRev: number | null }> {\n const [tip, newest] = await Promise.all([\n getRepository(TwinEvent).findOne({ where: { domain: { id: domainId }, instanceId }, order: { revision: 'DESC' } }),\n getRepository(TwinStructure).findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n ])\n return { revision: tip?.revision ?? 0, structureRev: newest?.rev ?? null }\n }\n\n /**\n * **저널을 보존 기간까지만 둔다** — 체크포인트가 대신할 수 있는 만큼만 지운다.\n *\n * 한 인스턴스에서 지우는 조건은 **둘 다** 만족해야 한다.\n *\n * · `createdAt` 이 보존 기간보다 오래됐다 — **행이 쓰인 실제 시각**이 기준이다\n * · `revision` 이 **체크포인트 리비전 이하**다 — 그 앞은 스냅샷이 대신한다\n *\n * ── 왜 `eventTime` 이 아니라 `createdAt` 인가 (2026-08-22 실측으로 고침) ────\n * 처음에 `eventTime` 으로 적었다. 그것은 **트윈의 시계**다 — 시뮬레이션은 자기 시계로 사건을 찍고,\n * 그 시계는 실제 시각과 무관하게 앞서거나 뒤선다. 실측:\n *\n * order-check 가장 늦은 eventTime = 2027-06-08 ← 실제 시각보다 10개월 앞\n * hatio-mx2 2026-01-01 ~ 지금 ← 7개월치를 한 번에 지우게 된다\n *\n * 즉 「7일」이 트윈마다 다른 뜻이 된다: 시계가 앞선 트윈은 영원히 지워지지 않고, 과거부터 찍은 트윈은\n * 거의 전부가 한 번에 지워진다. **보존은 저장 나이의 문제**이고 저장 나이는 실제 시계다.\n *\n * `createdAt` 은 그 행이 DB 에 쓰인 시각이고 1,599만 행 전부 채워져 있다(확인함). 도메인 시각을\n * 정책에 쓰지 않는다 — 그 둘을 섞으면 시뮬과 미러에서 같은 설정이 다르게 동작한다.\n *\n * 스냅샷이 없으면 **그 인스턴스는 건드리지 않는다.** 저널이 유일한 복구 수단인 상태이므로, 지우면\n * 그 트윈의 상태를 되돌릴 수 없다. 「지울 수 없었다」는 사실도 함께 센다 — 조용히 넘기면 「보존이\n * 도는데 왜 안 줄어드나」가 된다.\n *\n * `createdAt` 이 빈 옛 행은 **지우지 않는다**(시각을 모르는 것을 「오래됐다」로 읽지 않는다).\n *\n * 드라이버 다섯을 다 지나야 하므로 raw SQL 을 쓰지 않는다 — 조건 삭제는 쿼리빌더가 이식한다.\n */\n static async pruneJournal(domainId: string): Promise<{ deleted: number; instances: number; skipped: string[] }> {\n /* 도메인의 정책이 먼저다(§`retentionDaysOf`). 없으면 프로세스 기본값. 둘 다 없으면 지우지 않는다. */\n const perDomain = this.retentionDaysOf ? await this.retentionDaysOf(domainId).catch(() => undefined) : undefined\n const days = perDomain ?? this.JOURNAL_RETENTION_DAYS\n if (!days || days <= 0) return { deleted: 0, instances: 0, skipped: [] }\n\n /* 보존 기간은 스냅샷 TTL 보다 짧을 수 없다 — 짧으면 스냅샷이 가리키는 앞쪽이 비는 구간이 생긴다. */\n const minDays = this.SNAPSHOT_TTL_S / 86400\n const effectiveDays = Math.max(days, minDays)\n if (effectiveDays !== days) {\n twinWarn(\n `[twin-engine] journal retention ${days}일은 스냅샷 TTL(${minDays}일)보다 짧다 — ${effectiveDays}일로 올린다 ` +\n '(더 짧으면 스냅샷이 살아 있는데 그것이 가리키는 앞쪽 저널이 없는 구간이 생긴다)'\n )\n }\n const cutoff = new Date(Date.now() - effectiveDays * 86400 * 1000)\n\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n let deleted = 0\n let instances = 0\n const skipped: string[] = []\n\n for (const r of rows) {\n const snap = await this.loadSnapshot(domainId, r.instanceId).catch(() => null)\n const upTo = Number(snap?.revision ?? 0)\n if (!upTo) {\n /* 스냅샷이 없다 — 저널이 유일한 복구 수단이므로 손대지 않는다. */\n skipped.push(r.instanceId)\n continue\n }\n const res = await getRepository(TwinEvent)\n .createQueryBuilder()\n .delete()\n .from(TwinEvent)\n .where('domain_id = :domainId', { domainId })\n .andWhere('instance_id = :instanceId', { instanceId: r.instanceId })\n .andWhere('revision <= :upTo', { upTo })\n .andWhere('created_at IS NOT NULL')\n .andWhere('created_at < :cutoff', { cutoff })\n .execute()\n const n = res.affected ?? 0\n if (n > 0) {\n deleted += n\n instances++\n /* **지운 것을 말한다** — 조용히 줄어든 저널은 「없었던 일」과 구별되지 않는다. */\n twinLog(\n `[twin-engine] journal pruned \"${r.instanceId}\" — ${n}건 (revision ≤ ${upTo} · ${cutoff.toISOString()} 이전). ` +\n '그 앞은 체크포인트가 대신한다.'\n )\n }\n }\n if (skipped.length) {\n twinLog(\n `[twin-engine] journal prune skipped ${skipped.length} instance(s) with no checkpoint — ` +\n `저널이 유일한 복구 수단이라 손대지 않았다: ${skipped.slice(0, 5).join(', ')}${skipped.length > 5 ? ' …' : ''}`\n )\n }\n return { deleted, instances, skipped }\n }\n\n /** 보존 정리 주기 기동(1회) — 선언이 없으면 아무것도 하지 않는다. */\n static startRetentionLoop(domainId: string): void {\n if (this.retentionTimer) return\n /*\n * 걸지 않는 조건: 프로세스 기본값도 없고 **도메인에 물을 길도 없을** 때다. 시임이 심겨 있으면\n * 기본값이 없어도 걸어야 한다 — 그 도메인이 자기 값을 가질 수 있다.\n */\n if (!this.JOURNAL_RETENTION_DAYS && !this.retentionDaysOf) return\n this.retentionTimer = setInterval(() => {\n this.pruneJournal(domainId).catch(err => twinError('[twin-engine] journal prune failed', err?.message ?? err))\n }, this.RETENTION_SWEEP_MS)\n if (typeof this.retentionTimer?.unref === 'function') this.retentionTimer.unref()\n twinLog(\n `[twin-engine] journal retention on — ${this.JOURNAL_RETENTION_DAYS ?? '(도메인 정책)'}일 · ` +\n `${this.RETENTION_SWEEP_MS / 60000}분마다`\n )\n }\n\n /** 체크포인트 루프 기동(1회) — 라이브 인스턴스들의 최신 스냅샷을 주기 영속. */\n static startCheckpointLoop(): void {\n if (this.checkpointTimer) return\n this.checkpointTimer = setInterval(() => {\n for (const [key, inst] of Object.entries(this.instances)) {\n const { instanceId } = parseRuntimeKey(key)\n this.persistSnapshot(inst.domainId, instanceId).catch(err =>\n twinError(`[twin-engine] snapshot checkpoint fail \"${instanceId}\"`, err?.message ?? err)\n )\n }\n }, this.CHECKPOINT_MS)\n if (typeof this.checkpointTimer?.unref === 'function') this.checkpointTimer.unref()\n }\n\n /**\n * 부팅 훅 — DB 에 status='running' 으로 남은 인스턴스를 저널에서 상태 재구성(DB→replay).\n * 라이브 tick 재개(sim 결정적 re-run / live 인제스트 지속)는 후속. 여기선 상태 복원 + 노출.\n */\n static async bootstrap(): Promise<void> {\n /* 부팅부터 잰다 — 사람이 가장 답답한 구간이 여기이고, 그 구간을 재지 않으면 값으로 말할 수 없다. */\n loopLag.start()\n try {\n const repo = getRepository(TwinInstance)\n const rows = await repo.find({ where: { status: 'running' } })\n for (const row of rows) {\n if (!row.domainId || !row.instanceId) continue\n // 웜스타트: 캐시된 최신 스냅샷 우선(O(1) + attentions/OEE 등 라이브 파생상태 보존).\n // 없으면 저널 fold-from-0 replay(진실 폴백 — replay 는 라이브 파생상태를 못 담으므로 캐시가 더 충실).\n const cached = await this.loadSnapshot(row.domainId, row.instanceId).catch(() => null)\n if (cached?.state) {\n /* 예전에 겹포장으로 저장된 값이 남아 있을 수 있다 — 읽는 쪽에서도 벗긴다(한 번은 반드시 만난다). */\n this.recovered[runtimeKey(row.domainId, row.instanceId)] = { revision: cached.revision, state: unwrapState(cached.state) }\n /*\n * **「웜스타트했다」고 말하지 않는다** — 여기서는 상태를 **찾아 둔 것**뿐이다.\n *\n * 실제 주입은 기동 때 일어나고(`warmStart` 가 그때 무엇을 심었는지 말한다), 미러(live) 트윈은\n * 그 씨앗을 아예 쓰지 않는다(`startLive` 가 버린다). 그런데 이 줄이 「warm-started」라고 말해\n * 로그만 읽으면 심긴 줄 알게 된다 — 실제로 그렇게 읽고 재기동 뒤 지속시간이 사라진 것을\n * 데이터 문제로 오진할 뻔했다.\n */\n twinLog(`[twin-engine] found cached state for \"${row.instanceId}\" → revision ${cached.revision} (seeded at start).`)\n continue\n }\n const state = await this.recover(row.domainId, row.instanceId).catch(() => null)\n if (state) {\n this.recovered[runtimeKey(row.domainId, row.instanceId)] = { revision: state.revision, state }\n twinLog(`[twin-engine] recovered \"${row.instanceId}\" from journal → revision ${state.revision}.`)\n }\n }\n /*\n * 상태만 되찾는 것으로는 **도는 트윈이 되지 않는다** — 런타임까지 되살린다(아래).\n *\n * 되살리기 사이에 **루프를 한 번 비워 준다** (2026-08-21). 웜스타트 하나가 물품 수천 개를 접으므로\n * 스무 개를 연달아 하면 그 시간 내내 HTTP 가 서지 않는다 — 서버는 이미 `Server ready` 를 찍은\n * 뒤라서, 사람에게는 「열렸는데 아무 반응이 없는 화면」으로 보인다. 총 시간은 같고, 그 사이에\n * 도착한 요청이 처리될 틈만 생긴다.\n */\n for (const row of rows) {\n await this.resumeRow(row)\n await new Promise(resolve => setTimeout(resolve, this.BOOT_YIELD_MS))\n }\n this.startCheckpointLoop() // 이후 기동되는 라이브 인스턴스의 최신 스냅샷을 주기 영속\n /*\n * 보존 정리 — **선언이 있을 때만** 돈다(§`JOURNAL_RETENTION_DAYS`). 도메인마다 한 번 건다.\n * 체크포인트 루프 뒤에 두는 이유: 지울 수 있는 경계가 스냅샷이므로, 스냅샷을 남기는 쪽이 먼저\n * 돌아야 첫 정리가 실제로 지울 것을 갖는다.\n */\n for (const domainId of new Set(rows.map(r => r.domainId).filter(Boolean) as string[])) {\n this.startRetentionLoop(domainId)\n }\n } catch (err) {\n twinError('[twin-engine] recovery scan failed', err)\n }\n }\n\n /**\n * 부팅 때 **도는 트윈을 실제로 되살린다** — 「도는 중」이 사실이 되게.\n *\n * ── 무엇이 거짓말이었나 (2026-08-14) ────────────────────────────────────────\n * `bootstrap()` 은 상태만 되찾아 `recovered` 에 담았고, 커널을 세우는 것은 **명시 mutation 뿐**이었다\n * (이 파일 위쪽 주석이 「향후」라고 적어 둔 그 자리다). 그래서 서버를 한 번 재기동하면 등록부는\n * `running` 이라 말하는데 **아무 커널도 돌지 않았다** — 화면은 도는 트윈을, 실제로는 멈춘 트윈을.\n * 미러 트윈에서는 더 나쁘다: 계측이 조용히 끊기고, 사람은 「값이 안 변하네」로 알게 된다.\n *\n * ── 모드를 지어내지 않는다 ──────────────────────────────────────────────────\n * 미러였던 트윈을 시뮬로 되살리면 **없던 움직임을 만들어 낸다**(관측 트윈이 스스로 물건을 옮긴다).\n * 그래서 선언된 `restartPolicy` 그대로 되살린다 — 미러는 관측 구동으로, 시뮬은 시뮬로.\n *\n * ── 되살릴 수 없으면 그렇게 적는다 ──────────────────────────────────────────\n * 실패를 삼키면 등록부가 계속 `running` 이라 말한다 — 우리가 고치려던 그 거짓말이다. 그래서 실패한\n * 행은 `stopped` 로 적고 이유를 남긴다. 「멈췄다」는 사실이고, 「도는 중」은 사실이 아니었다.\n */\n private static async resumeRow(row: TwinInstance): Promise<void> {\n const { domainId, instanceId } = row\n if (!domainId || !instanceId) return\n if (this.instances[runtimeKey(domainId, instanceId)]) return // 이미 세워졌다(데모 시드 등)\n\n /*\n * 벤치 사본은 되살리지 않는다 — 그것은 **누군가 지켜보던 실험**이고, 무인으로 되살아나면 호스트를\n * 그대로 두들긴다(격리 사본의 뜻은 「운영과 섞이지 않는다」이지 「영원히 돈다」가 아니다).\n * 실험은 재기동을 넘기지 못했으므로 등록부도 그렇게 적는다.\n */\n if (row.purpose === 'bench') {\n await this.markStopped(row, 'bench copy — an experiment does not survive a restart unattended')\n return\n }\n\n try {\n /*\n * **선언된 모드로 되살리는 판단은 한 곳에 있다**(`startFromRegistry`) — 2026-08-20.\n *\n * 예전에는 이 자리에서 `resync` 를 갈라 `startLive` 를 불렀다. 그래서 부팅으로 살아난 미러는\n * 관측 구동이었지만 **사람이 화면에서 시작한 미러는 시뮬로 떴다**(그 문에는 갈림이 없었다).\n * 같은 선언이 두 결과를 내지 않도록 갈림을 문 안으로 옮겼다.\n */\n await this.startFromRegistry(domainId, instanceId)\n if (row.restartPolicy === 'resync') {\n /* 계측을 나르는 피드는 커넥터의 것이다 — 레퍼런스 계층이 부팅 훅에서 다시 붙인다\n (`resumeReferenceLiveFeeds`). 여기서 어댑터를 아는 것은 계층을 거꾸로 잇는 것이다. */\n twinLog(`[twin-engine] resumed mirror \"${instanceId}\" — feed reattach is the reference layer's job.`)\n } else {\n twinLog(`[twin-engine] resumed ${row.restartPolicy} \"${instanceId}\".`)\n }\n } catch (err: any) {\n await this.markStopped(row, err?.message ?? 'resume failed')\n }\n }\n\n /** 되살리지 못한 행을 정직하게 적는다 — 「도는 중」이라 말하는 채로 두지 않는다. */\n private static async markStopped(row: TwinInstance, why: string): Promise<void> {\n twinWarn(`[twin-engine] \"${row.instanceId}\" not resumed (${why}) — registry says stopped now.`)\n try {\n await getRepository(TwinInstance).update({ id: row.id }, { status: 'stopped' })\n } catch (e: any) {\n twinError(`[twin-engine] could not mark \"${row.instanceId}\" stopped — registry now lies about it.`, e?.message)\n }\n }\n\n /**\n * 웜스타트 — 기동하는 커널에 **직전 관측 상태**를 주입한다.\n *\n * ── 왜 필요한가 ─────────────────────────────────────────────────────────────\n * `loadTwinModel` 는 **구조만** 싣는다(자리·설비). 상태(무엇이 어디에 얼마나)는 없다. 그래서 재기동한\n * 트윈은 저널에 입고 540건이 남아 있어도 재고가 0 이었고, 화면은 \"보유 중인 것이 없습니다\" 라고\n * 말했다 — 있는 재고를 없다고 하는 셈이다(2026-07-31 hatiolab-wms 실측으로 확인).\n * `bootstrap()` 이 이미 체크포인트 캐시(없으면 저널 replay)로 상태를 복구해 `recovered` 에 담아 두는데,\n * 기동 순간 그걸 **버리고** 있었다. 반만 연결돼 있던 장치를 잇는다.\n *\n * ── 반쪽이던 복구를 마무리한다 (2026-08-05) ─────────────────────────────────\n * 재고는 살아났는데 **진행 중 주문이 통째로 사라진** 화면이 남아 있었다. 씨앗이 자리·물품·설비\n * 셋만 넘겼기 때문이다. 그 근거는 \"스냅샷 오더에 progress 밖에 없다\" 였고, 그때는 맞았다 —\n * 그러나 커널 `OrderState` 가 원값(`requested`·`fulfilled`·`lines`)을 되찾은 뒤에도 이 자리만\n * 그대로 남았다. 오류를 내지 않는 종류라 오래 버텼다.\n *\n * 지금은 **관측 스냅샷 전체**를 넘긴다(오더·작업·사람·자산 포함). 시뮬은 커널 `snapshot()`,\n * 라이브는 `StateProjector` 가 그 일곱 축을 모두 담는다. 무엇을 심을 수 있는지 판정하는 규칙\n * (이행 완료 오더 제외·고아 작업 제외)은 커널에 있고, 호스트가 미리 골라내지 않는다.\n *\n * ── 남은 한계는 숨기지 않고 센다 ────────────────────────────────────────────\n * · 원값이 없는 오더(progress 만 있는 것)는 남은 수량을 알 수 없어 주입하지 않는다. **지어내지 않는\n * 대신 몇 건인지 말한다** — 세지 않으면 \"주문이 없다\" 와 \"주문을 못 심었다\" 가 화면에서 같아진다.\n * · 진행 중 개별 작업의 내부 상태는 관측만으로 완전히 복원되지 않는다(커널이 명시한 한계, 재계획에 맡김).\n *\n * ── 벤치는 시드하지 않는다 ──────────────────────────────────────────────────\n * 부하 벤치는 **새 시작에서 용량을 재는 것**이 목적이라 현재 상태를 주입하면 측정이 오염된다.\n */\n private static warmStart(domainId: string, id: string, kernel: TwinKernel, purpose?: string): void {\n const hydrate = (kernel as any).hydrateObserved\n const plan = planWarmStart(this.recovered[runtimeKey(domainId, id)]?.state, purpose, typeof hydrate === 'function')\n\n if (plan.action === 'skip') {\n if (plan.reason === 'bench') {\n twinLog(`[twin-engine] \"${id}\" is a bench twin — starting empty on purpose (seeding would skew the measurement).`)\n } else if (plan.reason === 'unsupported') {\n twinWarn(\n `[twin-engine] kernel for \"${id}\" cannot be warm-started (no hydrateObserved) — it starts with structure only, so held stock will read as zero.`\n )\n }\n return\n }\n\n hydrate.call(kernel, plan.seed)\n const restored = [\n `${plan.itemCount} item(s)`,\n `${plan.equipmentCount} equipment`,\n `${plan.orderCount} open order(s)`,\n `${plan.taskCount} task(s)`,\n ...(plan.personCount ? [`${plan.personCount} person(s)`] : []),\n ...(plan.assetCount ? [`${plan.assetCount} asset(s)`] : []),\n /* 확인해 둔 신호를 이어받았다는 사실도 말한다 — 잃으면 확인 처리가 다시 빨개지는 것으로 보인다. */\n ...(plan.ackedCount ? [`${plan.ackedCount} acknowledged attention(s)`] : []),\n /* 「언제부터인가」도 말한다 — 잃으면 지속된 조건이 모두 「방금」으로 보인다. */\n ...(plan.attentionSinceCount ? [`${plan.attentionSinceCount} attention start time(s)`] : [])\n ].join(', ')\n twinLog(`[twin-engine] warm-started \"${id}\" — restored ${restored}.`)\n /* 뺀 것은 조용히 넘기지 않는다 — 지어내지 않았다는 사실 자체를 말해야 화면의 빈칸이 읽힌다. */\n if (plan.ordersWithoutDemand > 0) {\n twinWarn(\n `[twin-engine] \"${id}\": ${plan.ordersWithoutDemand} order(s) could not be restored — they carry progress only, ` +\n 'with no requested/fulfilled counts, so the remaining demand is unknown. They are left out rather than guessed.'\n )\n }\n }\n\n /** 트윈 인스턴스 시작 — 커널 생성 + 모델 로드 + 직전 상태 웜스타트 + State 스트림 브리지 + 워커 tick + 레지스트리 영속. */\n /**\n * 공정 명세를 커널에 싣는다 — **시뮬레이션의 시간을 데이터가 말하게 하는 마지막 한 칸.**\n *\n * `model.operations`(마스터 인제스트가 통과시킨 ISA-95 OperationsSegment 명세)를 커널이 소비한다.\n * 없으면 커널 기본 상수로 굴러가고, 커널 `specCoverage()` 가 무엇을 기본값으로 썼는지 보고한다.\n *\n * 커널이 아직 이 API 를 갖지 않은 버전이면(발행 이전) **조용히 넘어가지 않고 경고한다** — 명세를\n * 선언했는데 반영되지 않는 상태를 모르고 지나가면, 예측이 상수로 돌아간 것을 아무도 알 수 없다.\n */\n private static applyOperations(kernel: any, model: any, id: string): void {\n /*\n * 현장이 정한 공정 시간 — 명세 행과 **따로** 싣는다(`declareDurations`).\n *\n * 행이 없는 종류에도 시간을 줄 수 있어야 한다: 실측으로 창고·야드 트윈에는 공정 명세 행이 0개였고,\n * 그 트윈들의 시간은 전부 커널 상수에서 왔다. 행을 지어 만드는 길은 막았다(`label`·`intent` 를\n * 지어내면 능력 계산까지 오염된다) — 그래서 시간만 받는 창구가 커널에 있다.\n */\n const declared = model?.localDurations as Record<string, string> | undefined\n if (declared && Object.keys(declared).length) {\n if (typeof kernel?.declareDurations !== 'function') {\n twinWarn(\n `[twin-engine] \"${id}\": this facility declared ${Object.keys(declared).length} operation duration(s) but the kernel cannot consume them ` +\n '(declareDurations missing — kernel needs publishing). The simulation keeps running on built-in constants, and specCoverage() will keep reporting \"default\".'\n )\n } else {\n try {\n kernel.declareDurations(declared)\n } catch (err: any) {\n /* 커널이 거절한 값은 조용히 넘기지 않는다 — 화면은 「넣었습니다」라고 말한 값이다. */\n twinWarn(`[twin-engine] \"${id}\": declared operation duration rejected by the kernel — ${err?.message ?? err}`)\n }\n }\n }\n /* 공정 모수(수율·셋업)도 같은 규율로 싣는다 — 커널이 그 창구를 갖지 않으면 그 사실을 말한다. */\n const params = model?.localParams as Record<string, Record<string, string>> | undefined\n if (params && Object.keys(params).length) {\n if (typeof kernel?.declareParameters !== 'function') {\n twinWarn(\n `[twin-engine] \"${id}\": this facility declared operation parameters for ${Object.keys(params).length} operation(s) but the kernel cannot consume them ` +\n '(declareParameters missing — kernel needs publishing). Yield and setup keep running on built-in constants.'\n )\n } else {\n try {\n kernel.declareParameters(params)\n } catch (err: any) {\n twinWarn(`[twin-engine] \"${id}\": declared operation parameter rejected by the kernel — ${err?.message ?? err}`)\n }\n }\n }\n const ops = model?.operations\n if (!ops?.length) return\n if (typeof kernel?.loadOperations !== 'function') {\n twinWarn(`[twin-engine] \"${id}\": model declares ${ops.length} operation spec(s) but the kernel cannot consume them (loadOperations missing — kernel needs publishing). Simulation will use built-in default durations.`)\n return\n }\n kernel.loadOperations(ops)\n }\n\n /**\n * 소요시간 추정기 주입 — **상수를 데이터로 바꾸는 두 번째·세 번째 층.**\n *\n * 커널 `durationOf` 의 우선순위는 추정기 > 명세 > 상수다. 그 추정기 자리에 두 가지를 사슬로 넣는다:\n * ① **실측**(저널의 작업 종류별 작업시간 p50) — 그 현장에서 실제로 얼마 걸렸나. 가장 강한 근거.\n * ② **거리 × 속도**(model.layout + 설비 속도 속성) — 이동은 거리에 비례한다. 커널은 좌표를 모르므로\n * 호스트가 계산해 넣는다.\n * 둘 다 못 만들면 주입하지 않는다 — 커널이 명세·상수로 굴러가고 `specCoverage()` 가 그 사실을 남긴다.\n *\n * 실측은 DB 조회라 비동기다. 그래서 이 함수는 **await 하지 않는 쪽에서도 안전**하도록 실패를 삼키되,\n * 무엇을 왜 못 넣었는지는 로그로 남긴다(조용한 무효화 금지).\n */\n static async installEstimators(kernel: any, domainId: string, instanceId: string, model: any): Promise<void> {\n if (!kernel || typeof kernel !== 'object') return\n const travel = buildTravelEstimator({ layout: model?.layout, equipment: model?.equipment, unit: model?.unit })\n const measured = await this.measuredEstimator(domainId, instanceId)\n const chained = chainEstimators([measured?.estimator, travel.estimator])\n if (!chained) {\n /* 왜 못 넣었는지 한 번만 알린다 — 이동시간이 상수로 남은 이유를 모르고 지나가지 않게. */\n if (travel.reasons.length) twinWarn(`[twin-engine] \"${instanceId}\": no duration estimator installed — ${travel.reasons.join('; ')}`)\n return\n }\n kernel.durationEstimator = chained\n /*\n * **양품률도 이력에서 배운다** (2026-08-19) — 소요와 같은 자리에서 붙인다.\n *\n * 커널이 그 시임을 갖지 않은 버전이면(발행 이전) 조용히 넘어가지 않고 말한다: 수율이 상수로 남은\n * 이유를 모르고 지나가면, 화면의 불량 판정이 그 현장의 사실이 아니라 우리 상수의 결과다.\n */\n const yields = await this.measuredYield(domainId, instanceId)\n if (yields?.estimator) {\n if (typeof kernel.yieldOf !== 'function') {\n twinWarn(\n `[twin-engine] \"${instanceId}\": learned yield for ${Object.keys(yields.learned).length} operation kind(s) but the kernel cannot consume it ` +\n '(yieldOf missing — kernel needs publishing). Yield keeps running on the declared value or the built-in constant.'\n )\n } else {\n kernel.yieldEstimator = yields.estimator\n twinLog(\n `[twin-engine] \"${instanceId}\": measured yield installed — ${Object.entries(yields.learned)\n .map(([k, v]) => `${k}=${Math.round(v * 1000) / 10}%(${yields.samples[k].good + yields.samples[k].scrap}건)`)\n .join(', ')}${yields.skipped.length ? ` · 표본 부족으로 뺀 종류: ${yields.skipped.map(s => `${s.kind}(${s.judged})`).join(', ')}` : ''}`\n )\n }\n } else if (yields?.skipped.length) {\n /* 배운 것이 없고 버린 것만 있으면 그 사실도 말한다 — 「이력이 없다」와 「표본이 모자라다」는 다르다. */\n twinLog(\n `[twin-engine] \"${instanceId}\": no measured yield yet — samples below ${yields.minSamples}: ${yields.skipped\n .map(s => `${s.kind}(${s.judged})`)\n .join(', ')}`\n )\n }\n const learned = Object.keys(measured?.learned ?? {})\n const spread = Object.keys(measured?.spreads ?? {})\n twinLog(\n `[twin-engine] \"${instanceId}\": duration estimator installed — measured kinds: ${learned.length ? learned.join(',') : 'none'}` +\n ` (with observed spread: ${spread.length ? spread.join(',') : 'none'})` +\n `${travel.estimator ? `, travel from distance (speeds: ${Object.keys(travel.speedsByKind).join(',')})` : `, travel not derived (${travel.reasons.join('; ')})`}`\n )\n }\n\n /**\n * 실측 추정기 — **예측 요청마다 저널을 다시 접지 않는다.**\n *\n * 예측 커널은 요청마다 새로 세워지고(미러 예측·백테스트), 화면은 시각을 긁으면 계속 재예측한다.\n * 거기에 KPI 조회를 그대로 달면 요청당 저널 스캔이 하나씩 붙는다 — 실측은 분 단위로 바뀌지 않으므로\n * 짧은 TTL 로 재사용한다. 캐시는 인스턴스별이고, 만료 전에는 같은 값을 쓴다(예측 간 일관성도 얻는다).\n */\n private static measuredCache = new Map<\n string,\n {\n at: number\n value: ReturnType<typeof buildMeasuredEstimator> | undefined\n /** 같은 폴드에서 나온 양품률 — **저널을 두 번 접지 않는다**(소요와 수율은 같은 창의 같은 사실이다). */\n yields?: ReturnType<typeof buildYieldEstimator>\n }\n >()\n private static readonly MEASURED_TTL_MS = 60_000\n /**\n * 캐시 항목 상한 — **라이프사이클이 놓친 것까지 막는 두 번째 방어.**\n *\n * 지움은 `forgetInstance` 가 한다(그것이 첫 번째 방어이고 정확한 쪽이다). 그런데 트윈이 우리 API 를\n * 지나지 않고 사라지는 길이 있다: 도메인(테넌트)째로 지워지거나 DB 를 직접 손대는 경우다. 그때\n * 남은 항목을 지울 주인이 없으므로 상한이 필요하다.\n *\n * 넘치면 **가장 오래 손대지 않은 것**부터 버린다(Map 의 삽입 순서가 곧 그 순서다 — 값을 쓸 때마다\n * 다시 넣으므로). 버리는 것이 손해가 아닌 이유: 이 값은 캐시이고, 없으면 다시 계산한다.\n *\n * 수를 크게 잡는다 — 트윈 규모는 늘 크고, 항목 하나는 작업 종류별 소요 몇 줄이다. 상한이 작으면\n * 정상 규모에서 서로 밀어내며 캐시가 무의미해진다(그게 더 나쁘다: 조용히 느려진다).\n */\n private static readonly MEASURED_MAX = 5_000\n\n /** 이 트윈이 이력에서 배운 양품률 — 소요와 **같은 폴드·같은 캐시**에서 온다(저널을 두 번 접지 않는다). */\n private static async measuredYield(domainId: string, instanceId: string) {\n await this.measuredEstimator(domainId, instanceId)\n return this.measuredCache.get(runtimeKey(domainId, instanceId))?.yields\n }\n\n private static async measuredEstimator(domainId: string, instanceId: string) {\n /* 키는 `runtimeKey` 하나로 — 손으로 조립하면 지우는 쪽과 어긋나 못 지우는 항목이 생긴다. */\n const key = runtimeKey(domainId, instanceId)\n const hit = this.measuredCache.get(key)\n if (hit && Date.now() - hit.at < this.MEASURED_TTL_MS) return hit.value\n let value: ReturnType<typeof buildMeasuredEstimator> | undefined\n let yields: ReturnType<typeof buildYieldEstimator> | undefined\n try {\n /* 작업 종류별 실측 — 창은 넉넉히(하루) 두고 표본이 모자란 종류는 추정기가 스스로 뺀다. */\n const kpi: any = await computeTwinKpi({ domainId, instanceId, windowMinutes: 24 * 60, groupBy: 'taskKind' })\n value = buildMeasuredEstimator(kpi?.groups?.items, {})\n /* 같은 그룹에서 양품률도 배운다 — 한 번 접은 저널을 둘이 나눠 쓴다. */\n yields = buildYieldEstimator(kpi?.groups?.items, {})\n } catch (err) {\n twinWarn(`[twin-engine] \"${instanceId}\": measured duration lookup failed — falling back to declared/default durations.`, (err as any)?.message)\n }\n /* 다시 넣어 **최근 쓴 것**으로 만든다 — 삽입 순서가 곧 버릴 순서이므로 이 한 줄이 LRU 를 만든다. */\n this.measuredCache.delete(key)\n this.measuredCache.set(key, { at: Date.now(), value, yields })\n if (this.measuredCache.size > this.MEASURED_MAX) {\n const oldest = this.measuredCache.keys().next()\n if (!oldest.done) this.measuredCache.delete(oldest.value)\n }\n return value\n }\n\n /**\n * **원본이 선언한 자극을 싣는다** — 재기동해도 살아 있게 (2026-08-19).\n *\n * ── 무엇이 났나 ────────────────────────────────────────────────────────────\n * 데모의 시나리오는 시드 코드가 메모리에만 실었다. 그래서 트윈을 재기동하면 자극이 사라지고 구조만\n * 서 있는 트윈이 남았다(작업 0·오더 0) — 「살아 있는 데모」가 **첫 재기동까지만** 살았다.\n *\n * 자극의 집은 **원본**이다(`TwinReference.connectionConfig.scenario`, ADR-0029 ·\n * `plans/simulator-as-source.md` §4): 무엇이 들어오고 무슨 주문이 나는지는 시뮬레이터가 정하는 사실이고\n * 트윈은 반영한다. 트윈에 새 축을 만들면 ADR-0029 가 걷어내야 할 표면이 하나 늘어난다.\n *\n * 판정은 순수 함수가 한다(`planStimulus`) — 미러에 싣지 않고, 검사를 통과하지 못한 선언은 태우지 않고\n * (그 이력이 있다: 잘못된 선언 하나가 다음 틱에서 서버를 내렸다), 못 실은 이유는 **말한다.**\n */\n private static async installStimulus(domainId: string, instanceId: string, inst: InstanceRuntime): Promise<void> {\n let config: any\n try {\n const ref = await getRepository(TwinReference).findOne({ where: { domain: { id: domainId }, source: instanceId } })\n config = ref?.connectionConfig\n } catch (err: any) {\n twinWarn(`[twin-engine] \"${instanceId}\": could not read the declared stimulus — ${err?.message ?? err}`)\n return\n }\n const plan = planStimulus(config, { hasScenarioEngine: !!inst.runtime?.scenario, mode: inst.mode }, validateScenario as any)\n if (plan.action === 'skip') {\n /* 선언이 없는 것은 정상이므로 조용히 지난다. 나머지 셋은 **말한다** — 선언했는데 안 실린 상태다. */\n if (plan.reason !== 'none') {\n twinWarn(\n `[twin-engine] \"${instanceId}\": a stimulus is declared on its source but was not loaded (${plan.reason}${plan.detail ? `: ${plan.detail}` : ''}).` +\n (plan.reason === 'observed' ? ' This twin runs on observation — we do not manufacture arrivals for it.' : '')\n )\n }\n return\n }\n try {\n /* 자극을 싣고 시작하는 데 든 시간 — 실측에서 큰 트윈은 이 구간이 29~72초였다. */\n const tStim = performance.now()\n inst.runtime!.scenario.load(plan.scenario)\n inst.runtime!.scenario.start()\n const stimMs = performance.now() - tStim\n recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'stimulus', stimMs)\n const kinds = (plan.scenario.generators ?? []).map((g: any) => g?.kind).filter(Boolean)\n twinLog(\n `[twin-engine] \"${instanceId}\": stimulus from its source started in ${Math.round(stimMs)}ms — ${kinds.length ? kinds.join(', ') : 'no generators'}.`\n )\n } catch (err: any) {\n twinWarn(`[twin-engine] \"${instanceId}\": the declared stimulus was rejected at load — ${err?.message ?? err}`)\n }\n }\n\n /**\n * 자극을 **원본에 선언한다** — 프로비저닝·데모 시드가 부르는 문.\n *\n * 트윈이 아니라 원본에 적는 이유는 위와 같다(ADR-0029). 원본 행이 없으면 만들지 않는다 — 어떤 원본에서\n * 온 트윈인지 모르는 채 자극을 지어 붙이면, 그 자극이 어디서 왔는지 아무도 되짚을 수 없다.\n */\n static async declareStimulus(domainId: string, instanceId: string, scenario: any): Promise<boolean> {\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: domainId }, source: instanceId } })\n if (!ref) {\n twinWarn(`[twin-engine] \"${instanceId}\": no source reference — a stimulus has nowhere to be declared.`)\n return false\n }\n ref.connectionConfig = withStimulus(ref.connectionConfig, scenario)\n await repo.save(ref)\n return true\n }\n\n /**\n * 이 트윈이 **이력에서 시간을 배운 작업 종류들** — 재기동에도 남는 근거.\n *\n * ── 왜 필요한가 (2026-08-18 실측) ────────────────────────────────────────\n * 커널의 자기보고(`specCoverage()`)는 **작업이 새로 생길 때** 채워진다. 그래서 재기동 직후에는 이력이\n * 풍부한 트윈에서도 목록이 비고, 「이 트윈이 무슨 공정을 돌리나」 화면이 빈칸이 된다 — 값을 채울 곳을\n * 보여야 하는 화면이 정작 그때 아무 말도 못 한다.\n *\n * 그 빈칸을 이력로 메운다: 저널에서 배운 종류는 **추정기가 이미 답할 수 있는 종류**이므로, 지어내는\n * 것이 아니라 있는 사실을 꺼내는 것이다. 같은 캐시(60초)를 쓰므로 조회마다 저널을 다시 접지 않는다.\n */\n static async measuredOperationKinds(domainId: string, instanceId: string): Promise<string[]> {\n const measured = await this.measuredEstimator(domainId, instanceId)\n return Object.keys((measured as any)?.learned ?? {})\n }\n\n /**\n * 지금 이 트윈이 어떤 모델로 굴러가는가 — 예측 출력 보정이 **자기가 배운 모델**에만 적용되도록\n * 비교하는 지문. 재료는 호스트가 아는 것(실측·속도·선언 명세)이라 커널 발행 상태와 무관하다.\n * 실패하면 undefined — 그때는 비교를 하지 않는다(모르는 것을 근거로 보정을 끊지 않는다).\n */\n static async modelBasis(domainId: string, instanceId: string): Promise<ModelBasis | undefined> {\n try {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n const model: any = reg?.model\n const measured = await this.measuredEstimator(domainId, instanceId)\n const travel = buildTravelEstimator({ layout: model?.layout, equipment: model?.equipment, unit: model?.unit })\n return { measured: measured?.learned, speeds: travel.speedsByKind, declared: model?.operations }\n } catch {\n return undefined\n }\n }\n\n /**\n * **이 트윈이 하루 몇 대를 낼 수 있는가** — 실행해 보지 않고 답한다.\n *\n * 계산은 커널이 자기 상태에서 한다(`kernel.capacity`). 여기서 하는 일은 **기준 주를 정해 주는\n * 것**뿐이다: 공휴일이 없는 평상주여야 한다 — 공휴일은 연간 가용량을 따로 깎지, 이 공장의 평상시\n * 상한을 정하지 않는다. 커널이 임의로 고르게 두면 그 주에 공휴일이 끼었을 때 상한이 조용히 낮아진다.\n *\n * 트윈이 기동 중이 아니면 `undefined` 다 — 0 이 아니다. 기동하지 않은 트윈의 상한을 0 이라고 답하면 화면은\n * \"이 공장은 아무것도 못 만든다\" 고 말한다.\n */\n static async capacity(\n domainId: string,\n target: { instanceId?: string; spaceId?: string },\n unitsPerDay: number,\n sampleWeekStartMs: number\n ): Promise<{ instanceId: string; kind?: string; analysis?: any; reason?: 'not-running' | 'no-operations' }[]> {\n /* 대상은 **등록부**가 정한다 — 기동 중인 런타임만 훑으면 \"안 떠 있어서 안 보이는 것\" 과 \"없는 것\" 이\n 구별되지 않는다. 화면은 그 둘을 다르게 말해야 한다. */\n const where: any = { domain: { id: domainId } }\n if (target.instanceId) where.instanceId = target.instanceId\n else where.spaceId = target.spaceId\n const registered = await getRepository(TwinInstance).find({ where })\n\n return registered.map(reg => {\n const rt = this.instances[runtimeKey(domainId, reg.instanceId)]\n const kernel: any = rt?.kernel // 키에 도메인이 있으므로 남의 런타임을 집을 수 없다\n if (typeof kernel?.capacity !== 'function') return { instanceId: reg.instanceId, kind: reg.kind, reason: 'not-running' as const }\n\n const analysis = kernel.capacity({ unitsPerDay, sampleWeekStartMs })\n /* 공정을 선언하지 않은 트윈(대개 YMS·WMS)은 **판정 대상이 아니다.** 0 으로 채워 넣으면\n \"야드가 병목\" 이라는 없는 사실이 생긴다 — 잴 것이 없다고 말한다. */\n if (!analysis?.operations?.length) return { instanceId: reg.instanceId, kind: reg.kind, reason: 'no-operations' as const }\n return { instanceId: reg.instanceId, kind: reg.kind, analysis }\n })\n }\n\n /**\n * **생산 능력 보고서** — ISA-95 Part 4 `OperationsCapability`. 구간의 양을 종류로 구분한다\n * (약정·가용·달성불가). 용량(`capacity`)은 비율을 내고 이것은 **구간의 양**을 낸다.\n *\n * 대상 선정·거절 사유는 `capacity` 와 **같은 규율**이다: 등록부가 대상을 정하고(안 기동 중인 것과\n * 없는 것을 구별한다), 공정을 선언하지 않은 트윈은 판정 대상이 아니라고 말한다(0 으로 채우면\n * \"야드가 병목\" 이라는 없는 사실이 생긴다).\n */\n static async operationsCapability(\n domainId: string,\n target: { instanceId?: string; spaceId?: string },\n unitsPerDay: number,\n sampleWeekStartMs: number,\n window: { fromTime: string; toTime: string }\n ): Promise<{ instanceId: string; kind?: string; report?: any; reason?: 'not-running' | 'no-operations' }[]> {\n const where: any = { domain: { id: domainId } }\n if (target.instanceId) where.instanceId = target.instanceId\n else where.spaceId = target.spaceId\n const registered = await getRepository(TwinInstance).find({ where })\n\n return registered.map(reg => {\n const rt = this.instances[runtimeKey(domainId, reg.instanceId)]\n const kernel: any = rt?.kernel\n if (typeof kernel?.operationsCapability !== 'function') {\n return { instanceId: reg.instanceId, kind: reg.kind, reason: 'not-running' as const }\n }\n const report = kernel.operationsCapability({ unitsPerDay, sampleWeekStartMs, window })\n if (!report?.perOperation?.length) return { instanceId: reg.instanceId, kind: reg.kind, reason: 'no-operations' as const }\n return { instanceId: reg.instanceId, kind: reg.kind, report }\n })\n }\n\n /**\n * 미러 기동의 연속성 씨앗 — 이어받은 것은 **말한다**(조용히 잇지 않는다).\n *\n * 커널이 그 문을 열어 두지 않았으면 그 사실도 말한다: 그 트윈은 재기동마다 열린 구간을 잃는다.\n */\n private static seedLiveContinuity(domainId: string, id: string, kernel: any): void {\n const cached = this.recovered[runtimeKey(domainId, id)]?.state\n if (!cached) return\n const plan = planLiveContinuity(cached)\n if (!plan.ackedCount && !plan.attentionSinceCount && !plan.energy) return\n if (typeof kernel.hydrateContinuity !== 'function') {\n twinWarn(\n `[twin-engine] kernel for \"${id}\" cannot carry continuity (no hydrateContinuity) — the open demand window, ` +\n 'its peak and the attention start times are lost on every restart.'\n )\n return\n }\n try {\n kernel.hydrateContinuity(plan.seed)\n } catch (err: any) {\n /* 이어받기가 실패해도 미러는 돌아야 한다 — 다만 무엇을 잃었는지 말한다. */\n twinWarn(`[twin-engine] continuity seed failed for \"${id}\" — starting without it: ${err?.message ?? err}`)\n return\n }\n const carried = [\n ...(plan.energy ? ['energy accumulation (open window, totalizer baselines, peak)'] : []),\n ...(plan.ackedCount ? [`${plan.ackedCount} acknowledged attention(s)`] : []),\n ...(plan.attentionSinceCount ? [`${plan.attentionSinceCount} attention start time(s)`] : [])\n ].join(', ')\n twinLog(`[twin-engine] mirror \"${id}\" carried over ${carried} — observation axes come from the source.`)\n }\n\n static start(id: string, domainId: string, kind: string, model: TwinModelDef, restartPolicy?: RestartPolicy, purpose?: string, resumeFrom?: number): InstanceRuntime {\n const key = runtimeKey(domainId, id)\n if (this.instances[key]) return this.instances[key]\n\n const Kernel = kernelFor(kind)\n const kernel: TwinKernel = new Kernel(domainId, undefined, this.productionSpecOf(model))\n kernel.loadTwinModel(model) // 구조만. 상태는 아래 웜스타트가 주입한다.\n this.applyOperations(kernel, model, id) // 시간·수율 명세(있으면) — 없으면 커널 기본값\n /* 추정기는 DB 조회를 포함해 비동기 — 기동을 막지 않고 붙는다(붙기 전 작업은 명세·상수로 산출). */\n this.installEstimators(kernel, domainId, id, model).catch(err => twinWarn('[twin-engine] estimator install failed', err?.message))\n /*\n * **웜스타트에 든 시간을 값으로 남긴다** (2026-08-22). 실측으로 부팅이 620~717초였고 트윈 하나에\n * 15~93초였는데, 어느 작업이 그 시간을 쓰는지 답할 계기가 없었다. 로그에도 밀리초까지 적어\n * 부팅 로그만으로 구간을 읽을 수 있게 한다.\n */\n const tWarm = performance.now()\n this.warmStart(domainId, id, kernel, purpose)\n const warmMs = performance.now() - tWarm\n if (warmMs >= 1000) twinLog(`[twin-engine] \"${id}\": warm start took ${Math.round(warmMs)}ms.`)\n /*\n * **번호를 이어 센다** — 저널에 이미 있는 번호와 겹치지 않게.\n *\n * 저널이 비어 있으면(0) 아무 일도 안 한다. 비어 있지 않은데 0부터 다시 세면 같은 트윈에 같은\n * 리비전이 둘 생기고, 재생 순서가 뒤섞이며, 시간여행이 엉뚱한 시점을 답한다 — 오류는 안 난다.\n */\n if (resumeFrom && typeof (kernel as any).resumeRevision === 'function') (kernel as any).resumeRevision(resumeFrom)\n /*\n * ── 이 트윈의 시계를 **지금**에 맞춘다 (2026-08-15) ────────────────────────\n * 커널의 기본 기준점은 상수(2026-01-01)다. 그대로 두면 시뮬 트윈의 저널 시각이 **재기동마다\n * 되감겨** 며칠 치 사건이 전부 같은 분에 몰린다 — 「언제 있었던 일인가」를 되짚을 수 없고,\n * 실 시각으로 창을 자르는 성과·이력 질의에는 그 트윈이 아예 보이지 않는다.\n *\n * 재기동하면 그만큼 시계가 앞으로 뛰는데, 그것이 사실이다: 그 사이 이 트윈은 돌지 않았고\n * 저널의 빈 구간이 그 사실을 말한다.\n */\n kernel.setClockOrigin?.(Date.now())\n const runtime: TwinRuntimeType = new TwinRuntime(kernel)\n\n /* subscribe 는 RuntimeSubscription({ unsubscribe() }) 반환 → () => void 로 감쌈. */\n /*\n * **모드를 적어 둔다** (2026-08-18 실측으로 고침).\n *\n * 시뮬 경로는 `mode` 를 비워 두었고(「미지정=sim」이라는 규약에 기대), 라이브만 적었다. 그래서\n * `modeOf()` 가 **도는 시뮬레이션에 undefined** 를 답했고, 선언·철회의 답이 「저장했다」로 나갔다 —\n * 실제로는 도는 커널이 옛 수를 그대로 쓰고 재기동 때 받는데, 그 사실이 답에서 사라진 것이다.\n * 규약에 기대는 대신 사실을 적는다: 「돌고 있나」를 묻는 쪽이 그 답을 받아야 한다.\n */\n const inst: InstanceRuntime = {\n id,\n domainId,\n mode: 'sim',\n runtime,\n kernel,\n /* 정책은 부르는 쪽이 선언한다 — 여기서 고르면 같은 트윈이 부르는 자리에 따라 다르게 재기동한다. */\n restartPolicy: readRestartPolicy(restartPolicy, `start(\"${id}\")`),\n spaceId: (model as any)?.spaceId,\n /*\n * **시뮬도 계기를 든다** (2026-08-20).\n *\n * 예전에는 `startLive` 에서만 만들었다. 그래서 도는 트윈 22개가 시뮬인 서버에서 「초당 몇 행을\n * 쓰나」·「밀린 게 있나」를 물을 자리가 **아예 없었다** — 저널 쓰기를 배치로 고친 뒤에도 그 효과와\n * 회귀를 숫자로 볼 수 없다. 세지 않는 개선은 다음 사람이 되돌려도 아무도 모른다.\n *\n * 유입(`ingested`)은 시뮬에 뜻이 없다(원본에서 받는 것이 아니라 자기가 낸다) — 그 칸은 0 으로\n * 남고, 그것이 사실이다(「받은 것이 없다」).\n */\n metrics: this.newMetrics(),\n unsub: () => {}\n }\n this.instances[key] = inst\n /* 다시 세웠으므로 지난 정지 이유는 사실이 아니다 — 남겨 두면 도는 트윈이 「굶겨서 멈췄다」고 말한다. */\n this.stopNotes.delete(key)\n delete this.recovered[key] // 웜스타트로 커널에 옮겨 심었다 — 이제 라이브가 진실이다.\n /* 원본이 선언한 자극 — 기동을 막지 않는다(추정기와 같은 규율). 못 실었으면 그 사실을 말한다. */\n this.installStimulus(domainId, id, inst).catch(err => twinWarn(`[twin-engine] \"${id}\": stimulus install failed — ${err?.message ?? err}`))\n\n /* 라이브 바인딩(P3): data 채널 필터가 subdomain 을 보므로 Domain 객체를 1회 해석해 둔다. */\n getRepository(Domain).findOne({ where: { id: domainId } }).then(d => (inst.domain = d)).catch(() => {})\n\n /* State 채널: runtime.subscribe(snapshot→delta→clock) → pubsub 브로드캐스팅(구독 리졸버가 instanceId 필터). */\n const sub = runtime.subscribe((msg: SubscriptionMessage) => {\n this.publishGuarded(\n 'twin-state',\n { twinState: { instanceId: id, kind: msg.kind, revision: (msg as any).revision, payload: msg } },\n `twin-state:${id}`\n )\n /* 영속 + 라이브 바인딩 브리지: delta 를 저널 버퍼에 담고 + 엔티티별 data(tag:) publish → 보드 컴포넌트 라이브. */\n if (msg.kind === 'delta') {\n /*\n * ── 쓰기도 **모아서** 한 번 (2026-08-20 실측으로 잡음) ────────────────────\n *\n * 여기서 델타마다 `persist()` 를 불렀다 — 행 하나당 `save()` 하나, 그리고 그 안에서\n * `structureRevOf` 를 await(구조 행이 없는 트윈은 캐시 미스가 기억되지 않아 **델타마다\n * SELECT** 였다). 데모 자극을 켠 트윈 23개에서 그 결과가 이랬다: 프로세스 CPU 81~112%,\n * 아무 일도 하지 않는 질의가 8~14초. 프로파일은 `JSON.parse`·대형 GC·스레드풀을 가리키고\n * 계기는 틱의 몫이 16% 라고 말했다 — **틱이 아니라 쓰기였다.**\n *\n * 바로 위 주석이 **브로드캐스팅**에서 같은 함정을 적어 두었다(틱 하나가 35초). 브로드캐스팅은 모으도록\n * 고쳤고 쓰기는 단건으로 남아 있었다. 같은 규율로 들인다 — ADR-0030 이 *\"기록 경로가 둘인\n * 것은 시뮬만 옆문으로 들어오기 때문\"* 이라 예고한 그 자리다.\n *\n * **리비전은 커널의 것을 그대로 든다**(라이브는 flush 때 호스트가 부여한다). 시뮬의 저널은\n * 커널 리비전으로 접히므로 여기서 다시 번호를 매기면 시간여행이 어긋난다.\n */\n ;(inst.pendingJournal ?? (inst.pendingJournal = [])).push({ event: msg.event, revision: (msg as any).revision })\n /*\n * ── 브로드캐스팅은 **모아서** 한 번 (2026-08-14 실측으로 잡음) ────────────────────\n * 여기서 곧바로 브로드캐스팅하고 있었다. 그런데 커널은 한 번의 tick 에서 사실을 **여러 개** 낸다\n * (예약·배치·완료…). 그래서 tick 하나가 전 상태 투영을 수백 번 반복했다 — `order-check`\n * 트윈에서 **틱 하나가 35초**를 먹고(단계 합은 32ms 였다: 시간은 반복 횟수에 있었다) 그\n * 35초 동안 이벤트 루프가 막혀 구독자가 아무것도 빼내지 못했다. 밀린 push 가 1024를 넘는\n * 순간 pubsub 이 오류를 내고, 그 예외가 타이머 콜백을 타고 올라와 **호스트가 죽었다.**\n *\n * 라이브는 이미 dirty 표시 + 주기 flush 로 이 문제를 풀어 두었다(BROADCAST_COALESCE_MS).\n * 시뮬만 그 규율 밖에 있었다 — 같은 규율로 들인다(최신-상태 채널이라 중간 상태를 모두\n * 보낼 이유가 없다: 200ms 마다 마지막 것 하나면 화면은 같다).\n */\n inst.dirty = true\n /* 이 사실이 건드린 물품만 다음 브로드캐스팅에서 만든다(모르면 전부). */\n this.markItemsDirty(inst, [msg.event])\n this.ensureBroadcastCoalescer()\n }\n })\n inst.unsub = () => sub.unsubscribe()\n\n /* 위에서 잰 웜스타트 시간을 계기에 적는다 — 계기는 인스턴스가 생긴 뒤에야 있다. */\n recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'warmStart', warmMs)\n\n /* 복구 앵커: 레지스트리에 model/kind/status/restartPolicy 영속(재부팅 시 이게 있어야 replay·선언 거동 가능). */\n this.register(domainId, id, kind, model, 'running', inst.restartPolicy).catch(err => twinError('twin register fail', err))\n\n /* 워커 tick — 스켈레톤은 setInterval(메인 루프). 긴 시뮬 오프-루프(worker thread)는 스케일 하드닝(향후, §host 경계). */\n inst.timer = this.startTickTimer(\n () => this.tickGuarded(domainId, id, runtime),\n t => (inst.timer = t)\n )\n return inst\n }\n\n /**\n * live-모드 기동 — **관측 모드 커널**로 실 이벤트를 미러한다(통합 P2).\n *\n * 예전에는 `StateProjector` 를 세웠다. 그래서 라이브에는 **커널이 없었고**, 그 하나 때문에 우회가\n * 줄줄이 생겼다: 예측하려면 임시 커널을 세워야 했고(`buildForecastKernel`), 주목 신호를 호스트가\n * 덧붙여야 했고(`withLiveAttentions`), AI 예측 도구는 미러에서 \"찾을 수 없다\" 로 끝났다.\n *\n * 이제 라이브 인스턴스도 **커널이다.** 같은 규칙(`ObservedReducer`)으로 이벤트를 접고, 주목 신호를\n * 스스로 내고, 그 자리에서 `fork` 해 예측한다. 구동만 다르다 — sim 은 `tick`, live 는 `apply`.\n *\n * 실 이벤트원 = reference 어댑터 openLiveFeed → face2-adapter.ingest → CanonicalEnvelope → ingestLive().\n */\n /**\n * 모델이 실은 **생산 정의**(레시피·라우트·바인딩)를 꺼낸다 — 커널의 정의-구동 모드 입구.\n *\n * ── 없을 때 무엇이 일어났나 ──────────────────────────────────────────────\n * 커널에는 정의-구동 MES 경로가 있는데 **호스트가 그것을 한 번도 넘기지 않았다.** 그래서 모든 MES\n * 트윈이 **하드코딩된 레거시 흐름**으로 돌았다 — 현장 레시피를 아무리 정성껏 적어도 커널은 그것을\n * 보지 못하고 토이 부품으로 토이 제품을 만들었다. 선언과 실행이 갈라져 있던 자리다.\n *\n * 모델에 없으면 `undefined` — 레거시 경로 그대로다(기존 트윈의 거동을 바꾸지 않는다).\n */\n /**\n * 생산 선언을 꺼낸다 — 커널 생성자에 넘긴다.\n *\n * **옛 이름(`mesSpec`)은 읽지 않는다.** 그것은 계약에 선언조차 없던 필드였고(MES 커널 생성자 인자\n * 이름이 그대로 굳은 것), 일반 기제에 한 시스템 이름이 붙어 있었기 때문에 창고 트윈이 이 자리를\n * 쓰지 못했다. 별명으로 남겨 두면 그 혼동이 계속되므로 하나로 통일했다.\n *\n * 옛 이름만 가진 모델이 있으면 **조용히 생산 선언을 잃는 대신 분명히 멈춘다** — 그 트윈은 공정이\n * 없는 채로 돌게 되고(라인이 서 있는 창고), 원인을 찾기 어렵다.\n */\n private static productionSpecOf(model: TwinModelDef | undefined): any {\n const legacy = (model as any)?.mesSpec\n if (legacy && !(model as any)?.productionSpec) {\n throw new Error(\n 'the twin model carries the retired `mesSpec` field — rename it to `productionSpec` ' +\n '(same shape; the name was tied to one kernel while the declaration is ISA-95 operations + BOM)'\n )\n }\n return (model as any)?.productionSpec\n }\n\n /**\n * 현장(공간)의 **시각 기준**을 모델에 얹는다 — 커널이 교대의 `HH:MM` 을 읽을 기준.\n *\n * **테넌트가 아니라 공간이 권위다.** 한 테넌트가 Rosarito(태평양)와 한국 공장을 함께 가질 수 있고,\n * 테넌트 단위(`Domain.timezone`)로 두면 둘 중 하나는 반드시 틀린다. 그래서 인스턴스가 연결된 공간의\n * `timezone` 을 읽는다. 공간이 말하지 않으면 **테넌트로 내려가지 않는다** — 잘못된 입자로 답하는 것이\n * 모르는 것보다 나쁘다(그때는 커널이 UTC 로 읽고, 그 기본값은 계약에 밝혀져 있다).\n *\n * 커널은 zero-dep 이라 시간대 데이터베이스를 갖지 않으므로 **분 오프셋**으로 풀어 넘긴다. 그 값은\n * 지금 계절의 것이다(일광절약시간) — 계절을 넘는 긴 예측은 한 시간 어긋난다(계약에 명시).\n */\n static async withSpaceTimeBase(model: TwinModelDef, domainId: string, spaceId?: string): Promise<TwinModelDef> {\n const sid = spaceId ?? (model as any)?.spaceId\n if (!sid) return model\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId: sid } }).catch(() => null)\n const offset = utcOffsetOf(space?.timezone)\n if (offset === undefined) {\n if (space?.timezone) twinWarn(`[twin-engine] space \"${sid}\" declares time zone \"${space.timezone}\" but it is not a known IANA zone — times will be read as UTC.`)\n return model\n }\n return { ...model, utcOffsetMinutes: offset }\n }\n\n static startLive(id: string, domainId: string, kind: string, model: TwinModelDef): InstanceRuntime {\n const key = runtimeKey(domainId, id)\n if (this.instances[key]) return this.instances[key]\n const Kernel = kernelFor(kind)\n const kernel: any = new Kernel(domainId, undefined, this.productionSpecOf(model))\n kernel.loadTwinModel(model)\n /* **세우는 쪽이 아는 사실은 세울 때 말한다.** 예전에는 첫 이벤트가 도착해야 커널이 스스로를\n 관측 구동으로 여겼고, 그래서 아직 아무것도 못 받은 미러는 시뮬레이션 취급을 받았다. */\n declareObserved(kernel, `live twin '${id}'`)\n this.applyOperations(kernel, model, id) // 명세는 라이브에도 실린다(예측 자격이 sim 과 같아진다)\n /* `projector` 필드는 옛 이름으로 남긴다 — 소비처가 `snapshot()` 을 부르므로 얇은 어댑터로 잇는다.\n * (P3 에서 소비처를 커널 어휘로 바꾸면 사라진다.) */\n const projector = { apply: (e: CanonicalEnvelope) => kernel.apply(e), snapshot: () => kernel.getSnapshot() }\n const inst: InstanceRuntime = { id, domainId, mode: 'live', restartPolicy: 'resync', kernel, projector, oee: new OeeAccumulator(), spaceId: (model as any)?.spaceId, unsub: () => {} }\n /*\n * ── 커널이 **판정으로 낸 사실**도 저널에 남는다 (2026-08-14 실측으로 잡음) ────\n *\n * 라이브는 인입 봉투만 저널에 적고 있었다(`ingestLive`). 그런데 커널은 관측을 접다가 **자기 사실**을\n * 낸다 — 에너지의 수요 구간 마감·피크 경신·감축 제안이 그렇다(`emitOp`). 그것을 구독하는 곳이\n * 없어서 그 사실들이 **커널 안에서 사라졌다**: 표본 48건이 저널에 쌓였는데 구간 마감은 0건이었고,\n * 저널을 읽는 성과 화면의 전력 타일은 영원히 나오지 않았다.\n *\n * sim 은 `runtime.subscribe` 로 같은 일을 한다 — 라이브에만 그 배선이 없었다.\n *\n * **인입의 재방출은 걸러낸다**: `apply()` 는 받은 봉투를 구독자에게 그대로 흘린다(호스트가 두 모드에서\n * 같은 배선을 쓰게 하려고). 그것까지 적으면 인입이 저널에 두 번 들어간다 — 그래서 방금 넣은 것과\n * **같은 객체**인지 보고 건너뛴다(id 비교는 어댑터가 id 를 어떻게 만드는지에 기대게 되어 약하다).\n */\n const applying = new WeakSet<object>()\n inst.applying = applying\n inst.unsub = kernel.onEvent?.((e: CanonicalEnvelope) => {\n if (e && typeof e === 'object' && applying.has(e as object)) return // 인입의 재방출 — 저널은 인입에서 한 번만\n ;(inst.pendingJournal ?? (inst.pendingJournal = [])).push(e)\n /* 커널이 낸 사실도 상태를 바꾼다(피크·마감) — 다음 브로드캐스팅 주기에 실린다. */\n inst.dirty = true\n this.markItemsDirty(inst, [e])\n this.ensureBroadcastCoalescer()\n }) ?? (() => {})\n /* 추정기(실측·거리)도 라이브에 붙인다 — 예측이 상수로 계산되지 않게. 기동을 막지 않는다. */\n this.installEstimators(kernel, domainId, id, model).catch(err => twinWarn('[twin-engine] estimator install failed', err?.message))\n inst.metrics = this.newMetrics()\n this.instances[key] = inst\n /* 미러에도 부른다 — 선언이 있으면 「미러에는 싣지 않는다」고 말해야 한다(조용한 무시 금지). */\n this.installStimulus(domainId, id, inst).catch(err => twinWarn(`[twin-engine] \"${id}\": stimulus check failed — ${err?.message ?? err}`))\n /*\n * **원천이 되풀어 주지 않는 것만 잇는다** (2026-08-18 실측으로 붙임).\n *\n * 미러는 오랫동안 아무것도 이어받지 않았다 — 진실이 원천에 있으니 옳은 판단이었지만, 원천이 **애초에\n * 다시 말해 주지 않는 축**까지 함께 버렸다: 열린 15분 구간의 누적·적산 기준점·관측 이후 최대, 그리고\n * 확인해 둔 신호와 조건이 언제부터인지. 그래서 재기동하면 오류 없이 값이 작아졌다(그 구간의 전력량과\n * 피크가 부팅 이후로만 잡히고, 세 시간째 지속된 경보가 「0초째」가 됐다 — 요금이 걸린 수다).\n *\n * 관측 축(재고·위치·설비)은 **여전히 심지 않는다** — 다음 계측이 정정하고, 심으면 떠난 물건이\n * 되살아난다. 무엇을 넘길지는 `planLiveContinuity` 가 고르고, 어떻게 흡수할지는 커널이 정한다.\n */\n this.seedLiveContinuity(domainId, id, kernel)\n delete this.recovered[key]\n /* 라이브 바인딩(data 채널) subdomain 필터용 Domain 1회 해석(sim 과 동일). */\n getRepository(Domain).findOne({ where: { id: domainId } }).then(d => (inst.domain = d)).catch(() => {})\n /*\n * 저널 revision 카운터 시드 — 기존 저널 최대치에서 이어붙임(재기동 시 revision 충돌 방지).\n *\n * ── **커널에도 같은 번호를 알려 준다** (2026-08-23 실측) ────────────────────\n * 예전에는 이 자리에서 `inst.revision`(저널 줄 번호)만 이어받고 **커널은 0 부터 세게 두었다.**\n * 그래서 체크포인트가 뜻이 다른 두 수를 나란히 적었다.\n *\n * 바깥 revision 12,972 저널에 적힌 줄 번호 (이 자리에서 이어받는다)\n * state.revision 6,478 커널이 처리한 봉투 수 (0 부터 셌다)\n *\n * 포천 미러에서 확정했다: 차이 6,494 는 그 트윈을 **다시 세운 시각**(09:11)에 저널이 이미 갖고\n * 있던 줄 수와 정확히 같았다(줄 6494 = 08:23:59, 줄 6495 = 09:11:13). 산수가 맞았다.\n *\n * 결함은 두 수가 다르다는 것 자체가 아니라 **비대칭**이다: 재기동 경로(`start` → `resumeRevision`)는\n * 커널에 번호를 알려 주는데 **이 경로(미러)는 알려 주지 않았다.** 그래서 같은 저장물을 읽는 소비처가\n * 같은 이름의 두 수를 같은 축으로 견주게 되고, 실제로 그렇게 읽혔다.\n *\n * 저널이 비어 있으면(0) 아무 일도 하지 않는다 — 새 트윈은 0 부터 세는 것이 맞다. 그리고 이 조회는\n * 비동기라 그 사이에 이벤트가 몇 건 들어와 있을 수 있는데, 그때 뒤로 되돌리는 것은 커널이 거절한다\n * (겹치는 번호를 막는 그 판정이다). 거절은 삼키지 않고 남긴다.\n */\n getRepository(TwinEvent)\n .findOne({ where: { domain: { id: domainId }, instanceId: id }, order: { revision: 'DESC' } })\n .then(top => {\n const head = top?.revision ?? 0\n inst.revision = head\n if (!head || typeof (kernel as any).resumeRevision !== 'function') return\n try {\n ;(kernel as any).resumeRevision(head)\n } catch (err: any) {\n /* 뒤로 갈 수 없다는 거절 — 이 조회가 도착하기 전에 이미 그만큼 처리했다는 뜻이다. */\n twinWarn(`[twin-engine] \"${id}\": journal head ${head} is behind the kernel — ${err?.message ?? err}`)\n }\n })\n .catch(() => (inst.revision = 0))\n this.register(domainId, id, kind, model, 'running', 'resync').catch(err => twinError('twin register fail', err))\n return inst\n }\n\n /**\n * live 이벤트 인제스트 — projector 구동 + data(tag) 브로드캐스팅(폐루프의 인바운드 도착 지점, command-routing §8.2).\n * reference 어댑터가 낸 records → 커널 face2-adapter.ingest → CanonicalEnvelope 를 여기로 밀어넣는다.\n * (State 채널 델타/저널 결선은 후속 — 스켈레톤은 data(tag) 미러 중심.)\n *\n * ── 넣은 수를 **답한다** (2026-08-20) ────────────────────────────────────────\n * 트윈이 라이브로 돌지 않으면 여기서 봉투를 버린다. 그것 자체는 맞다(넣을 커널이 없다). 문제는\n * **조용히** 버린 것이었다: 트윈이 멈춘 뒤에도 피드는 남아 레코드를 나르고, 유입 장부는 그것을\n * 「통과」로 셌다. 화면은 멈춘 트윈 옆에 「150 통과 · 100%」라고 적었다 — 사실이 사라지는 동안\n * 화면이 안심시킨 것이다.\n *\n * 그래서 **넣은 수를 돌려준다.** 부르는 쪽이 제시 수와 견주어 버려진 수를 장부에 적는다. 반환을\n * 무시하는 호출부는 그대로 동작한다(전과 같다).\n */\n static ingestLive(domainId: string, id: string, envelopes: CanonicalEnvelope[]): number {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst?.mode !== 'live' || !inst.projector) return 0\n const tIngest = performance.now()\n /* 인입 봉투를 표시해 두고 넣는다 — 커널이 그것을 재방출해도 저널에 두 번 적히지 않게(위 구독 주석). */\n for (const e of envelopes) {\n if (e && typeof e === 'object') inst.applying?.add(e as object)\n inst.projector.apply(e)\n inst.oee?.apply(e) // 관측(projector) + 계산(OEE 누적)\n }\n recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'ingest', performance.now() - tIngest)\n // 저널 결선(라이브도 sim 처럼 이벤트 영속) — 단 이벤트마다 DB write 하면 부하폭발이라 모아뒀다가\n // coalescer tick 에서 배치 기록(브로드캐스팅과 동일 주기). 히스토리 노브·타임라인·비즈니스 원장이 이 저널을 읽는다.\n ;(inst.pendingJournal ?? (inst.pendingJournal = [])).push(...envelopes)\n if (inst.metrics) { inst.metrics.ingestedTotal += envelopes.length; inst.metrics._accIngest += envelopes.length } // 계측(④-1)\n // 브로드캐스팅 병합(ingest-scale §1.1/§4.4) — apply 는 O(1)·싸다. 그러나 브로드캐스팅(snapshot O(state))은 비싸(대규모 5ms+)\n // 이벤트마다 브로드캐스팅하면 폭발 → dirty 만 찍고 coalescer tick 이 주기 브로드캐스팅(브로드캐스팅률 ≠ 인제스트률).\n inst.dirty = true\n this.markItemsDirty(inst, envelopes)\n this.ensureBroadcastCoalescer()\n return envelopes.length\n }\n\n /**\n * 구간 성과 브로드캐스팅은 **없앴다**(2026-08-06). 카드가 `twinKpi` 를 직접 묻는다.\n *\n * 왜: 카드를 여러 단계(공간·트윈·구역·자리·설비)에 붙이려면 브로드캐스팅으로는 태그가 트윈당 1,200개가 되고,\n * **모델에 카드를 하나도 안 놓아도** 30초마다 트윈마다 저널을 접었다. 질의로 바꾸니 보고 있는 카드\n * 수만큼만 들고, 같은 (대상·창·축) 은 클라이언트가 하나로 합친다.\n *\n * 덤으로 질의만 할 수 있는 것이 둘 생겼다 — **과거 시각**(`toTime`)과 **공간 단위 합산**(여러 트윈을\n * 한 번에 접기). 브로드캐스팅 루프는 트윈별이라 둘 다 못 했다.\n *\n * 축을 나눠도 폴드 비용이 같다는 실측이 근거다(`test/kpi-query-bench.test.ts`).\n */\n /**\n * 몇 창마다 한 번은 **전부** 만드나 — 사건 없이 값이 바뀌는 자리에 대한 그물.\n *\n * 25 창이면 기본 주기에서 5초다. 보장이 아니라 그물이다(위 `publishEntityData` 주석).\n */\n static FULL_BROADCAST_EVERY = 25\n /** 전부 만든 횟수 — 범위를 좁히지 못한 창이 얼마나 되는지 값으로 남는다. */\n static broadcastFullPasses = 0\n /**\n * 브로드캐스팅을 만든 횟수 전부 — **전부 만든 횟수의 분모.**\n *\n * 분자만 내면 「전부 만들기 1,200회」가 많은 것인지 적은 것인지 읽을 수 없다. 좁히기가 듣고 있으면\n * 이 값의 `1/FULL_BROADCAST_EVERY` 쯤이 전부 만든 횟수이고, 두 값이 비슷하면 범위를 거의 못 좁힌\n * 것이다(원인은 대개 「모른다」로 떨어지는 사건이다).\n */\n static broadcastPasses = 0\n\n /**\n * 이 창에 건드린 물품을 모은다 — **말할 수 없으면 범위를 버린다(전부 만든다).**\n *\n * `events` 를 주지 않으면 「무엇이 바뀌었는지 모른다」다(구조 전환처럼 상태 전반이 달라지는 자리).\n * 한 창에서 한 번 「모른다」가 되면 그 창은 끝까지 모르는 채로 둔다 — 뒤에 온 사건으로 범위를\n * 되살리면 앞 사건이 건드린 것을 빠뜨린다.\n */\n static markItemsDirty(inst: InstanceRuntime, events?: any[]): void {\n if (inst.dirtyItems === undefined) return // 이 창은 이미 「모른다」\n if (!events) {\n inst.dirtyItems = undefined\n return\n }\n for (const e of events) {\n const touched = touchedItemKeys(e)\n if (!touched) {\n inst.dirtyItems = undefined\n return\n }\n for (const epc of touched) inst.dirtyItems.add(epc)\n }\n }\n\n /** 브로드캐스팅 병합 주기(ms) — 브로드캐스팅률 상한. 인제스트가 아무리 빨라도 이 주기로만 브로드캐스팅. */\n static BROADCAST_COALESCE_MS = 200\n /**\n * ── 브로드캐스팅 주기는 **재 본 비용에 맞춘다** (2026-08-21 실측) ────────────────────\n * 한 번의 브로드캐스팅은 상태 크기에 비례한다(실측: 물품 2,400 개인 트윈 하나가 4.5ms — 상태 투영 1.7ms,\n * payload 만들기 1.8ms, 시그니처 1.0ms). 트윈이 스무 개면 200ms 마다 90ms 가 브로드캐스팅에 들어가고,\n * 그 시간에는 HTTP 도 구독도 서지 못한다.\n *\n * 그래서 한 창에서 브로드캐스팅에 쓴 시간이 주기의 일정 몫을 넘으면 **주기를 늘린다**. 화면은 조금 늦게\n * 갱신되고(최신-상태 채널이라 값은 마지막 것 하나뿐이므로 내용은 같다), 늘렸다는 것은 계기판이\n * 말한다(`broadcastCoalesceMs`). 여유가 생기면 원래 주기로 되돌린다.\n *\n * 이것은 브로드캐스팅 비용을 **줄이는 것이 아니다** — 비용을 줄이는 것은 변경분만 만드는 일이고 그것은 별\n * 작업이다. 여기서는 그때까지 호스트가 굶지 않게 상한을 둔다.\n */\n static BROADCAST_MAX_COALESCE_MS = 1000\n /** 주기의 몇 몫까지 브로드캐스팅에 써도 되는가 — 넘으면 주기를 늘린다(절반이면 나머지 절반은 남긴다). */\n static BROADCAST_LOAD_RATIO = 0.3\n /** 지금 쓰고 있는 주기(ms) — 계기판이 이 값을 읽는다. 늘어난 채로 있으면 그것이 사실이다. */\n static broadcastPeriodMs = 200\n /** 주기를 늘린 횟수 — 조용히 늦추지 않는다. */\n static broadcastBackoffs = 0\n private static broadcastTimer?: any\n\n /** live 브로드캐스팅 coalescer — dirty 인 live 인스턴스만 주기적으로 1회 브로드캐스팅(entitySigs 로 변경 엔티티만). */\n private static ensureBroadcastCoalescer(): void {\n if (this.broadcastTimer) return\n this.broadcastPeriodMs = this.BROADCAST_COALESCE_MS\n this.broadcastTimer = setInterval(() => this.flushLiveBroadcasts(), this.broadcastPeriodMs)\n if (typeof this.broadcastTimer.unref === 'function') this.broadcastTimer.unref() // 종료 비차단\n }\n\n /**\n * 브로드캐스팅에 쓴 시간을 보고 주기를 정한다 — **늘리는 것도 줄이는 것도 값에 근거한다.**\n *\n * 한 번의 flush 가 주기의 `BROADCAST_LOAD_RATIO` 를 넘게 쓰면 주기를 두 배로(상한까지), 그 몫의\n * 절반 아래로 내려오면 절반으로(원래 주기까지) 되돌린다. 문턱을 두 개 두는 이유는 하나면 경계에서\n * 늘리고 줄이기를 반복하기 때문이다.\n */\n private static adjustBroadcastPeriod(flushMs: number): void {\n const period = this.broadcastPeriodMs\n const high = period * this.BROADCAST_LOAD_RATIO\n const low = high / 2\n let next = period\n if (flushMs > high && period < this.BROADCAST_MAX_COALESCE_MS) {\n next = Math.min(this.BROADCAST_MAX_COALESCE_MS, period * 2)\n this.broadcastBackoffs++\n twinWarn(\n `[twin-engine] broadcast period ${period}ms → ${next}ms — one flush took ${Math.round(flushMs)}ms across ${Object.keys(this.instances).length} twin(s)`\n )\n } else if (flushMs < low && period > this.BROADCAST_COALESCE_MS) {\n next = Math.max(this.BROADCAST_COALESCE_MS, Math.round(period / 2))\n }\n if (next === period) return\n\n this.broadcastPeriodMs = next\n if (this.broadcastTimer) clearInterval(this.broadcastTimer)\n this.broadcastTimer = setInterval(() => this.flushLiveBroadcasts(), next)\n if (typeof this.broadcastTimer.unref === 'function') this.broadcastTimer.unref()\n }\n\n /**\n * dirty 인스턴스 브로드캐스팅 flush(주기 tick 또는 명시 호출) — **시뮬과 라이브 둘 다.**\n *\n * 예전에는 라이브만 봤다(`mode !== 'live'` 면 건너뜀). 시뮬은 delta 마다 곧바로 브로드캐스팅했고, 그것이\n * 한 tick 에서 수백 번 반복되며 이벤트 루프를 막았다(위 `start()` 주석의 35초 틱). 브로드캐스팅을 모으는\n * 규율은 모드의 성질이 아니라 **채널의 성질**이다 — 최신-상태 채널이면 중간 상태는 보낼 값이 없다.\n */\n static flushLiveBroadcasts(): void {\n const now = Date.now()\n const flushStart = performance.now()\n for (const inst of Object.values(this.instances)) {\n const isLive = inst.mode === 'live'\n /*\n * 처리량 계측(④-1) — 창(≥1s)마다 유입·브로드캐스팅·저널률 갱신. dirty 무관(유휴면 0으로 수렴).\n *\n * **두 구동을 함께 센다** (2026-08-20). 예전에는 `isLive ? … : undefined` 로 시뮬을 잘라 냈다.\n * 그래서 도는 트윈 대부분이 시뮬인 서버에서 「초당 몇 행을 쓰나」에 답할 자리가 없었다 — 저널 쓰기를\n * 배치로 고친 뒤에도 그 효과를 숫자로 볼 수 없었다. 유입(`ingestRate`)은 시뮬에서 0 으로 수렴하고,\n * 그것이 사실이다(원본에서 받는 것이 없다).\n */\n const m = inst.metrics\n if (m) {\n const dt = (now - m._windowStartMs) / 1000\n if (dt >= 1) {\n m.ingestRate = Math.round(m._accIngest / dt)\n m.broadcastRate = Math.round((m._accBroadcast / dt) * 10) / 10\n m.journalRate = Math.round(m._accJournal / dt)\n m._accIngest = 0; m._accBroadcast = 0; m._accJournal = 0; m._windowStartMs = now\n }\n }\n if (!inst.dirty) continue\n inst.dirty = false\n /* 주기마다 한 번은 범위를 버리고 전부 만든다 — 사건 없이 값이 바뀌는 자리에 대한 그물. */\n const left = (inst.fullBroadcastCountdown ?? 0) - 1\n if (left <= 0) {\n inst.fullBroadcastDue = true\n inst.fullBroadcastCountdown = this.FULL_BROADCAST_EVERY\n } else {\n inst.fullBroadcastCountdown = left\n }\n // ① 엔티티 data(tag) 브로드캐스팅 — 보드 컴포넌트 라이브 렌더.\n this.publishEntityData(inst)\n if (m) { m.broadcastTotal++; m._accBroadcast++ }\n /* ③ 저널 배치 기록 — **두 구동이 같은 문을 쓴다**(시뮬도 여기서 흘린다, §7.1). */\n this.flushJournal(inst)\n /* 여기서부터는 **라이브만**이다: 시뮬의 state 채널은 자기 콜백이 델타마다 보내므로(리비전이 커널의\n 것이다) 여기서 또 보내면 같은 신호가 두 번 간다. 저널은 위에서 이미 두 구동 몫을 흘렸다. */\n if (!isLive) continue\n // ② State 채널 브로드캐스팅 — \"바뀌었다\"는 가벼운 신호만(kind+revision). 맵 구독(subscribeTwinState)은 이 신호에\n // scheduleRefresh(250ms 디바운스)→pollLive 로 되물어봄. 스냅샷(O(state))은 보는 사람이 물을 때만 1회 계산.\n // (여기서 payload 로 스냅샷을 실으면 아무도 안 읽는데 tick 마다 통째로 떠서 순수 낭비 — 신호만 보낸다.)\n this.publishGuarded(\n 'twin-state',\n { twinState: { instanceId: inst.id, kind: 'delta', revision: inst.revision ?? 0 } },\n `twin-state:${inst.id}`\n )\n }\n /* 가동 중인 인스턴스가 하나도 없으면 tick 을 멈춘다(예전엔 「라이브가 없으면」이었는데, 이제\n 시뮬도 이 flush 에 기대므로 그 조건이면 시뮬 브로드캐스팅이 멈춘 채 남는다). */\n if (!Object.keys(this.instances).length && this.broadcastTimer) {\n clearInterval(this.broadcastTimer)\n this.broadcastTimer = undefined\n this.broadcastPeriodMs = this.BROADCAST_COALESCE_MS\n return\n }\n /* 이번 flush 가 얼마를 썼는지로 다음 주기를 정한다 — 브로드캐스팅이 루프를 다 쓰지 못하게. */\n this.adjustBroadcastPeriod(performance.now() - flushStart)\n }\n\n /**\n * 저널 행 한 줄 — **기록 경로가 둘이라(라이브 벌크·심 단건) 행 모양은 반드시 한 곳에서 만든다.**\n * 두 곳에 각자 적으면 승격 검색 키가 한쪽에만 채워지고, 반쯤 빈 색인은 \"저널에는 있는데\n * 검색으로는 안 나오는 이벤트\" 를 만든다 — 저널에서 가장 나쁜 종류의 결함이다.\n */\n /** 저널의 시각 축은 날짜다 — 못 읽는 값은 비운다(0 이나 지금으로 위장하지 않는다). */\n private static toEventTimeValue(v: any): Date | undefined {\n if (v instanceof Date) return v\n const t = typeof v === 'string' ? Date.parse(v) : NaN\n return Number.isNaN(t) ? undefined : new Date(t)\n }\n\n private static journalRow(repo: any, domainId: string, instanceId: string, e: any, revision: number, structureRev?: number) {\n return repo.create({\n domain: { id: domainId } as any,\n instanceId,\n eventType: e?.eventType,\n /* 커널이 커맨드에서 이어 준 값 — 이것이 감사 기록과 저널을 잇는 다리다. */\n correlationId: e?.correlationId,\n revision,\n /* **이 사실이 일어난 공장**을 함께 찍는다 — 이것이 없으면 나중에 구조가 바뀌었을 때 이 행을\n 새 공장에 대고 접게 되고, 그때 없던 설비에서 일이 있었던 것처럼 보인다. */\n ...(structureRev === undefined ? {} : { structureRev }),\n /* 커널은 ISO 문자열을 준다. 컬럼은 날짜다 — **여기서 옮긴다.** 문자열을 그대로 넣으면\n 드라이버가 제 형식으로 정규화하지 않아, 나중에 날짜로 거는 질의에 안 걸린다. */\n eventTime: this.toEventTimeValue(e?.eventTime),\n ...twinEventKeys(e),\n payload: e\n })\n }\n\n /**\n * 이 트윈이 지금 어느 구조로 도는가 — 이벤트에 찍을 번호. 한 번 읽고 캐시한다(쓰기마다 조회 금지).\n *\n * 없으면 `undefined` 다 — 0 이 아니다. 구조 리비전이 생기기 전에 만들어진 트윈은 아직 리비전이\n * 없고, 그 사실을 0 이라는 **유효해 보이는 번호**로 위장하면 안 된다.\n */\n /** 구조 리비전 캐시 — `null` 은 **없다는 것을 알고 있다**는 뜻이다(모름과 구별한다, §7.1). */\n private static structureRevCache: Record<string, number | null> = {}\n static async structureRevOf(domainId: string, instanceId: string): Promise<number | undefined> {\n const key = runtimeKey(domainId, instanceId)\n const cached = this.structureRevCache[key]\n /*\n * **없다는 것도 답이다** — 예전에는 찾지 못하면 캐시하지 않았다(`if (latest) …`). 그래서 구조 행이\n * 없는 트윈은 **부를 때마다 SELECT** 했고, 그 경로가 델타마다 불리고 있었다(§7.1). `null` 로 기억한다.\n */\n if (cached !== undefined) return cached === null ? undefined : cached\n const latest = await getRepository(TwinStructure).findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n this.structureRevCache[key] = latest ? latest.rev : null\n return latest?.rev\n }\n\n /** 계기 한 벌 — **두 구동이 같은 것을 든다**(한쪽만 들면 그 구동은 물어도 답이 없다). */\n private static newMetrics(): TwinMetrics {\n return { ingestedTotal: 0, broadcastTotal: 0, journaledTotal: 0, ingestRate: 0, broadcastRate: 0, journalRate: 0, backlog: 0, _accIngest: 0, _accBroadcast: 0, _accJournal: 0, _windowStartMs: Date.now() }\n }\n\n /**\n * 모아 둔 저널을 **한 번에** 쓴다 — 두 구동이 같은 문을 쓴다 (§7.1).\n *\n * ── 왜 한 함수인가 ─────────────────────────────────────────────────────────\n * 쓰는 자리가 둘이면(주기 flush · 정지) 한쪽만 고쳐지고, 그 어긋남은 **사실이 조용히 사라지는**\n * 모양으로 나타난다. 그래서 흘리는 규칙을 여기 한 곳에 둔다.\n *\n * ── 리비전을 누가 매기나 ───────────────────────────────────────────────────\n * · 라이브 — 원천은 리비전을 주지 않으므로 **호스트가** 이어 붙인다(저널 high-water 에서 시드).\n * · 시뮬 — **커널의 리비전**이 실려 온다(저널이 그것으로 접히고 시간여행이 그것을 딛는다).\n * 그래서 버퍼는 두 모양을 함께 든다: 봉투만 있으면 라이브, `{ event, revision }` 이면 시뮬이다.\n */\n private static flushJournal(inst: InstanceRuntime): Promise<void> {\n const batch = inst.pendingJournal\n if (!batch?.length) return Promise.resolve()\n inst.pendingJournal = []\n const m = inst.metrics\n /* 쓴 건수는 누적에, **지금 남은 것**은 backlog 에. 이 자리에서 배치 크기를 backlog 로 적으면\n 정상적인 배치 저장이 화면에서 경고로 보인다(2026-08-21 교정). */\n if (m) { m.journaledTotal += batch.length; m._accJournal += batch.length; m.backlog = inst.pendingJournal?.length ?? 0 }\n\n /* 시뮬은 자기 리비전을 들고 온다 — 그대로 쓴다. 라이브는 여기서 이어 붙인다. */\n const carried = batch.filter((b: any) => b && typeof b === 'object' && 'event' in b && typeof b.revision === 'number')\n const plain = batch.filter((b: any) => !(b && typeof b === 'object' && 'event' in b && typeof b.revision === 'number'))\n\n const tJournal = performance.now()\n const done = () => recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'journal', performance.now() - tJournal)\n const jobs: Promise<void>[] = []\n\n if (carried.length) jobs.push(this.persistCarried(inst.domainId, inst.id, carried))\n if (plain.length && inst.revision != null) {\n const start = inst.revision\n inst.revision = start + plain.length\n jobs.push(this.persistBatch(inst.domainId, inst.id, plain, start))\n }\n if (!jobs.length) return Promise.resolve()\n /*\n * **약속을 돌려준다** — 주기 flush 는 기다리지 않지만(핫 경로) **정지는 기다려야 한다.** 기다리지\n * 않으면 곧바로 이어지는 저널 재생이 아직 안 쓰인 구간을 못 보고, 웜스타트가 「없던 일」로 시작한다\n * (실제로 그렇게 깨졌다: 확보분을 든 오더가 되살아나지 못했다).\n */\n const written = carried.length + plain.length\n return Promise.all(jobs)\n .then(() => {\n done()\n /*\n * **적힌 뒤에 적는다** — 실패한 배치를 「남았다」고 세면 추이가 없는 사실을 있다고 말한다.\n * 창(10분)에 쌓이므로 재기동 뒤에도 「지난 여섯 시간 얼마나 적었나」를 답할 수 있다.\n */\n this.recordJournalWrite(inst.domainId, inst.id, written)\n })\n .catch(err => twinError('twin journal flush fail', err))\n }\n\n /**\n * 커널이 매긴 리비전을 그대로 들고 벌크 저장 — 시뮬 경로.\n *\n * 예전에는 이 경로가 **델타마다 한 행씩** 저장했다(그리고 행마다 구조 리비전을 물었다). 규모에서 그것이\n * 호스트를 먹었다(§7.1 실측). 여기서 구조 리비전은 **한 번만** 묻는다.\n */\n static async persistCarried(domainId: string, instanceId: string, items: { event: any; revision: number }[]): Promise<void> {\n const repo = getRepository(TwinEvent)\n const structureRev = await this.structureRevOf(domainId, instanceId)\n const rows = items.map(it => this.journalRow(repo, domainId, instanceId, it.event, it.revision, structureRev))\n await this.insertRows(repo, rows)\n }\n\n /**\n * 저널 행을 넣는다 — **넣기만 한다**(2026-08-20).\n *\n * 예전에는 `save()` 였다. 그런데 `save` 는 넣은 뒤 생성 컬럼을 읽으려고 **행마다 SELECT 를 한 번 더**\n * 한다(시험 로그에서 그 질의가 그대로 보였다: `SELECT … FROM twin_events WHERE id = ?`). 저널은\n * append-only 이고 부르는 쪽은 돌려받은 엔티티를 쓰지 않으므로 그 왕복이 순수 낭비다.\n *\n * 묶음은 **나눠서** 넣는다: 한 문에 열이 열다섯인 행을 수천 개 실으면 드라이버의 파라미터 한계에\n * 걸린다(pg 는 65,535개). 500행이면 어느 드라이버에서도 안전하다.\n */\n private static async insertRows(repo: any, rows: any[]): Promise<void> {\n const CHUNK = 500\n /*\n * ── 한 트랜잭션으로 감싸 보았고, **되돌렸다** (2026-08-22 실측) ─────────────\n * 「청크마다 커밋하면 fsync 가 그만큼 늘어난다」는 이유로 전체를 한 트랜잭션에 감쌌다. 쓰기 자체는\n * 실제로 빨라졌다 — 느린 질의 목록에서 이 INSERT 가 사라졌다. **그런데 서버가 더 느려졌다.**\n *\n * 감싸기 전 느린 질의 최대 32.3초 · ROLLBACK 없음\n * 감싼 뒤 느린 질의 최대 50.2초 · ROLLBACK 36.3초 등장\n *\n * 기전은 드라이버다. TypeORM 의 sqlite 드라이버는 연결을 **하나**만 든다(풀 없음). 트랜잭션이\n * 열려 있는 동안 그 유일한 연결은 이 묶음의 것이므로, **묶음이 끝날 때까지 앱의 모든 질의가\n * 기다린다.** 청크마다 커밋하면 그 사이에 다른 질의가 끼어들 자리가 생긴다 — fsync 를 더 치르는\n * 대신 **머리 막힘이 짧아진다.**\n *\n * 즉 여기서는 「커밋 수를 줄이는 것」이 목적이 아니다. 목적은 **한 번에 오래 붙잡지 않는 것**이다.\n * 저널 묶음의 원자성은 그 대가를 치를 만큼의 값이 아니다: 저널은 append-only 이고 리비전이\n * 이어지므로, 절반만 들어간 묶음은 다음 기동의 replay 가 그 지점부터 이어받는다.\n *\n * 연결 풀이 있는 드라이버(postgres·mysql)에서는 판단이 달라질 수 있다 — 그때는 이 주석을 근거로\n * 다시 재고 정하라. **드라이버마다 다른 결론이 나는 자리다.**\n */\n for (let i = 0; i < rows.length; i += CHUNK) await repo.insert(rows.slice(i, i + CHUNK))\n }\n\n /** live 저널 배치 기록 — 모아둔 CanonicalEnvelope 들에 startRevision+1.. 을 부여해 벌크 저장(coalescer tick 당 1회). */\n static async persistBatch(domainId: string, instanceId: string, envelopes: any[], startRevision: number): Promise<void> {\n const repo = getRepository(TwinEvent)\n const structureRev = await this.structureRevOf(domainId, instanceId)\n const rows = envelopes.map((e, i) => this.journalRow(repo, domainId, instanceId, e, startRevision + i + 1, structureRev))\n await this.insertRows(repo, rows)\n }\n\n /** 레지스트리 upsert(도메인+instanceId 유니크). status 인자로 provision(stopped)/start(running) 공용. */\n static async register(\n domainId: string,\n instanceId: string,\n kind: string,\n model: TwinModelDef,\n status: 'running' | 'stopped' = 'running',\n restartPolicy?: RestartPolicy,\n origin?: any,\n /*\n * 사람이 부르는 이름과 **누가 했나** — 업무키를 나눠 둔 대가로 이름을 함께 실어야 한다.\n * 사람 없는 경로(부팅 자동 프로비저닝·복구)는 `actor` 를 주지 않는다 — 아무 사용자를 적으면\n * 감사 기록이 거짓이 된다.\n */\n meta?: { name?: string; description?: string; actor?: { id: string } }\n ): Promise<void> {\n const repo = getRepository(TwinInstance)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n instanceId,\n kind,\n model,\n // 인스턴스↔공간 1급 링크(space #3) — model.spaceId/areaId 를 컬럼으로 승격(dual-write). model JSON 도 유지(커널·복구용).\n spaceId: (model as any)?.spaceId ?? existing?.spaceId,\n areaId: (model as any)?.areaId ?? existing?.areaId,\n /* 재기동 정책(ADR-0029 §2) — 명시값 우선, 없으면 기존값 보존(재프로비전이 선언을 지우지 않게).\n **둘 다 없으면 오류를 낸다**: 예전에는 여기서 기본값을 각인했는데, 그 기본값이 「저널 초기화」라서\n 선언을 빠뜨린 프로비저닝이 조용히 이력을 지우는 트윈을 만들었다. 선언은 부르는 쪽의 몫이다. */\n restartPolicy:\n restartPolicy ??\n readRestartPolicy(\n existing?.restartPolicy,\n `register(\"${instanceId}\") did not declare a restart policy and the stored row has none`\n ),\n /* 용도도 각인한다. 벤치로 뒤집는 것은 `setPurpose` 하나뿐이므로 기존값을 반드시 보존한다\n — 여기서 덮으면 재프로비전이 벤치 사본을 운영 트윈으로 되돌린다. */\n purpose: existing?.purpose ?? 'operational',\n /* **다시 읽는 방법**을 각인한다. 명시값 우선, 없으면 기존값 보존 — 원천을 모르는 호출이\n 한 번 지나가면서 이미 알던 것을 지워 버리면, 그 트윈은 다시 읽을 수 없는 트윈이 된다. */\n origin: origin ?? existing?.origin ?? null,\n /* 이름은 **덮지 않고 채운다** — 사용자가 고친 이름을 재프로비전이 되돌리면 안 된다. */\n name: existing?.name ?? meta?.name ?? null,\n description: existing?.description ?? meta?.description ?? null,\n /* 만든 사람은 처음 한 번만. 고친 사람은 사람이 한 경우에만 갱신한다. */\n ...(existing ? {} : meta?.actor ? { creator: { id: meta.actor.id } as any } : {}),\n ...(meta?.actor ? { updater: { id: meta.actor.id } as any } : {}),\n status\n })\n )\n }\n\n /**\n * 라이브 구조 변이(resource.add 등)를 저장된 model 에 반영 — 런타임 커널의 무버를 registry model.equipment 에 동기.\n * 이게 없으면 런타임엔 추가돼도(상태·저널엔 반영) 저장 model 는 원본이라 프로비저닝 편집기·재기동(loadTwinModel)이\n * 추가분을 잃는다. 기존 model.equipment 항목은 보존(homeLocation 유지)하고 새 id 만 append(추가 시점 location=homeLocation).\n * 좌표(layout)만 다루는 register 와 달리 equipment 집합을 갱신하나, 재프로비전(purge)이 아니라 in-place 갱신이라\n * 저널은 보존된다(추가는 이미 equipment 델타로 저널됨 → replay 는 id-keyed upsert 라 이중계산 없음).\n */\n static async syncBoardEquipment(domainId: string, instanceId: string): Promise<void> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n const snap = inst?.kernel?.getSnapshot?.()\n if (!snap?.equipment) return\n const repo = getRepository(TwinInstance)\n const reg = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) return\n const model = reg.model as TwinModelDef\n const known = new Set((model.equipment ?? []).map(m => m.id))\n const added = snap.equipment\n .filter((m: any) => !known.has(m.id))\n .map((m: any) => ({ id: m.id, kind: m.kind, homeLocation: m.location }))\n if (!added.length) return\n model.equipment = [...(model.equipment ?? []), ...added]\n reg.model = model\n await repo.save(reg)\n }\n\n /**\n * 프로비저닝 — 레지스트리에 구조(model)를 등록만 하고 기동하지 않음(status='stopped').\n * 재프로비전 시 구조 시그니처가 바뀌면(노드·무버 집합/속성 변경) 기존 저널을 purge 한다(ADR-0015):\n * model 는 replay 의 마스터라 구조가 바뀌면 과거 이벤트의 전제가 깨진다. 좌표(layout)만 바뀌면 저널 보존.\n */\n /**\n * 실행 중이면 구조를 교체하지 않는다 — **판정 문장을 한 곳에 둔다.**\n *\n * 인제스트는 전량 교체라, 이벤트를 접고 있는 커널 밑에서 바닥을 바꾸는 셈이 된다. 지금은 거절이\n * 유일한 답이지만 최종형은 아니다(`adoptStructure` 배선). 두 곳에서 같은 문장으로 거절해야\n * 나중에 이 규칙을 걷어낼 때 걷어낼 것이 하나로 보인다.\n */\n private static assertNotRunning(domainId: string, instanceId: string): void {\n if (!this.instances[runtimeKey(domainId, instanceId)]) return\n /*\n * **거절도 번역돼야 한다.** 이 문장은 전달되어 리졸버의 `catch` 를 지나 화면 토스트에 그대로\n * 떴다 — 다섯 언어 제품에서 영어 한 줄이 사용자에게 보였다(2026-08-14 실측).\n *\n * 그래서 코드와 파라미터를 예외에 실어 보낸다(`ImportSpaceRefusal` 과 같은 규약: 영어 문장은\n * canonical 이고 로그·폴백으로만 쓰인다). 이유가 코드로 오면 화면이 옮길 수 있다.\n */\n const err: any = new Error(`instance \"${instanceId}\" is running — stop before re-provisioning`)\n err.code = 'twin-running'\n err.params = { instanceId }\n throw err\n }\n\n /**\n * 돌면서 공장을 전환한다 — **미러 전용.**\n *\n * 미러가 비추는 현실은 안 멈춘다. 설비 한 대가 늘었다고 트윈을 멈췄다 세우면 그 사이의 사실을\n * 잃고, 라이브에서 유실은 곧 거짓이다. 그래서 미러는 **동작 중에** 새 구조를 받는다.\n *\n * 시뮬레이션은 여기 오지 않는다. 조건이 바뀐 실험은 다른 실험이므로 멈추고 다시 세우는 것이\n * 옳다 — 커널이 그렇게 거절한다(`FlowEngine.adoptStructure`).\n *\n * 세 가지가 **함께** 일어나야 한다. 하나라도 빠지면 층이 어긋난다:\n * ① 리비전 — 이 시점 이후의 이벤트가 새 번호를 달고 다닌다(재생이 마디를 나눌 수 있게)\n * ② 저장 model·구조 행 — 조회가 새 구조를 본다\n * ③ 커널 — 지금 접히는 이벤트가 새 구조 위에서 접힌다\n */\n static async adoptStructure(\n domainId: string,\n instanceId: string,\n model: TwinModelDef,\n comment?: string,\n origin?: any\n ): Promise<{ rev: number } & StructureShift> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n if (!inst) throw new Error(`instance \"${instanceId}\" is not running — provision it instead of adopting`)\n if (inst.mode !== 'live')\n throw new Error(`instance \"${instanceId}\" is a simulation — stop it and re-provision (a changed experiment is a different experiment)`)\n\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg) throw new Error(`instance \"${instanceId}\" is running but not registered — refusing to adopt into an unknown twin`)\n\n const rev = await this.recordStructure(domainId, instanceId, model, comment)\n await this.register(domainId, instanceId, reg.kind, model, 'running', undefined, origin)\n /* 커널을 **마지막에** 전환한다 — 저장이 실패하면 메모리만 새 구조가 되어, 재기동하면 조용히\n 옛 구조로 돌아간다(고치기 어려운 어긋남이다). */\n const shift: StructureShift = inst.kernel.adoptStructure(model)\n /*\n * **공정 명세·현장이 정한 시간도 함께 싣는다** — 커널의 구조 전환은 자리·설비를 갈지만, 공정 시간은\n * 호스트가 실어 주는 것이므로(`model.localDurations`) 여기서 다시 부르지 않으면 돌고 있는 미러는\n * 재기동할 때까지 옛 시간으로 돈다(화면은 「넣었습니다」라고 말한 값이다).\n */\n this.applyOperations(inst.kernel, model, instanceId)\n\n /*\n * **투영 행도 새 구조를 따른다** (2026-08-18 실측으로 붙임).\n *\n * 행(`twin_locations`·`twin_equipment`)은 구조의 캐시다. 그런데 이 경로는 커널만 갈고 행은 그대로\n * 두었다 — 돌고 있는 미러에 값을 선언하면 커널은 새 값으로 계산하는데 **항목 패널은 옛 행을 보여\n * 준다**(넣은 값이 화면에서 보이지 않는다). 구조가 바뀐 순간이 곧 캐시를 다시 그릴 순간이다.\n *\n * 실패는 흡수한다: 투영이 막혀도(예: 모델에 중복 id) 커널은 이미 새 구조로 돌고 있으므로 그 사실을\n * 되돌리지 않는다 — 다만 조용히 넘기지 않고 말한다.\n */\n await projectStructure(domainId, instanceId, model, instanceId).catch((err: any) =>\n twinWarn(`[twin-engine] \"${instanceId}\" adopted a new structure but its projected rows were not refreshed — ${err?.message ?? err}`)\n )\n\n /*\n * **구조가 바뀐 순간이 상태가 바뀐 순간이다** — 그러니 브로드캐스팅한다.\n *\n * ── 무엇이 났나 (2026-08-18) ────────────────────────────────────────────\n * 구조 전환은 커널만 갈고 조용히 끝났다. 그런데 화면이 보는 것 상당수가 구조에서 파생된다 —\n * 계약 대비 판정, 주목 신호, 자리 색. 현장이 계약을 고쳐 선언한 순간 조건이 성립하는데도, 상태\n * 브로드캐스팅이 없어서 지도 레일은 **다음 계측 표본이 올 때까지** 옛 화면을 들고 있었다(그 사이 헤더\n * 배지는 4초 폴링으로 먼저 알아, 「배지엔 있고 목록엔 없는」 어긋난 화면이 실제로 보였다).\n *\n * 새 브로드캐스팅 경로를 만들지 않는다: dirty 를 세워 **이미 있는 병합 규율**(200ms)에 얹는다. 구조 전환은\n * 드물지만, 여러 트윈에 잇달아 들어올 수 있고(현장 일괄 선언) 그때도 브로드캐스팅률 상한은 지켜야 한다.\n */\n inst.dirty = true\n /* 구조가 갈렸으면 무엇이 달라졌는지 사건으로 말할 수 없다 — 전부 다시 만든다. */\n this.markItemsDirty(inst)\n this.ensureBroadcastCoalescer()\n\n return { rev, ...shift }\n }\n\n static async provision(\n domainId: string,\n instanceId: string,\n kind: string,\n model: TwinModelDef,\n /**\n * **재기동 정책은 생성 시점의 선언이다**(ADR-0029 §2) — 트윈은 정책 없이 존재할 수 없다.\n *\n * 예전에는 이 자리가 없었고 `register` 가 기본값(`sim-experiment` = 저널 초기화)을 각인했다. 그래서\n * 선언을 빠뜨린 프로비저닝이 **재기동마다 이력을 지우는 트윈**을 조용히 만들었다. 이제 만드는 쪽이\n * 말해야 한다: 이 트윈이 자기 과거를 어떻게 대하는지는 만드는 사람이 아는 사실이다.\n */\n restartPolicy: RestartPolicy,\n comment?: string,\n origin?: any,\n /** 이름·저자 — 업무키를 나눠 둔 대가로 이름을 함께 남긴다(`register` 의 `meta` 그대로). */\n meta?: { name?: string; description?: string; actor?: { id: string } }\n ): Promise<void> {\n this.assertNotRunning(domainId, instanceId)\n /* 종류를 **저장하기 전에** 검증한다. 나중에 기동할 때 걸리면 원인이 프로비저닝에서 멀어지고,\n 그 사이 레지스트리에는 돌릴 수 없는 트윈이 앉아 있다. */\n kernelFor(kind)\n const repo = getRepository(TwinInstance)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n\n /*\n * **구조가 바뀌어도 역사를 지우지 않는다.**\n *\n * 예전에는 서명이 다르면 그 트윈의 저널을 통째로 지웠다. 안 지우면 옛 이벤트를 새 공장에 대고\n * 접게 되어 이력이 거짓말을 했기 때문이다 — 부스가 둘이던 시절의 사실을 여섯 개짜리 공장에\n * 접으면 그때 없던 부스에서 일이 있었던 것처럼 보인다. 선택지가 **역사를 잃거나 거짓말을\n * 하거나** 둘뿐이었고, 그래서 공장을 고칠 때마다 이력을 버려야 했다.\n *\n * 이제 셋째 길로 간다: 바뀐 구조를 **새 리비전**으로 남기고, 앞으로 쓰이는 이벤트가 그 번호를\n * 달고 다닌다. 재생은 구조가 바뀌는 지점에서 전환한 뒤 이어 접는다(`replaySegments`).\n */\n await this.recordStructure(domainId, instanceId, model, comment)\n await this.register(domainId, instanceId, kind, model, existing?.status === 'running' ? 'stopped' : (existing?.status as any) ?? 'stopped', restartPolicy, origin, meta)\n }\n\n /**\n * 이 구조를 리비전으로 남기고 그 번호를 돌려준다 — **바뀌었을 때만** 새 번호가 생긴다.\n *\n * 프로비저닝은 부팅마다 다시 도는데, 그때마다 리비전이 늘면 이력이 뜻 없는 마디로 잘게 쪼개진다.\n * 그래서 **구조 서명이 같으면 있던 리비전을 그대로 쓴다.**\n */\n static async recordStructure(domainId: string, instanceId: string, model: TwinModelDef, comment?: string): Promise<number> {\n const repo = getRepository(TwinStructure)\n const signature = this.structureFingerprint(model)\n const latest = await repo.findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n\n /*\n * **저장된 지문이 아니라 저장된 공장과 비교한다.**\n *\n * 지문 계산 방식을 한 번이라도 바꾸면(원문 → 해시로 바꿨다) 저장된 문자열은 전부 옛 방식의\n * 것이라 무엇과도 안 맞는다. 그러면 **아무것도 안 바뀐 트윈들이 전부 \"구조가 바뀌었다\"** 로\n * 기록된다 — 실제로 그렇게 됐고, 재기동 한 번에 리비전이 통째로 하나씩 늘었다.\n *\n * 그래서 안 맞을 때 한 번 더 묻는다: 저장된 **모델**로 지문을 다시 계산하면 같은가? 같다면\n * 공장은 그대로이고 지문 표기만 낡은 것이니, 리비전을 만들지 않고 표기만 고친다.\n */\n if (latest && latest.signature !== signature && this.structureFingerprint(latest.model as TwinModelDef) === signature) {\n latest.signature = signature\n await repo.save(latest)\n }\n\n if (latest?.signature === signature) {\n this.structureRevCache[runtimeKey(domainId, instanceId)] = latest.rev\n return latest.rev\n }\n\n const rev = (latest?.rev ?? 0) + 1\n await repo.save(repo.create({ domain: { id: domainId } as any, instanceId, rev, signature, model: model as any, ...(comment ? { comment } : {}) }))\n this.structureRevCache[runtimeKey(domainId, instanceId)] = rev\n /* 구조가 바뀌면 재구성 캐시는 옛 공장의 것이다 — 버린다(지우는 건 캐시뿐, 사실은 남는다). */\n delete this.recovered[runtimeKey(domainId, instanceId)]\n if (latest) console.info(`[twin-engine] \"${instanceId}\" structure changed → revision ${rev} (history kept; older events stay under revision ${latest.rev}).`)\n return rev\n }\n\n /**\n * 이 트윈이 거쳐 온 구조들 — **무엇이 언제 달라졌나.**\n *\n * 리비전은 그 시절 공장을 통째로 담지만(재생에 필요하다), 사람이 보고 싶은 것은 통째가 아니라\n * 차이다. 모델은 빼고 **차이 요약만** 내보낸다 — 62KB 짜리 보드를 화면에 실어 보낼 이유가 없다.\n */\n static async structureHistory(\n domainId: string,\n instanceId: string\n ): Promise<{ rev: number; createdAt?: Date; comment?: string; events: number; diff: StructureDiff }[]> {\n const revs = await getRepository(TwinStructure).find({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'ASC' } })\n if (!revs.length) return []\n\n /* 리비전마다 그 아래에서 몇 건이 일어났나 — 이력의 무게를 보여준다(짧게 스쳐간 구조인지). */\n const counts = new Map<number | null, number>()\n for (const row of await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select('e.structureRev', 'rev')\n .addSelect('COUNT(1)', 'n')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n .groupBy('e.structureRev')\n .getRawMany())\n counts.set(row.rev === null || row.rev === undefined ? null : Number(row.rev), Number(row.n))\n\n /* 번호 없는 옛 행은 **가장 오래된 리비전**의 몫이다 — 재생이 그렇게 접으므로 세는 것도 같아야 한다. */\n const oldest = revs[0].rev\n const legacy = counts.get(null) ?? 0\n\n return revs.map((r, i) => ({\n rev: r.rev,\n createdAt: r.createdAt,\n ...(r.comment ? { comment: r.comment } : {}),\n events: (counts.get(r.rev) ?? 0) + (r.rev === oldest ? legacy : 0),\n diff: diffStructures(i === 0 ? undefined : (revs[i - 1].model as any), r.model as any)\n }))\n }\n\n /** 지금 쓰이는 구조 리비전 — 이벤트에 찍을 번호. 아직 없으면 기록하며 만든다. */\n static async currentStructureRev(domainId: string, instanceId: string, model?: TwinModelDef): Promise<number | undefined> {\n const latest = await getRepository(TwinStructure).findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n if (latest) return latest.rev\n return model ? this.recordStructure(domainId, instanceId, model) : undefined\n }\n\n /** 구조 동일성 지문 — 좌표(layout) 등 뷰 관심사는 제외하고 커널이 보는 위상·용량·무버만. */\n /**\n * 지문을 **64자로 줄인다** — 컬럼이 varchar(64) 다.\n *\n * 원문 지문은 자리·설비를 전부 이어 붙인 문자열이라 큰 공장에서는 수만 자가 된다. sqlite 는\n * 길이를 강제하지 않아 그냥 들어가지만 **Postgres 는 거기서 터진다** — 개발에서는 멀쩡하고\n * 운영에서만 죽는 종류의 실패다. 비교에만 쓰는 값이므로 해시로 충분하다.\n */\n private static structureFingerprint(model: TwinModelDef): string {\n return createHash('sha256').update(this.structureSignature(model)).digest('hex')\n }\n\n private static structureSignature(model: TwinModelDef): string {\n const locations = [...(model.locations ?? [])]\n .map(n => `${n.id}:${n.type}:${n.capacity}`)\n .sort()\n .join('|')\n const equipment = [...(model.equipment ?? [])]\n .map(m => `${m.id}:${m.kind}:${m.homeLocation}`)\n .sort()\n .join('|')\n return `N[${locations}]M[${equipment}]`\n }\n\n /** 레지스트리 model 로 기동(프로비전된 인스턴스 start). model 인자 없이 저장된 구조로 재기동. */\n static async startFromRegistry(domainId: string, instanceId: string, restartPolicy?: RestartPolicy): Promise<InstanceRuntime> {\n const key = runtimeKey(domainId, instanceId)\n if (this.instances[key]) return this.instances[key]\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) throw new Error(`instance \"${instanceId}\" not provisioned (no model)`)\n\n /*\n * ── 선언된 `restartPolicy` 가 **기동 방식을 정한다** (2026-08-20) ──────────\n *\n * 예전에는 이 함수가 정책을 **읽어서 넘기기만** 했고, 기동은 언제나 시뮬 경로였다. 그래서 미러로\n * 선언한 트윈을 화면에서 시작하면 **시뮬로 떴다** — 그 트윈은 유입을 받지 못한다(`ingestLive` 는\n * 라이브가 아니면 0 을 돌려준다). 오류는 나지 않고, 화면에는 「running」이라 적힌다.\n *\n * 부팅 경로(`resumeRow`)에는 그 갈림이 있었는데 여기에는 없었다. 즉 **부팅으로 살아난 미러는\n * 받고, 사람이 시작한 미러는 받지 못했다.** 같은 선언이 두 결과를 내는 것은 결함이다.\n *\n * 갈림을 여기 한 곳에 둔다 — 부팅도 이 문을 지난다.\n *\n * ── `reset` 은 선언대로 **저널을 비운다** (2026-08-20) ───────────────────\n * 「seed 재현」은 백지에서 다시 시작한다는 뜻이다. 예전에는 그 선언이 구현되지 않아 `reset` 트윈이\n * 사실상 이어졌고, 그래서 「이 트윈의 이력은 왜 재기동을 넘겨 남아 있나」를 아무도 설명할 수 없었다.\n *\n * 이것은 **사실을 지우는 동작**이라 순서를 지켜 켰다: 먼저 사람이 각 트윈의 정책을 다시 선언할 문을\n * 만들고(`setTwinRestartPolicy`), 이력을 두고 볼 트윈을 `resume` 으로 옮긴 뒤에 켠다. 그 순서를\n * 뒤집으면 선언을 지킨 대가로 남의 이력을 지운다.\n */\n const policy = restartPolicy ?? readRestartPolicy(reg.restartPolicy, `twin \"${instanceId}\"`)\n if (policy === 'resync') {\n /* 미러는 **관측 구동**으로 세운다 — 시뮬로 세우면 없던 움직임을 스스로 만든다.\n 시각 기준은 공간이 갖는다(부팅 경로와 같은 규칙). */\n return this.startLive(instanceId, domainId, reg.kind, await this.withSpaceTimeBase(reg.model as TwinModelDef, domainId))\n }\n if (policy === 'reset') {\n /*\n * 씨앗 재현 — 저널을 비우고 리비전 0 부터 다시 센다. 복구본도 함께 버린다(`resetJournal` 이 한다):\n * 남겨 두면 백지로 시작한 트윈에 옛 상태가 되살아나 「씨앗 재현」이 아니게 된다.\n *\n * **벤치 사본은 예외다.** 그것은 누군가 지켜보는 실험이고, 그 실험의 기록을 기동이 지우면 실험이\n * 사라진다(부팅은 벤치를 되살리지도 않는다 — `resumeRow`).\n */\n if (reg.purpose !== 'bench') await this.resetJournal(domainId, instanceId)\n }\n\n /*\n * 웜스타트 재료를 **여기서 확실히 확보한다.**\n * `start()` 는 동기라 스스로 캐시를 읽을 수 없어서 `recovered` 에 미리 담겨 있기를 기대하는데,\n * 그건 `bootstrap()` 이 먼저 돌았을 때만 참이다. 부팅 순서에 기대면 어떤 날은 재고가 살아나고\n * 어떤 날은 조용히 빈 채로 뜬다 — 재현되지 않는 결함이 가장 나쁘다.\n * 체크포인트 캐시 우선(O(1) + 라이브 파생상태 보존), 없으면 저널 replay 폴백(부팅과 같은 순서).\n */\n if (!this.recovered[key] && reg.purpose !== 'bench') {\n const cached = await this.loadSnapshot(domainId, instanceId).catch(() => null)\n if (cached?.state) {\n this.recovered[key] = { revision: cached.revision, state: cached.state }\n } else {\n const state = await this.recover(domainId, instanceId).catch(() => null)\n if (state) this.recovered[key] = { revision: state.revision, state }\n }\n }\n\n /*\n * 저널에 남아 있는 마지막 번호 — **모드와 무관하게** 이것을 이어 센다.\n *\n * 저널을 초기화하고 기동하는 정책(`reset`)이라면 이 값이 0이라 아무 영향이 없다. 규칙을\n * 모드별로 구분하지 않는 이유: \"저널이 비어 있지 않으면 그 뒤부터\" 하나면 어느 모드에서도\n * 겹칠 수 없고, 모드가 늘어도 이 자리를 다시 손볼 일이 없다.\n */\n const last = await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select('MAX(e.revision)', 'max')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n .getRawOne()\n\n return this.start(\n instanceId,\n domainId,\n /* 커널 종류·현실 선언은 레지스트리에 반드시 있다(둘 다 NOT NULL). 예전에는 `?? 'wms'` 로\n 메웠는데, 그건 YMS/MES 트윈을 **조용히 WMS 로 부팅**시키는 길이었다 — 오류 없이 다른 공장이 뜬다. */\n reg.kind,\n reg.model as TwinModelDef,\n /* 저장된 값은 위에서 **엄격히** 읽었다 — 모르는 값을 기본값으로 메우면 그 트윈이 조용히 다르게 재기동한다. */\n policy,\n reg.purpose,\n Number(last?.max ?? 0) || 0\n )\n }\n\n /**\n * 선언 기반 부팅(§0 프레임 ① → 부팅 거동 매핑) — 트윈이 선언한 restartPolicy 에 따라 재기동 방식을 구분한다.\n * 부팅 경로를 한 곳에 모아 \"런타임 ≠ 현실\" 범주오류를 코드로 강제한다.\n * - 'resync' : 현실=외부 실물 → startLive(재동기). 이벤트는 어댑터 ingest 로 유입, 커널 tick 없음.\n * - 'resume' : 생성 타임라인 지속 → 저널 보존 + resume(현실 이어감).\n * ⚠ GATE(§8 ②③): 커널 상태 직렬화/재개가 아직 없어 진짜 resume 불가 → 실 필요·실부하 시 구현.\n * 그때까지는 저널을 보존하되 revision 충돌을 피하려 fresh 로 기동하고, 선언과 구현의 간극을 크게 경고한다.\n * - 'reset' : seed 재현 → resetJournal + fresh 기동(백지 시작이 버그가 아니라 선언된 거동).\n * 반환: 기동된 InstanceRuntime.\n */\n static async bootDeclared(domainId: string, instanceId: string, mode: RestartPolicy): Promise<InstanceRuntime> {\n if (mode === 'resync') {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) throw new Error(`instance \"${instanceId}\" not provisioned (no model)`)\n return this.startLive(instanceId, domainId, reg.kind, reg.model as TwinModelDef)\n }\n if (mode === 'resume') {\n /*\n * **이어지는 현실** — 저널을 지우지 않는다.\n *\n * 예전에는 여기서 저널을 지우고 fresh 로 띄웠다. resume 기계장치가 없다고 봤기 때문인데,\n * 실제로 없던 것은 **번호 이어 세기 하나**였다: 상태 복원은 이미 `startFromRegistry` 가\n * 저널 재생(또는 체크포인트)으로 하고 있었고, 막힌 것은 커널이 리비전을 0부터 다시 세어\n * 기존 행과 겹치는 문제였다. 그 하나를 `resumeRevision` 으로 풀었으므로 이제 이어 간다.\n *\n * 아직 이어지지 않는 것(정직하게): 시나리오 생성기의 난수 흐름은 재기동에 이어지지 않는다 —\n * 같은 씨앗에서 다시 시작하므로 자극의 패턴이 재기동 지점에서 한 번 끊긴다. 쌓인 사실과\n * 상태는 이어지고, 앞으로 일어날 일의 무작위 순서만 새로 시작한다.\n */\n return this.startFromRegistry(domainId, instanceId, 'resume')\n }\n // `reset`: seed 재현 — 저널 초기화 후 revision 0 부터 재실행.\n await this.resetJournal(domainId, instanceId)\n return this.startFromRegistry(domainId, instanceId, 'reset')\n }\n\n /**\n * 저널 초기화 — 인스턴스 이벤트 저널 purge(레지스트리·상태는 유지).\n * 데모 fresh-start 용: 매 부팅 seed 부터 새로 실행하는 데모에서, 복구본 폐기 후 revision 0 부터 재실행하면\n * 옛 런과 revision 이 겹쳐 저널이 오염된다 → start 전에 호출해 현재 런만 남긴다.\n */\n static async resetJournal(domainId: string, instanceId: string): Promise<void> {\n await getRepository(TwinEvent).delete({ domain: { id: domainId } as any, instanceId })\n delete this.recovered[runtimeKey(domainId, instanceId)]\n /*\n * ── **체크포인트도 함께 무효로 만든다** (2026-08-20) ──────────────────────\n *\n * 저널만 지우면 씨앗 재현이 되지 않는다: 웜스타트는 체크포인트를 **먼저** 보고, 그것이 남아 있으면\n * 백지로 시작한 트윈에 옛 상태가 되살아난다(저널은 비었는데 재고가 있는 트윈이 된다).\n * 시간여행이 딛는 사슬 캐시도 같은 이유로 무효다 — 지워진 리비전을 가리키게 된다.\n *\n * 공통 캐시 서비스에는 삭제가 없다(get/set/clearStale 뿐). 그래서 **「없음」을 적는다** — 값을\n * 지어내는 것이 아니라 「체크포인트가 없다」는 사실을 적는 것이고, 읽는 쪽은 이미 `cached?.state` 로\n * 그것을 가려낸다. 공통 모듈에 삭제를 새로 뚫는 것은 이 한 자리를 위해 하기에는 큰 변경이다.\n */\n await cacheService\n .setInCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId }, { revision: 0, state: null }, this.SNAPSHOT_TTL_S)\n .catch(err => twinWarn(`[twin-engine] \"${instanceId}\" checkpoint not invalidated — a seed run may inherit old state:`, err?.message ?? err))\n await cacheService\n .setInCache(this.CHAIN_INDEX_CACHE_ID, { domainId, instanceId }, { revisions: [] }, this.SNAPSHOT_TTL_S)\n .catch(err => twinWarn(`[twin-engine] \"${instanceId}\" chain index not cleared — time travel may point at deleted revisions:`, err?.message ?? err))\n }\n\n /** 삭제 — 정지 + 레지스트리 삭제 + 저널 purge(domain 스코프). */\n static async remove(domainId: string, instanceId: string): Promise<void> {\n await this.stop(domainId, instanceId)\n this.forgetInstance(domainId, instanceId)\n await getRepository(TwinEvent).delete({ domain: { id: domainId } as any, instanceId })\n await getRepository(TwinInstance).delete({ domain: { id: domainId } as any, instanceId })\n }\n\n /**\n * 이 트윈에 대해 **메모리에 남은 것을 전부 잊는다** — 지움의 한 자리.\n *\n * 캐시가 라이프사이클과 어긋나 있었다: 저널·등록부는 지우면서 인스턴스별 캐시는 남겨, 삭제된 트윈의\n * 항목이 **서버 재기동까지 살아 있었다.** 항목 하나가 하루치 KPI 그룹을 물고 있으므로 잊지 않으면\n * 지운 트윈이 계속 메모리를 차지한다. TTL 은 값이 낡는 것을 막을 뿐 **없어진 주인을 지우지 않는다.**\n *\n * 잊을 것을 여기 모아 두는 이유: 캐시를 새로 만드는 사람이 지우는 자리를 찾아 헤매지 않게 한다.\n * 새 인스턴스별 캐시를 만들면 **이 함수에 한 줄을 더한다** — 그러지 않으면 같은 누수가 다시 생긴다.\n */\n private static forgetInstance(domainId: string, instanceId: string): void {\n const key = runtimeKey(domainId, instanceId)\n delete this.recovered[key]\n this.measuredCache.delete(key)\n delete this.structureRevCache[key]\n }\n\n /** 관리 목록 — domain 의 등록 인스턴스 전체(라이브 여부·최신 저널 revision·노드/무버 수 포함). */\n static async list(domainId: string): Promise<any[]> {\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n /*\n * **현장 이름을 함께 낸다** — 목록이 `spaceId` 만 내보내서 화면이 이름을 따로 조회하고 있었다.\n * 그 조회(`twinSpaces`)는 공간마다 카운트 쿼리를 도는 N+1 이라 느리고, 그 사이 화면은 **id 를\n * 이름처럼** 보여 준다(2026-08-13 관측: 「현장 crew-probe-site」). 한 번에 읽어 map 으로 붙이면\n * 왕복도 줄고 그 깜빡임도 사라진다. 이름이 없으면 **비운다** — id 를 이름으로 베끼지 않는다.\n */\n const spaceNameOf = new Map(\n (await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })).map(s => [s.spaceId, s.name])\n )\n /*\n * **최신 리비전은 트윈마다 인덱스 끝에서 한 행씩 읽는다.**\n *\n * ── 그룹 질의로 바꾸었다가 되돌렸다 (2026-08-22 실측) ─────────────────────\n * 예전 주석은 이랬다: 「트윈마다 `findOne(order revision DESC)` 을 돌고 있었다 — 13개면 질의\n * 13번이고, 트윈이 늘면 그대로 자란다. 한 번의 그룹 질의로 바꾼다.」\n *\n * **질의 개수를 줄였지만 일의 양을 늘렸다.**\n *\n * findOne × 13 `(domain, instance, revision)` 인덱스 **끝에서 한 행** — 각각 O(1)\n * GROUP BY 한 번 그 도메인의 저널을 **전수 집계** — O(전체)\n *\n * 저널이 작을 때는 이득이었고, 커지면서 손해가 됐다. 실측(저널 1,134만 행): 이 그룹 질의가\n * **44.7초**였다. 그리고 sqlite 드라이버는 연결이 하나이므로 그동안 앱의 모든 질의가 그 뒤에 섰다 —\n * 같은 순간 29행짜리 `twin_instances` 조회도 44.7초로 찍혔다. 이 목록은 「트윈 관리·현장 구성·\n * 엔티티 패널이 모두 읽는 자리」여서, 화면을 열 때마다 서버 전체가 그만큼 멈췄다.\n *\n * 트윈 수는 수십이고 저널은 천만이다. **작은 것을 여러 번 읽는 편이 큰 것을 한 번 훑는 것보다 싸다.**\n * 질의 개수가 트윈 수에 비례해 자라는 것은 사실이지만, 각 질의가 인덱스 끝 한 행이므로 그 성장은\n * 감당된다 — 그리고 병렬로 묻는다.\n *\n * **다시 그룹 질의로 바꾸지 말 것.** 바꾸려면 이 숫자를 먼저 다시 재라.\n */\n const tipOfInstance = new Map<string, number>()\n await Promise.all(\n rows.map(async r => {\n try {\n /*\n * **집계 하나로 묻는다 — 행을 실어 오지 않는다.**\n *\n * `findOne(order revision DESC)` 로 두었더니 두 가지가 틀렸다. ① 관계를 가진 엔티티의 정렬\n * 조회는 TypeORM 이 `DISTINCT` 로 감싸므로 `select` 로 컬럼을 좁히면 `distinctAlias.\n * TwinEvent_id` 가 없다고 터진다(실측: 모든 트윈에서 SQLITE_ERROR). ② `select` 를 떼면\n * **`payload` 까지 실어 온다** — 이 값 하나를 알려고 큰 TEXT 를 읽는다.\n *\n * 그래서 단일 집계를 쓴다. `(domain, instance, revision)` 인덱스에서 instance 가 정해지면\n * `MAX` 는 그 구간의 끝이므로 sqlite 가 끝을 집는다(실측 0.007초 · 도메인 전체 GROUP BY 는\n * 14.5초). 이 파일의 다른 자리도 같은 규율이다(§`timeRange` · 기동 시 최종 리비전).\n */\n const row = await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select('MAX(e.revision)', 'revision')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId: r.instanceId })\n .getRawOne<{ revision: unknown }>()\n /* 행이 없으면 `null` 이다 — 그때는 비워 둔다(0 은 \"아무 일도 없었다\" 는 주장이다). */\n if (row?.revision != null) tipOfInstance.set(String(r.instanceId), Number(row.revision) || 0)\n } catch (err: any) {\n /* 한 트윈의 조회가 실패해도 **0 으로 메우지 않는다** — 리비전 0 은 \"아직 아무 일도 없었다\" 는\n 사실 주장이다. 비워 두면 아래에서 undefined 로 남고, 화면은 그것을 \"모름\" 으로 그린다.\n 그리고 그 트윈만 모름이 된다 — 예전에는 집계 하나가 실패하면 전부 모름이었다. */\n twinError(`[twin-engine] latest revision lookup failed \"${r.instanceId}\"`, err?.message ?? err)\n }\n })\n )\n\n const out: any[] = []\n for (const r of rows) {\n const model = (r.model as TwinModelDef) ?? { locations: [], equipment: [] }\n out.push({\n instanceId: r.instanceId,\n /*\n * **이름을 함께 낸다.** 업무키(`instanceId`)만 내보내고 있어서 목록이 `crew-two` 만 보였다 —\n * 업무키를 나눠 둔 설계에서는 이름을 같이 실어야 그 나눔이 값을 한다.\n * 없으면 `undefined` 다(id 를 베끼지 않는다 — 화면이 이름 없음을 알아볼 수 있어야 한다).\n */\n name: r.name ?? undefined,\n description: r.description ?? undefined,\n kind: r.kind,\n status: r.status,\n spaceId: r.spaceId, // co-location: 같은 spaceId 인스턴스들이 한 현장 공유 — 현장뷰 집약 키(G7)\n /* 사람이 읽는 현장 이름 — 없으면 `undefined`(화면이 \"이름 없음\" 을 알아볼 수 있어야 한다). */\n spaceName: (r.spaceId ? spaceNameOf.get(r.spaceId) : undefined) || undefined,\n restartPolicy: r.restartPolicy, // 재기동 정책(ADR-0029 §2) — resync/resume/reset. 선언이므로 비어 있을 수 없다.\n purpose: r.purpose, // 운영 vs 벤치 사본(1급 구별 — 이름 접두사 아님). 저장 시 각인되므로 비지 않는다.\n copyOf: r.copyOf ?? undefined,\n running: !!this.instances[runtimeKey(domainId, r.instanceId)],\n /*\n * **계측이 들어오고 있나** — 「도는 중」과 다른 사실이다.\n *\n * 미러 트윈은 피드가 떨어져도 커널이 돌기만 하면 「도는 중」이었다. 그래서 아무것도 받지 않는\n * 트윈과 흐르는 트윈이 화면에서 똑같이 보였다(재기동 뒤 실제로 그랬다). 시뮬·정지 트윈에는\n * 「해당 없음」이다 — 없어야 하는 것을 끊겼다고 부르지 않는다.\n */\n /* 스스로 멈춘 이유 — 있으면 낸다. 재기동 뒤에는 없다(그때는 「모른다」가 사실이다). */\n stopNote: this.stopNotes.get(runtimeKey(domainId, r.instanceId)) || undefined,\n liveFeed: liveFeedStateOf({\n restartPolicy: r.restartPolicy,\n running: !!this.instances[runtimeKey(domainId, r.instanceId)],\n instanceId: r.instanceId\n }),\n revision: tipOfInstance.get(r.instanceId) ?? 0,\n /*\n * **리더를 거쳐 센다** — 보드 키를 직접 읽으면 옛 세대 모델이 0 으로 보인다.\n *\n * 커널은 자리·설비 배열의 **옛 세대 키까지 흡수해** 읽어 주는데, 이 목록은 새 이름만 직접\n * 세고 있었다. 그래서 옛 모델 12개가 화면에 **자리 0 · 설비 0**\n * 으로 떴다 — 오류 없이, 그냥 빈 공장처럼. 세는 규칙이 두 벌이면 이런 식으로 어긋난다.\n */\n locationCount: readBoardLocations(model).length,\n equipmentCount: readBoardEquipment(model).length\n })\n }\n return out\n }\n\n /** 운영 공간 목록(벤치 소스 선택기) — 이름·규모 포함, 벤치 사본 제외. */\n static async listSpaces(domainId: string): Promise<{ spaceId: string; name: string; instances: number; locations: number; equipment: number }[]> {\n const nameOf = new Map((await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })).map(s => [s.spaceId, s.name]))\n const insts = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n const agg = new Map<string, { spaceId: string; name: string; instances: number; locations: number; equipment: number }>()\n for (const r of insts) {\n /* 벤치 제외는 **선언으로만** 판단한다. 예전에는 spaceId 이름(`bench-`·`loadtest*`)으로도 추측했는데,\n 그러면 그렇게 이름 지은 진짜 운영 공간이 목록에서 조용히 사라진다. purpose 가 정본이다. */\n if (!r.spaceId || r.purpose === 'bench') continue\n const model: any = r.model ?? {}\n const a = agg.get(r.spaceId) ?? { spaceId: r.spaceId, name: nameOf.get(r.spaceId) ?? r.spaceId, instances: 0, locations: 0, equipment: 0 }\n a.instances++\n /* 목록과 **같은 규칙**으로 센다 — 여기만 직접 세면 공간 요약과 인스턴스 목록이 다른 수를 말한다. */\n a.locations += readBoardLocations(model).length\n a.equipment += readBoardEquipment(model).length\n agg.set(r.spaceId, a)\n }\n return [...agg.values()]\n }\n\n /** 인스턴스 목적 표식(운영/벤치) 설정 — 벤치 사본을 1급 속성으로 구별(이름 접두사 아님). */\n static async setPurpose(domainId: string, instanceId: string, purpose: 'operational' | 'bench', copyOf?: string): Promise<void> {\n await getRepository(TwinInstance).update({ domain: { id: domainId } as any, instanceId }, { purpose, copyOf: copyOf ?? null } as any)\n }\n\n /**\n * 공간 구조 판독 — 완전복제(벤치 사본)의 소스. 저장물이 model(위상)·TwinSpace.content(치수·geo·표현)·TwinArea(영역)로\n * 분산돼 있으므로 셋을 모아 돌려준다. 호출측이 ReferenceMaster 로 재구성 → 재식별 → ingestMaster.\n */\n static async spaceStructure(domainId: string, spaceId: string): Promise<{\n name?: string\n /** 설계 좌표계 범위(미터)와 지오레퍼런스 — 사본이 원본과 같은 자리에 서려면 함께 가야 한다. */\n frame: { extentX?: number; extentY?: number; geo?: any; primaryRepresentationId?: string }\n areas: any[]\n instances: { instanceId: string; kind?: string; model: any }[]\n } | null> {\n const sp = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n const areas = sp\n ? (await getRepository(TwinArea).find({ where: { domain: { id: domainId } as any, space: { id: sp.id } as any } })).map(a => ({ id: a.areaId, type: a.type, name: a.name, parentId: a.parentId, layout: a.layout }))\n : []\n const insts = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n if (!insts.length) return null\n return {\n name: sp?.name,\n frame: { extentX: sp?.extentX, extentY: sp?.extentY, geo: sp?.geo, primaryRepresentationId: sp?.primaryRepresentationId },\n areas,\n instances: insts.map(i => ({ instanceId: i.instanceId, kind: i.kind, model: i.model }))\n }\n }\n\n /** 공간(+표현·영역) 삭제 — 벤치 정리 등. 호출측이 바인딩 인스턴스를 먼저 제거하는 전제(가드 없음). deleteTwinSpace 리졸버와 동형. */\n static async deleteSpace(domainId: string, spaceId: string): Promise<void> {\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (space) {\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n for (const rep of reps) await getRepository(TwinSpaceArea).delete({ domain: { id: domainId } as any, representation: { id: rep.id } as any })\n await getRepository(TwinSpaceRepresentation).delete({ domain: { id: domainId } as any, space: { id: space.id } as any })\n await getRepository(TwinArea).delete({ domain: { id: domainId } as any, space: { id: space.id } as any })\n }\n await getRepository(TwinSpace).delete({ domain: { id: domainId } as any, spaceId })\n }\n\n /**\n * Face2 마스터 인제스트(ADR-0018) — 레퍼런스 시스템(실 또는 가상)의 마스터를 읽어 트윈을 생성.\n * 엔티티를 손배선/발명하지 않고 마스터에서 반영: 공간(Space) upsert + 인스턴스 provision(미기동).\n * 노드타입은 커널 카탈로그로 검증(warning). start 는 호출측(bootstrap/mutation)이 결정.\n *\n * `into.spaceId` — **이 현장에 더한다.** 한 현실을 여러 렌즈(WMS·MES·YMS)가 비추므로 새 트윈이\n * 기존 공간으로 들어갈 수 있다. 아래 병합은 원래 그 경우를 위해 있었는데(N:1) 만드는 흐름에서\n * 공간을 고를 방법이 없었다 — 마스터가 파생한 id 만 쓰였다. 판정은 `resolveIngestSpace`(순수).\n */\n static async ingestMaster(\n domainId: string,\n master: ReferenceMaster,\n /** 만들어지는 트윈의 재기동 정책 — 원본이 정하는 것이 아니라 **만드는 쪽의 선언**이다(ADR-0029 §2). */\n restartPolicy: RestartPolicy,\n into?: { spaceId?: string },\n /** 누가 인제스트했나 — 사람이 없는 경로(부팅)는 주지 않는다(감사 기록을 지어내지 않는다). */\n actor?: { id: string }\n ): Promise<{ instanceId: string; spaceId: string; warnings: IngestWarning[] }> {\n /*\n * **거절할 것이면 아무것도 쓰기 전에 거절한다.**\n *\n * 가동 중 재프로비저닝은 `provision` 이 막는다. 그런데 그 호출은 이 함수의 **맨 끝**이라,\n * 그때까지 공간·표현·구역(TwinArea)은 이미 저장된 뒤였다. 사용자에게는 \"인제스트 실패\" 로\n * 보이는데 실제로는 절반이 적용된 상태 — 실패라고 말하면서 데이터를 바꾸는 것이 가장 나쁘다.\n *\n * 그래서 판정을 앞으로 옮긴다. 아래 `provision` 의 같은 판정은 그대로 둔다 — 이건 편의를 위한\n * 앞선 거절이고, 저기가 진짜 방벽이다(다른 경로가 생겨도 지켜져야 한다).\n *\n * **미러는 여기서 거절하지 않는다.** 미러가 비추는 현실은 안 멈추므로 동작 중에 전환한다\n * (아래 `adoptStructure`). 거절은 시뮬레이션에만 남는다 — 조건이 바뀐 실험은 다른 실험이다.\n */\n const running = this.instances[runtimeKey(domainId, master.source)]\n if (running && running.mode !== 'live') this.assertNotRunning(domainId, master.source)\n\n const { model, spaceContent, warnings } = masterToTwin(master, DOMAIN_CATALOG)\n /*\n * ── 현장 선언을 다시 얹는다 (2026-08-18) ──────────────────────────────────\n *\n * 여기가 「원천에서 다시 그리는」 자리다. 요금 단가·계약 정보처럼 **현장이 정한 수**는 원천이 모르므로\n * 다시 그리면 그대로 사라진다 — 금액이 사라지고, 사용자는 자기가 넣은 값이 어디로 갔는지 알 수 없다.\n * 그래서 겹으로 보관한 선언을 매번 다시 얹는다(`engine/local-declarations`).\n *\n * 대상이 사라졌으면(구조가 바뀌었다) 그 사실을 경고로 낸다 — 갈 곳 없는 선언을 조용히 버리지 않는다.\n */\n const prior = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: master.source } })\n /*\n * 겹이 **둘**이다 — 현장(공간)의 것과 이 트윈의 것. 순서가 규율이다: 현장 먼저, 트윈이 나중.\n * 요금처럼 현장이 정한 수는 그 현장의 트윈 전부가 같이 읽어야 하고, 한 트윈만 다르게 두는 실험은\n * 좁은 겹이 이겨야 한다(넓은 값을 고치면 나머지 트윈이 함께 흔들린다).\n */\n const priorSpaceId = prior?.spaceId ?? (model as any)?.spaceId\n const spaceRow = priorSpaceId\n ? await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId: priorSpaceId } })\n : null\n if (prior?.localDeclarations || spaceRow?.localDeclarations) {\n const layered = applyDeclarationLayers(model as any, spaceRow?.localDeclarations as any, prior?.localDeclarations as any)\n Object.assign(model as any, layered.model)\n /*\n * 겹을 **다시 저장한다** — 여기서 얹은 것은 원천에서 새로 그린 모델이므로, 그때 우리가 덮은 값이\n * 곧 지금의 원천 값이다(`replaced`). 저장하지 않으면 그 기억이 낡아, 철회가 옛 원천 값으로\n * 되돌린다 — 원천이 그동안 값을 고쳤어도 알 수 없다.\n */\n if (prior) {\n prior.localDeclarations = layered.instanceLayerApplied as any\n await getRepository(TwinInstance).save(prior)\n }\n if (spaceRow) {\n spaceRow.localDeclarations = layered.spaceLayerApplied as any\n await getRepository(TwinSpace).save(spaceRow)\n }\n /*\n * 갈 곳 없는 선언은 경고로 낸다 — 다만 **현장 겹의 것은 뺀다**: 한 현장에는 여러 종류의 트윈이\n * 살고(창고·야드·에너지), 요금 자리가 없는 트윈에 요금이 얹히지 않는 것은 정상이다.\n */\n for (const t of layered.missingTargets.filter(x => x.scope === 'instance')) {\n warnings.push(unresolvedReference('localDeclaration.target', `${t.target}:${t.id}`))\n }\n }\n const repo = getRepository(TwinSpace)\n /* 합칠 공간을 골랐으면 **있는지 먼저 확인한다** — 없는 곳에 조용히 새 공간을 만들면 사용자는\n 합쳤다고 믿고 화면은 따로 논다. 판정 함수가 그 경우 거절한다. */\n const wanted = (into?.spaceId ?? '').trim()\n const wantedExists = wanted\n ? (await repo.count({ where: { domain: { id: domainId }, spaceId: wanted } })) > 0\n : false\n const choice = resolveIngestSpace(model.spaceId, wanted, wantedExists)\n const spaceId: string = choice.spaceId\n model.spaceId = spaceId // 보드(커널 소비)도 같은 공간을 가리켜야 한다\n const existing = await repo.findOne({ where: { domain: { id: domainId }, spaceId } })\n if (choice.joined) {\n /* 같은 id 의 구역·랜드마크는 합집합으로 접힌다 — 구분할 수 없는 것을 고르지 않고 무엇이\n 합쳐졌는지 말한다(정당한 경우가 많으므로 막지 않는다). */\n }\n /*\n * 공유 공간(여러 트윈이 한 spaceId, N:1) — **먼저 쓴 값이 이긴다.**\n *\n * 마지막 인제스트가 통째로 덮어써 표현·구역이 유실되던 문제 보정. 설계 좌표계 범위와\n * 지오레퍼런스는 공간의 성질이라 트윈마다 다를 수 없다 — 두 번째 트윈이 들어오면서 바꾸면\n * 먼저 놓인 구역들이 통째로 어긋난다. 그래서 이미 있으면 그대로 둔다.\n */\n const cur: any = spaceContent\n const timezone = existing?.timezone || master.space.timezone\n const savedSpace = await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n spaceId,\n name: existing?.name || master.siteName,\n ...(timezone ? { timezone } : {}),\n extentX: existing?.extentX ?? cur.width,\n extentY: existing?.extentY ?? cur.depth,\n geo: existing?.geo ?? cur.geo,\n /*\n * 대표 표현 포인터는 **표현을 저장한 뒤** 실제 행 id 로 채운다(아래). 여기서 마스터의 논리\n * id(`r-map` 따위)를 넣으면 표현 행은 생성 uuid 를 받으므로 포인터가 **처음부터 허공을\n * 가리킨다** — 실제로 13개 현장이 그 상태였고 정합성 점검이 잡았다(2026-08-13). 화면은\n * 행의 `isPrimary` 로 ★를 그려서 증상이 보이지 않았다(사실이 두 벌이면 이렇게 조용하다).\n */\n primaryRepresentationId: existing?.primaryRepresentationId ?? null\n })\n )\n /*\n * 표현을 twin_space_representations 테이블에 저장한다 — 뷰(twin-map-page 등)는 content 가 아니라 테이블 표현을 소싱하므로,\n * 저장하지 않으면 인제스트 사이트에 \"대표 표현\" 이 없어 지도로 시작하지 못한다. rep.areas 가 있으면 TwinSpaceArea 도 함께 저장.\n * 최초 인제스트만(기존 표현 있으면 사용자 편집 보존).\n */\n const repRepo = getRepository(TwinSpaceRepresentation)\n const areaRepo = getRepository(TwinSpaceArea)\n if ((await repRepo.count({ where: { space: { id: savedSpace.id } } })) === 0) {\n const reps: any[] = (spaceContent as any).representations ?? []\n for (let i = 0; i < reps.length; i++) {\n const rep = reps[i]\n const config =\n rep.type === 'map' ? { center: rep.center, zoom: rep.zoom }\n : rep.type === 'board' ? { boardId: rep.boardId }\n : rep.type === 'image' ? { imageUrl: rep.imageUrl, width: rep.width, height: rep.height }\n : {}\n const savedRep = await repRepo.save(repRepo.create({ domain: { id: domainId } as any, space: { id: savedSpace.id } as any, type: rep.type, name: rep.name, seq: i, isPrimary: !!rep.primary || rep.id === (spaceContent as any).primaryId, config }))\n for (const area of (rep.areas ?? []) as any[]) {\n await areaRepo.save(areaRepo.create({ domain: { id: domainId } as any, representation: { id: savedRep.id } as any, name: area.name, type: area.type, geometry: area.geometry, drillTo: area.drillTo ?? null, binding: area.binding ?? null, style: area.style ?? null }))\n }\n }\n /*\n * 대표를 **저장된 행 id** 로 가리킨다 — 마스터의 논리 id 는 저장 키가 아니다. 고른 순서:\n * ① 마스터가 primary 로 표시한 표현 ② 없으면 첫 표현 ③ 표현이 없으면 비운다(지어내지 않는다).\n */\n const saved = await repRepo.find({ where: { domain: { id: domainId } as any, space: { id: savedSpace.id } as any }, order: { seq: 'ASC' } })\n const primary = saved.find(r => r.isPrimary) ?? saved[0]\n if (primary && savedSpace.primaryRepresentationId !== primary.id) {\n await repo.save(repo.create({ ...savedSpace, primaryRepresentationId: primary.id }))\n /* 하나만 대표다 — 행 플래그도 그 하나로 맞춘다(둘이 켜져 있으면 화면이 ★를 두 번 그린다). */\n for (const r of saved) if (!!r.isPrimary !== (r.id === primary.id)) await repRepo.save(repRepo.create({ ...r, isPrimary: r.id === primary.id }))\n }\n }\n /*\n * area 단일화(space #2, P1) — 논리 구역을 TwinArea(정규·표현무관·공유)에 dual-write(upsert by areaId).\n * P3: content.areas 저장 폐기 → TwinArea 가 유일 권위. 소스 = masterToTwin 산출 spaceContent.areas(cur).\n * (원천 diff 제거[master 에서 빠진 area 삭제]는 사용자저작 area 보호 위해 per-area provenance 필요 → 후속.)\n */\n const twinAreaRepo = getRepository(TwinArea)\n for (const a of ((spaceContent as any).areas ?? []) as any[]) {\n if (!a?.id) continue\n const existingArea = await twinAreaRepo.findOne({ where: { domain: { id: domainId }, space: { id: savedSpace.id }, areaId: a.id } })\n await twinAreaRepo.save(\n twinAreaRepo.create({\n ...(existingArea ?? {}),\n domain: { id: domainId } as any,\n space: { id: savedSpace.id } as any,\n areaId: a.id,\n name: a.name ?? a.id,\n type: a.type,\n parentId: a.parentId ?? null,\n layout: a.x != null || a.w != null ? { x: a.x, y: a.y, w: a.w, h: a.h } : null\n })\n )\n }\n\n if (running) {\n /* 실행 중인 미러 — 멈추지 않고 전환한다. 무엇이 사라졌는지는 **경고로 말한다**\n (멈췄다 세우는 마디가 없으므로, 말하지 않으면 자리 하나가 조용히 없어진다). */\n const shift = await this.adoptStructure(domainId, master.source, model, undefined, master.origin)\n warnings.push(structureAdopted(shift.rev, shift))\n } else {\n /* 사이트 이름이 곧 트윈의 이름이다 — 마스터가 이미 말했으므로 지어내지 않고 그대로 싣는다. */\n await this.provision(domainId, master.source, master.system, model, restartPolicy, undefined, master.origin, {\n name: master.siteName,\n description: (master as any).description,\n actor\n })\n }\n\n /*\n * 구조 투영 — model(커널 입력 문서)를 **표준 엔티티 행**으로 푼다(ADR-0032).\n *\n * 인제스트가 유일한 쓰기 경로다. 여기서 실패해도 인제스트 자체는 성공으로 둔다 —\n * 행은 **원본에서 언제든 다시 그릴 수 있는 캐시**이고, 트윈 자체는 model 로 이미 동작한다.\n * 다만 **조용히 넘기지 않는다**: 못 이은 참조는 인제스트 경고로 올라간다.\n */\n try {\n const projected = await projectStructure(domainId, master.source, model, master.source)\n for (const ref of projected.unresolvedHome) warnings.push(unresolvedReference('equipment.homeLocation', ref))\n for (const ref of projected.unresolvedArea) warnings.push(unresolvedReference('location.area', ref))\n /*\n * 발전 형상은 **시각**을 읽는다 — 시간대를 모르면 UTC 로 읽히고, 현장 정오가 아닌 시각에 피크가 선다.\n * 시간대를 지어내지 않고 그 조합을 말한다(공간에 선언하면 사라진다).\n */\n if ((model as any)?.utcOffsetMinutes === undefined) {\n for (const e of ((model as any)?.equipment ?? []) as any[]) {\n const hasProfile = ((e?.properties ?? []) as any[]).some(p => String(p?.id) === EMS_PROPERTY.genDailyProfile && String(p?.value ?? '').trim())\n if (hasProfile) warnings.push(generationWithoutTimeZone(String((model as any)?.spaceId ?? ''), String(e.id)))\n }\n }\n } catch (err: any) {\n twinError(`[twin-engine] structure projection failed for \"${master.source}\":`, err?.message)\n warnings.push(projectionFailed(err?.message ?? 'unknown'))\n }\n\n if (warnings.length) twinWarn(`[twin-engine] ingest \"${master.source}\" warnings: ${describeWarnings(warnings)}`)\n return { instanceId: master.source, spaceId, warnings }\n }\n\n /** 단건 상세 — 프로비저닝 에디터가 편집할 model(구조+layout) 포함. */\n static async detail(domainId: string, instanceId: string): Promise<any | null> {\n const r = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!r) return null\n return {\n instanceId: r.instanceId,\n kind: r.kind,\n status: r.status,\n running: !!this.instances[runtimeKey(domainId, r.instanceId)],\n restartPolicy: r.restartPolicy, // 현실 선언 — what-if 적용 가드용(mirror=예측 전용, 자극 주입 불가)\n model: r.model\n }\n }\n\n /**\n * 라이브 바인딩 브리지(P3, ADR-0018) — 트윈 엔티티 상태를 `data(tag=엔티티id)` 채널로 publish.\n * 보드 컴포넌트가 tag 로 구독(board-ui provider)해 `component.data` 로 라이브 갱신. delta 시에만(희소).\n * tag=엔티티 id(데모=단일 인스턴스). 멀티 인스턴스/보드 재사용 시 tag 네임스페이스는 후속.\n */\n /** 브로드캐스팅 실패 로그 조절 — 창마다 한 줄(막힌 구독자는 초당 수십 번 실패한다). */\n private static publishDrops = new Map<string, { count: number; lastLogMs: number }>()\n private static readonly PUBLISH_DROP_LOG_MS = 10_000\n\n /**\n * 한 번의 브로드캐스팅 — **구독자 하나가 호스트를 죽이지 못하게.**\n *\n * ── 무엇이 죽였나 (2026-08-14) ─────────────────────────────────────────────\n * 밀린 push 가 1024를 넘으면 pubsub 이 오류를 낸다(`RepeaterOverflowError`). 그 브로드캐스팅은 타이머 콜백\n * 안에서 일어나므로 예외가 잡히는 곳 없이 올라가 **프로세스가 끝났다** — 트윈 14개가 도는 호스트가\n * 소비를 멈춘 구독자 하나 때문에 통째로.\n *\n * 못 보낸 것은 **사실로 남긴다**(횟수를 세고 창마다 한 줄 남긴다). 삼키면 「보냈는데 화면이 낡았다」가\n * 되고, 그건 가장 찾기 어려운 부류다.\n */\n private static publishGuarded(channel: 'data' | 'twin-state', payload: any, what: string): boolean {\n try {\n pubsub.publish(channel as any, payload)\n return true\n } catch (err: any) {\n const d = this.publishDrops.get(what) ?? { count: 0, lastLogMs: 0 }\n d.count++\n const now = Date.now()\n if (now - d.lastLogMs >= this.PUBLISH_DROP_LOG_MS) {\n d.lastLogMs = now\n twinWarn(`[twin-engine] broadcast dropped on \"${what}\" (${d.count} so far) — ${err?.message ?? err}`)\n }\n this.publishDrops.set(what, d)\n return false\n }\n }\n\n static publishEntityData(inst: InstanceRuntime): void {\n const domain = inst.domain\n if (!domain) return\n /* 상태 출처 스왑 — sim: 커널 runtime, live: projector 미러(+OEE 계산 층 보강). 계약·payload 동일, 드라이버만 다름. */\n const load = inst.load ?? (inst.load = newLoadMeter())\n\n /* ① 상태 투영 — 상태 크기에 비례한다(대규모에서 가장 무거운 축). */\n const tSnap = performance.now()\n const st: any =\n inst.mode === 'live'\n ? inst.oee\n ? withLiveOee(inst.projector?.snapshot?.(), inst.oee) // 관측 커널 + 계산(OEE) → equipment payload 에 oee 포함(sim 동형)\n : inst.projector?.snapshot?.()\n : inst.runtime?.resync?.()?.state\n recordPhase(load, 'snapshot', performance.now() - tSnap)\n if (!st) return\n /*\n * 변화한 엔티티만 발행 — 이전엔 delta 마다 전 엔티티(노드+무버+오더)를 값 변화와 무관하게 전량 재발행해\n * 같은 데이터를 매초 반복 push 하고 있었다(오용). 최신-상태 채널이므로 무변화 재브로드캐스팅은 무의미하다.\n * 엔티티별 시그니처를 비교해 바뀐 것만 push.\n */\n const sigs = inst.entitySigs ?? (inst.entitySigs = new Map())\n const seen = new Set<string>()\n /* payload 매핑은 순수 함수(buildEntityDeltas)로 분리 — 여기선 시그니처 dedup + 발행만.\n * 변화한 엔티티만 발행(최신-상태 채널이라 무변화 재브로드캐스팅 무의미). */\n /* ② payload 만들기 — 엔티티 수에 비례. ③ 시그니처 비교 + 발행 — 바뀐 것 수에 비례. */\n const tDelta = performance.now()\n /*\n * ── 물품은 **건드린 것만** 만든다 (2026-08-21 실측) ──────────────────────\n * 만드는 payload 의 대부분이 물품이다(엔티티 3,611 중 2,400). 바뀐 것이 하나여도 전부 만들어\n * 문자열로 바꾼 뒤 「같다」를 확인하고 버렸다.\n *\n * 범위는 이 창에 들어온 사건에서 모았다(`touchedItemKeys`). **말할 수 없는 사건이 하나라도 있으면\n * 범위는 없고 전부 만든다** — 낯선 어휘가 오면 조용히 빠뜨리는 대신 비싸게 안전한 쪽으로 떨어진다.\n *\n * 그리고 주기마다 한 번은 **무조건 전부** 만든다(`FULL_BROADCAST_EVERY`). 커널이 사건 없이 물품을\n * 바꾸는 자리가 생기면 그 값이 화면에 남을 수 있는데, 그 창을 몇 초로 묶는 그물이다. **보장이 아니라\n * 그물이다** — 사건 없이 바뀌는 자리를 찾으면 그것을 고치는 것이 답이고 이 그물은 시간을 벌 뿐이다.\n */\n const full = inst.fullBroadcastDue === true || !inst.dirtyItems\n const deltas = buildEntityDeltas(st, inst.id, full ? undefined : { items: inst.dirtyItems! })\n this.broadcastPasses++\n if (full) this.broadcastFullPasses++\n /* 이번 창의 범위는 여기서 닫는다 — 다음 창은 다시 모은다. */\n inst.dirtyItems = new Set()\n inst.fullBroadcastDue = false\n recordPhase(load, 'deltas', performance.now() - tDelta)\n\n const tPub = performance.now()\n for (const { tag, data } of deltas) {\n seen.add(tag)\n const sig = JSON.stringify(data)\n if (sigs.get(tag) === sig) continue // 무변화 → 발행 생략\n sigs.set(tag, sig)\n /*\n * **못 보냈으면 보낸 것으로 적지 않는다.** 시그니처를 남겨 두면 다음 주기에 「무변화」로 건너뛰고,\n * 그 태그는 영원히 낡은 값을 보여 준다(오류 없이). 되돌려 두면 다음 주기가 다시 시도한다.\n */\n if (!this.publishGuarded('data', { data: { domain, tag, data } }, `data:${inst.id}`)) sigs.delete(tag)\n }\n recordPhase(load, 'publish', performance.now() - tPub)\n /*\n * 사라진 엔티티의 시그니처 정리(맵 무한 성장 방지) — **전부 만든 창에서만.**\n * 범위를 좁힌 창의 `seen` 에는 만들지 않은 엔티티가 없으므로, 그때 정리하면 살아 있는 태그의\n * 시그니처를 지운다. 낡은 값이 나가는 것은 아니지만(다음 창에 다시 만들어 보낸다) 같은 값을\n * 되풀어 보내게 되어, 줄이려던 것을 되돌린다.\n */\n if (full && sigs.size > seen.size) for (const tag of sigs.keys()) if (!seen.has(tag)) sigs.delete(tag)\n }\n\n /*\n * 단건 저장(`persist`)은 **없앴다** (2026-08-20, §7.1).\n *\n * 시뮬이 델타마다 이것을 불러 행 하나씩 썼고, 그것이 규모에서 호스트를 먹었다. 남겨 두면 다음 사람이\n * 다시 부를 자리가 되므로 지운다 — 쓰는 문은 `flushJournal` 하나다(`persistBatch`·`persistCarried`).\n */\n\n /**\n * 재부팅 복구 / 시간여행 — DB 저널을 replay 해 상태 재구성.\n * model 는 레지스트리(TwinInstance)에서, 이벤트는 TwinEvent(revision ASC)에서.\n * 커서 두 축(runtime-state-model §4): **시각(untilTime, 사용자 모국어·공간 공통축)** 우선, 없으면 리비전(untilRevision, 렌즈 내부).\n * - untilTime 주면 `eventTime ≤ T` 인 이벤트만(그 시점 watermark) — 공동배치 여러 트윈을 하나의 시각 T로 통일 해소.\n * - 둘 다 없으면 최신(라이브 인메모리 진실).\n * 이벤트는 항상 revision ASC(인과 순서)로 적용 — 시각 필터는 컷오프 집합만 정한다.\n */\n static async recover(domainId: string, instanceId: string, untilRevision?: number, untilTime?: string): Promise<any> {\n // 라이브 최신(시간여행 아님) + 인메모리 인스턴스 → 라이브 커널 스냅샷을 직접 사용.\n // replay(StateProjector)는 attentions·ack 등 라이브 전용 파생 상태를 담지 못하므로, 최신은 커널 진실을 쓴다.\n if (untilRevision == null && untilTime == null) {\n const live = this.instances[runtimeKey(domainId, instanceId)]\n if (live?.kernel?.getSnapshot) return live.kernel.getSnapshot()\n // live 모드는 kernel 이 없고 projector 미러 → 인메모리 최신 스냅샷(projector+OEE+attentions) 직접 사용.\n // (저널이 있어도 최신은 인메모리가 진실 — replay 는 시간여행/복구 전용.)\n if (live?.mode === 'live' && live.projector) return this.snapshot(domainId, instanceId)\n }\n /*\n * **끝에 있는 스냅샷이면 접지 않는다.**\n *\n * 멈춘 트윈을 조회할 때마다 저널을 전량 접고 있었다 — 트윈을 하나도 안 돌려도 모델 조회가\n * 4.6~7.7초였던 이유다(crew-probe 23,731건). 스냅샷은 같은 폴드의 결과이므로, 그 뒤로 이벤트도\n * 구조 변경도 없다면 **다시 접어 봐야 같은 값**이다.\n *\n * 쓰지 않는 조건을 좁게 잡는다: 지금을 물었을 때만(시간여행은 그 시점까지 접어야 한다), 리비전이\n * 끝과 같을 때만, 구조 리비전까지 같을 때만. 하나라도 어긋나면 접는다 — 캐시가 사실을 이기지 않는다.\n */\n const asOfNowRead = untilRevision == null && untilTime == null\n const tip = asOfNowRead ? await this.tipOf(domainId, instanceId).catch(() => null) : null\n /* 한 번만 읽는다 — 끝에 있으면 그대로 쓰고, 아니면 아래에서 **이어 접는 씨앗**으로 쓴다. */\n const cachedForResume = asOfNowRead && tip ? await this.loadSnapshot(domainId, instanceId).catch(() => null) : null\n if (cachedForResume) {\n const state = unwrapState(cachedForResume.state)\n if (state && (cachedForResume.revision ?? 0) === tip!.revision && (cachedForResume.structureRev ?? null) === tip!.structureRev)\n return state\n }\n\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) throw new Error(`twin instance \"${instanceId}\" not registered (no model to replay)`)\n\n /*\n * ── 재개점에서 **이어 접는다** (2026-08-18) ────────────────────────────\n *\n * 우리는 이미 접은 결과를 남기고 있다(`saveFoldedSnapshot`). 그 지점의 **재개점**(리듀서 내부 상태\n * 전부 + 가동 누적기)이 함께 있으면, 그 뒤에 일어난 것만 접어도 같은 답이 나온다 — 그 동치는\n * 커널 시험이 증명한다(0부터 접기 == 재개점 + 꼬리).\n *\n * 쓰는 조건을 좁게 잡는다: **지금을 물었을 때만**(시간여행은 목표 이전 재개점이 필요한데 지금은\n * 최신 하나만 남긴다 — 사슬은 다음 단계다), 구조가 그대로일 때만(구조가 바뀌면 그 경계에서 갈라\n * 접어야 한다), 재개점이 저널 끝보다 앞설 때만. 하나라도 어긋나면 0부터 접는다 — **캐시가 사실을\n * 이기지 않는다.**\n */\n /*\n * 씨앗은 둘 중 하나다: **지금**을 물으면 최신 재개점, **과거**를 물으면 사슬에서 목표 직전 지점.\n *\n * 과거 씨앗은 구조가 한 번도 바뀌지 않은 트윈에서만 쓴다 — 구조가 갈린 저널은 마디마다 갈아 접어야\n * 하고, 마디를 건너뛴 씨앗은 그 경계의 판정을 잃는다(그때는 0부터 접는 것이 옳다).\n */\n const structureCount = asOfNowRead\n ? 0\n : await getRepository(TwinStructure).count({ where: { domain: { id: domainId }, instanceId } }).catch(() => 99)\n const pastSeed =\n !asOfNowRead && structureCount <= 1\n ? await this.chainSeedFor(domainId, instanceId, {\n ...(untilRevision != null ? { revision: untilRevision } : {}),\n ...(untilTime != null && !Number.isNaN(Date.parse(untilTime)) ? { timeMs: Date.parse(untilTime) } : {})\n }).catch(() => null)\n : null\n const resume =\n asOfNowRead && tip && cachedForResume && cachedForResume.fold && (cachedForResume.structureRev ?? null) === tip.structureRev\n ? cachedForResume\n : pastSeed\n\n /*\n * **자를 것을 알면서 다 읽어 오지 않는다** (2026-08-18 실측).\n *\n * 저널을 전량 읽어 온 뒤 JS 에서 걸렀다. 27만 건짜리 트윈(order-check)에서 한 시간 전 상태를 물으면\n * **7.4초**가 걸렸고, 그 대부분이 「필요 없는 행을 읽어 오는 시간」이었다. 시각·리비전 상한은 SQL 이\n * 아는 조건이므로 거기서 자른다(TypeORM 관용구만 — 원시 SQL 은 5개 드라이버에서 갈라진다).\n *\n * 시각 상한에는 **경계를 그대로** 쓴다(`<=`): 그 시각에 일어난 사실은 그 시각의 화면에 있어야 한다.\n * 시각이 없는 레거시 행은 보수적으로 포함해 왔는데, SQL 로 자르면 그 행들이 빠진다 — 그래서 시각\n * 조건일 때는 **시각이 비어 있는 행도 함께** 가져와 예전과 같은 결과를 낸다.\n */\n const cutoffMs = untilTime != null ? Date.parse(untilTime) : NaN\n const useTime = untilTime != null && !Number.isNaN(cutoffMs)\n const baseWhere = { domain: { id: domainId }, instanceId }\n /* 이어 접을 때는 **그 뒤만** 읽는다 — 재개점까지의 사실은 이미 씨앗 안에 있다. */\n const from = resume ? (resume.revision ?? 0) : undefined\n /*\n * journal-fold: 재생은 사실을 하나씩 접는 것이므로 그 구간의 행이 필요하다. 커서(`from`)와 시각\n * 상한이 구간을 자르고, 체크포인트가 앞쪽을 씨앗으로 대신한다 — 표 전체를 읽지 않는다.\n */\n const rows = await getRepository(TwinEvent).find({\n where: useTime\n ? from\n ? /* 씨앗 뒤 · 목표 이내 — 시각이 빈 옛 행은 씨앗 뒤에 있는 것만 포함한다(보수적 포함을 유지). */\n [\n { ...baseWhere, revision: MoreThan(from), eventTime: LessThanOrEqual(new Date(cutoffMs)) },\n { ...baseWhere, revision: MoreThan(from), eventTime: IsNull() }\n ]\n : [\n { ...baseWhere, eventTime: LessThanOrEqual(new Date(cutoffMs)) },\n { ...baseWhere, eventTime: IsNull() }\n ]\n : untilRevision != null\n ? from\n ? { ...baseWhere, revision: And(MoreThan(from), LessThanOrEqual(untilRevision)) }\n : { ...baseWhere, revision: LessThanOrEqual(untilRevision) }\n : from\n ? { ...baseWhere, revision: MoreThan(from) }\n : baseWhere,\n order: { revision: 'ASC' }\n })\n const wanted = rows\n\n /*\n * **그때의 공장으로 접는다.**\n *\n * 예전에는 모든 이벤트를 지금 등록된 보드 하나로 접었다. 구조가 바뀐 적 없으면 맞지만, 바뀐\n * 뒤에는 옛 사실을 새 공장에 대고 접게 되어 — 그때 없던 설비에서 일이 있었던 것처럼 보인다.\n * (그래서 예전 프로비저닝은 구조가 바뀌면 저널을 아예 지웠다. 역사를 잃거나 거짓말을 하거나.)\n *\n * 이제 이벤트가 자기 구조를 달고 오므로, 리비전이 바뀌는 지점에서 구조를 갈아타며 이어 접는다.\n * 리비전이 하나뿐이거나(대다수) 아예 없으면(구조 이력 이전) 예전과 똑같이 한 번에 접는다.\n */\n const structures = await getRepository(TwinStructure).find({\n where: { domain: { id: domainId }, instanceId },\n order: { rev: 'ASC' }\n })\n const boardOf = new Map<number, TwinModelDef>(structures.map(x => [x.rev, x.model as TwinModelDef]))\n /* 컬럼이 생기기 전 행은 리비전이 비어 있다 — **가장 오래된 구조**에 속한다(0 으로 채우지 않는다). */\n const oldest = structures[0]?.rev\n const revOf = (r: { structureRev?: number }): number | undefined => r.structureRev ?? oldest\n\n const segments: { model: TwinModelDef; events: any[] }[] = []\n for (const r of wanted) {\n if (!r.payload) continue\n const rev = revOf(r)\n const model = (rev !== undefined && boardOf.get(rev)) || (reg.model as TwinModelDef)\n const last = segments[segments.length - 1]\n if (last && last.model === model) last.events.push(r.payload)\n else segments.push({ model, events: [r.payload] })\n }\n /*\n * **가장 새 구조가 지금의 공장이다** — 그 아래에서 아직 아무 일도 없었더라도.\n *\n * 재프로비저닝 직후가 정확히 그 상태다: 부스를 넷 늘렸는데 새 이벤트는 아직 하나도 없다. 이때\n * 마지막 이벤트의 구조로만 접으면 화면은 **옛 공장**을 보여준다 — 방금 늘린 것이 안 보인다.\n * 그래서 마디의 끝에 지금 구조를 한 번 더 얹는다(이벤트 없는 마디).\n *\n * **다만 \"지금\" 을 물었을 때만이다.** 과거 시점을 물었는데 최신 구조를 얹으면, 그 시점에 없던\n * 설비가 화면에 서고 — 이 작업이 막으려던 바로 그 거짓말이 된다.\n */\n const asOfNow = untilRevision == null && untilTime == null\n const newest = structures[structures.length - 1]?.model as TwinModelDef | undefined\n if (asOfNow && newest && segments[segments.length - 1]?.model !== newest) segments.push({ model: newest, events: [] })\n\n /*\n * 접은 상태에 **주의 신호와 시각을 채운다.**\n *\n * 라이브·시뮬은 커널이 신호를 스스로 내지만, 저널을 접는 이 경로는 프로젝터 상태만 낸다 — 신호도\n * `nowTime` 도 없다. 그래서 **과거를 다시 계산하면 주의 레일이 텅 비었고**(지도는 `snap.attentions` 를\n * 읽는다), 기동돼 있지 않은 트윈을 보는 화면도 같았다. 신호는 상태에서 계산되는 것이므로\n * 여기서 같은 공식(`deriveAttentions`)으로 채우면 된다 — 두 벌을 두지 않는다.\n *\n * `nowTime` 이 먼저다: \"늦었나\" 판정이 그 값을 본다. 다시 계산한 시점의 정직한 \"지금\" 은 물어본 시각\n * (`untilTime`)이고, 없으면 마지막으로 적용한 이벤트의 시각이다. 둘 다 없으면 채우지 않는다 —\n * 벽시계를 끼워 넣으면 과거 화면이 \"지금 기준으로 늦었다\" 고 말하게 된다.\n */\n const lastEventTime = rows.length ? (rows[rows.length - 1]?.eventTime?.toISOString() ?? '') : ''\n\n /*\n * **가동 이력도 되살린다** — 다시 계산한 화면에 설비 계측이 비어 있던 것.\n *\n * OEE 는 원 시스템이 누적을 보내 주지 않아 호스트가 상태 전이를 적분해 만든다(그래서 커널이 아니라\n * 여기 있다). 그런데 그 누적기는 **라이브에서만** 돌았고, 저널을 접는 경로는 그 계산을 하지 않았다 —\n * 과거를 다시 계산하면 모든 설비가 \"가동 이력이 전혀 없음\" 으로 보였다.\n *\n * 없는 것은 데이터가 아니라 계산이다: 입력(`equipment.status` 전이·`quality.output`)은 저널에 다\n * 있다. 그래서 **같은 누적기에 같은 이벤트를 태운다** — 규칙을 두 벌 만들지 않는다.\n *\n * 시간여행에서도 맞다: 여기 태우는 것은 이미 잘라 낸(`wanted`) 이벤트뿐이므로, 그 시점까지의\n * 가동 이력이 나온다(그 뒤에 일어난 고장이 과거 화면에 섞이지 않는다).\n */\n const oee = new OeeAccumulator()\n /* 재개점이 있으면 그 위에 꼬리만 얹는다 — 없으면 꼬리분만 세어 가용률이 조용히 작아진다. */\n if (resume?.fold?.oee) oee.restore(resume.fold.oee)\n for (const r of wanted) {\n try {\n oee.apply(r.payload as any)\n } catch {\n /* 한 건이 이상해도 나머지 계측을 버리지 않는다 — 누적기는 모르는 이벤트를 무시하는 계약이다. */\n }\n }\n\n const withNow = (st: any): any => {\n if (!st || typeof st !== 'object') return st\n const nowTime = st.nowTime || untilTime || lastEventTime || undefined\n const based = nowTime ? { ...st, nowTime } : st\n /* 계측 시점은 그 화면의 \"지금\" 이다 — 벽시계로 재면 과거 화면의 가용률이 시간이 갈수록 떨어진다. */\n const nowMs = nowTime ? Date.parse(String(nowTime)) : Number.NaN\n const withMetrics = withLiveOee(based, oee, Number.isFinite(nowMs) ? nowMs : undefined)\n return withLiveAttentions(withMetrics)\n }\n\n /* 접은 결과를 남긴다 — **지금을 물었을 때만**(시간여행 결과를 \"지금\" 으로 저장하면 거짓이 된다). */\n /*\n * 접은 지점의 리비전 — 사슬에 적을 이름이다. 꼬리를 접었으면 그 꼬리의 끝, 아무것도 안 읽었으면\n * 씨앗의 자리 그대로다(모르면 0).\n */\n const foldedTo = rows.length ? (rows[rows.length - 1]?.revision ?? 0) : (from ?? 0)\n\n const keep = (st: any, fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint }): any => {\n /* 재개점을 함께 남긴다 — 상태만 남기면 다음 번에 또 0부터 접어야 한다(그것이 이 작업의 요점이다).\n **구조가 갈린 폴드에는 재개점을 붙이지 않는다**: 마디를 건너뛴 씨앗은 그 경계의 판정을 잃는다. */\n if (asOfNowRead && tip && st) {\n void this.saveFoldedSnapshot(domainId, instanceId, { revision: tip.revision, state: st, structureRev: tip.structureRev, fold })\n }\n /*\n * 사슬에는 **과거를 접었을 때도** 한 지점을 남긴다 (2026-08-18 실측으로 고침).\n *\n * 처음에는 「지금 읽기」에서만 남겼다. 그런데 도는 트윈의 지금 읽기는 커널 스냅샷으로 즉시 답하고\n * 폴드에 닿지 않는다 — 그래서 사슬이 **영원히 비어 있었다**(실측: 지점 0개, 시간여행 3.7s 그대로).\n *\n * 지점은 「지금」을 주장하지 않는다: 자기 리비전과 시각을 달고 있으므로 과거 폴드의 결과를 남겨도\n * 거짓이 아니다(그것이 스냅샷과 다른 점이다). 그래서 첫 과거 조회가 다음 과거 조회를 빠르게 한다.\n */\n if (fold && st) {\n const at = asOfNowRead && tip ? tip.revision : foldedTo\n if (at > 0)\n void this.keepChainPoint(domainId, instanceId, {\n revision: at,\n ...(lastEventTime ? { eventTime: lastEventTime } : {}),\n structureRev: (asOfNowRead && tip ? tip.structureRev : null) ?? null,\n fold\n }).catch(() => {})\n }\n return st\n }\n\n /*\n * 씨앗이 있으면 **이어 접는다** — 한 구조 안에서만(구조가 갈리면 아래 마디 경로가 맡는다).\n * 새 재개점도 함께 남긴다: 다음 번에 또 꼬리만 접을 수 있어야 이 지름길이 계속 산다.\n */\n if (resume?.fold?.reducer && segments.length <= 1) {\n const model = (segments[0]?.model ?? (asOfNow && newest) ?? reg.model) as TwinModelDef\n const out = replayFrom(model, resume.fold.reducer, segments[0]?.events ?? [])\n return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() })\n }\n\n if (!segments.length) {\n const model = ((asOfNow && newest) || reg.model) as TwinModelDef\n const out = replayWithCheckpoint(model, [])\n return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() })\n }\n if (segments.length === 1) {\n const out = replayWithCheckpoint(segments[0].model, segments[0].events)\n return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() })\n }\n\n /* 커널 계약도 `model` 이다(0.6.14) — 경계에서 어휘를 되돌려 담던 브릿지가 사라졌다. */\n const { state, shifts } = replaySegments(segments)\n /* 경계에서 사라진 것을 조용히 넘기지 않는다 — 수가 줄어든 이유를 어딘가에는 남겨야 한다. */\n for (const sh of shifts)\n if (sh.equipmentDropped || sh.locationsDropped || sh.personsDropped || sh.assetsDropped)\n console.info(`[twin-engine] \"${instanceId}\" replay crossed a structure change — dropped ${sh.equipmentDropped} equipment, ${sh.locationsDropped} locations, ${sh.personsDropped} persons, ${sh.assetsDropped} assets that no longer exist.`)\n return keep(withNow(state))\n }\n\n /**\n * 공간(공동배치) 시각 범위 — 스크러버 앵커(runtime-state-model §4·§6). 그 공간 전 인스턴스 저널의 min/max eventTime.\n * 반환 {minTime, maxTime}(ISO) — 이벤트/시각 없으면 null. 클라 히스토리 스크러버가 이 범위를 시각축으로 그린다.\n *\n * ── 두 수를 구하려고 저널을 다 읽지 않는다 (2026-08-20 실측으로 잡음) ────────\n * 여기서 인스턴스마다 `find()` 로 **행을 전부 엔티티로 하이드레이션**한 다음 JS 에서 min/max 를\n * 골랐다. 그런데 이 함수는 화면 상단의 컨텍스트 띠가 **4초마다** 부른다. 실측한 개발 서버에서\n * `order-check` 한 트윈이 275,882행 · `payload` 131MB 였다 — 4초마다 그 JSON 을 전부 파싱한 것이다.\n *\n * 그 결과가 이랬다: 프로세스 CPU 81~152%, 아무 일도 하지 않는 질의가 8~14초. JS 프로파일의 상위가\n * TypeORM 의 `RelationIdLoader`·`RawSqlResultsToEntityTransformer`·`stringToSimpleJson`(= `payload`\n * 파싱)이고 GC 가 16.7% 였다. **트윈 틱도 저널 쓰기도 아니라 이 읽기였다.**\n *\n * 집계는 DB 가 한다. `(domain, instanceId, eventTime)` 인덱스가 이미 있어(`ix_twin_event_1`)\n * 인덱스의 **양 끝을 집는다** — 행을 하나도 실어 오지 않는다.\n *\n * ── 왜 MIN 과 MAX 를 한 문장에 넣지 않나 (실측) ─────────────────────────────\n * 처음에 `SELECT MIN(...), MAX(...) ... WHERE instanceId IN (...)` 한 방으로 두었더니 **21ms** 였다.\n * 집계가 **둘이면** 옵티마이저의 「인덱스 끝을 집는」 최적화가 걸리지 않아 인덱스 구간을 훑는다 —\n * 즉 비용이 여전히 **행 수에 비례**한다. 트윈마다 단일 집계로 나눠 물으면 **0.32ms**(트윈 3개 · 6왕복)\n * 이고, 비용이 **트윈 수에 비례**한다. 규모 기준(엔티티 10만)에서는 이 차이가 본질이다.\n *\n * 왕복은 트윈당 둘이지만 **함께 띄운다** — 원격 DB 에서 직렬로 돌면 왕복 지연이 그대로 쌓인다.\n *\n * 드라이버 다섯을 다 지나가야 하므로 raw SQL 을 쓰지 않는다(쿼리빌더의 MIN/MAX 는 이식된다).\n * 돌려주는 값의 **모양은 드라이버마다 다르다**(문자열·Date) — 받은 뒤에 한 번 정규화한다(`parseTime`).\n */\n static async timeRange(domainId: string, spaceId: string): Promise<{ minTime: string | null; maxTime: string | null }> {\n const regs = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n const ids = regs.map(r => r.instanceId)\n if (!ids.length) return { minTime: null, maxTime: null }\n\n /**\n * 한 트윈 저널의 시각 양 끝 하나 — 단일 집계라 인덱스 끝을 집는다.\n *\n * 집계식을 **조립하지 않고 표에 리터럴로 적는다.** `` `${agg}(e.eventTime)` `` 로 만들면 이 자리가\n * 집계를 쓰는지 훑는 검사(`journal-read-discipline`)가 찾지 못한다 — 실제로 그렇게 빨개졌다.\n * 번역 키에서 겪은 것과 같은 규율이다: 검사가 일하게 두는 편이 낫다.\n */\n const AGG_SELECT = { MIN: 'MIN(e.eventTime)', MAX: 'MAX(e.eventTime)' } as const\n const edge = async (instanceId: string, agg: 'MIN' | 'MAX'): Promise<number | null> => {\n const row = await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select(AGG_SELECT[agg], 't')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n .getRawOne<{ t: unknown }>()\n return parseTime(row?.t)\n }\n\n let min = Infinity\n let max = -Infinity\n\n /*\n * 한 번에 띄우는 수를 묶는다 — 공간에 트윈이 수백이면 왕복 수백 개를 동시에 보내 커넥션 풀을\n * 말려 버린다(이 함수 하나 때문에 다른 질의가 기다리게 된다).\n */\n for (let i = 0; i < ids.length; i += TIME_RANGE_FANOUT) {\n const batch = ids.slice(i, i + TIME_RANGE_FANOUT)\n const edges = await Promise.all(batch.flatMap(id => [edge(id, 'MIN'), edge(id, 'MAX')]))\n for (let k = 0; k < edges.length; k += 2) {\n const lo = edges[k]\n const hi = edges[k + 1]\n if (lo !== null && lo < min) min = lo\n if (hi !== null && hi > max) max = hi\n }\n }\n\n if (min === Infinity) return { minTime: null, maxTime: null }\n return { minTime: new Date(min).toISOString(), maxTime: new Date(max).toISOString() }\n }\n\n /** 정지 훅 — 인스턴스 정지 시 부수자원 정리(예: reference-live 피드 unsubscribe). 순환 임포트 없이 결선. */\n static stopHooks: ((id: string) => void)[] = []\n static onStop(fn: (id: string) => void): void {\n this.stopHooks.push(fn)\n }\n\n static async stop(domainId: string, id: string): Promise<void> {\n const i = this.instances[runtimeKey(domainId, id)]\n if (i) {\n /*\n * **끄기 전에 남긴다** — 지금이 메모리가 진실인 마지막 순간이다.\n *\n * 남기지 않으면 다음 조회가 저널을 전량 다시 접는다(그 값은 어차피 방금 메모리에 있던 것이다).\n * 체크포인트 루프가 20초마다 뜨지만 그 사이에 멈추면 그 구간이 통째로 다시 접힌다.\n */\n await this.persistSnapshot(domainId, id).catch(err =>\n twinError(`[twin-engine] snapshot on stop fail \"${id}\"`, err?.message ?? err)\n )\n /*\n * **모아 둔 저널도 지금 흘린다** — 주기 flush 사이(최대 `BROADCAST_COALESCE_MS`)에 멈추면 그 구간의\n * 사실이 사라진다. 스냅샷만 남기면 상태는 살아도 **왜 그렇게 됐는지**가 빈다(저널이 답하는 것이다).\n * 쓰기는 이 함수를 기다리지 않지만(비차단) 버퍼는 여기서 비워지므로 다음 기동이 두 번 적지 않는다.\n */\n await this.flushJournal(i)\n clearInterval(i.timer)\n i.unsub()\n delete this.instances[runtimeKey(domainId, id)]\n await getRepository(TwinInstance)\n .update({ domain: { id: i.domainId }, instanceId: id }, { status: 'stopped' })\n .catch(err => twinError('twin deregister fail', err))\n }\n for (const hook of this.stopHooks) { try { hook(id) } catch { /* 훅 격리 */ } }\n }\n\n /*\n * tick 한 번 — **한 트윈의 예외가 서버를 내리지 못하게** 감싼다.\n *\n * 잘못된 시나리오가 실렸을 때 다음 tick 에서 `rate.meanPerHour` 를 읽다 터졌고, 타이머 콜백의\n * 예외는 아무도 받지 않아 **uncaught exception 으로 프로세스가 내려갔다.** 한 테넌트의 잘못된\n * 선언이 모든 테넌트를 멈춘 셈이다. 문 앞에서 막는 것이 1차 방벽이고(`validateScenario`),\n * 이것이 2차 방벽이다.\n *\n * **조용히 삼키지 않는다.** 실행을 멈추고 그 사실을 남긴다 — 예외를 무시하고 계속 tick 하면\n * 같은 오류가 매 주기 쏟아지고, 그 트윈은 \"도는 것처럼 보이면서\" 아무것도 진행하지 않는다.\n */\n /**\n * 같은 현장 트윈들의 **설비 상태**를 커널에 넘긴다 — 커널이 요청할 때만.\n *\n * ── 경계 (2026-08-14) ──────────────────────────────────────────────────────\n * 호스트가 아는 것은 **누가 같은 현장에 있는가** 하나다. 무엇을 읽고 그것을 어떻게 부하로 바꿀지는\n * 커널이 정한다(계수는 트윈의 모델이 선언한다). 호스트가 kW 를 계산해 주면 트윈마다 다른 규칙이\n * 생기고, 그 규칙은 어디에도 적혀 있지 않게 된다.\n *\n * 상태만 넘긴다. 스냅샷을 통째로 넘기면 상태 크기에 비례한 비용을 매 tick 치르게 된다 —\n * 설비 목록은 그 트윈의 커널이 이미 들고 있는 것이라 훑는 값이 싸다.\n */\n private static feedPeerEquipment(inst: InstanceRuntime): void {\n const kernel: any = inst.kernel\n if (typeof kernel?.observePeerEquipment !== 'function') return // 이웃을 읽지 않는 커널\n if (!inst.spaceId) {\n kernel.observePeerEquipment([]) // 현장이 없으면 이웃도 없다(옛 상태가 남지 않게 비운다)\n return\n }\n const peers: { id: string; status?: string }[] = []\n for (const other of Object.values(this.instances)) {\n if (other === inst || other.domainId !== inst.domainId || other.spaceId !== inst.spaceId) continue\n const eq: Map<string, any> | undefined = (other.kernel as any)?.equipment\n if (!eq || typeof eq.forEach !== 'function') continue\n eq.forEach(e => peers.push({ id: String(e?.id ?? ''), status: String(e?.status ?? '') }))\n }\n kernel.observePeerEquipment(peers)\n }\n\n private static tickGuarded(domainId: string, id: string, runtime: TwinRuntimeType): void {\n const inst = this.instances[runtimeKey(domainId, id)]\n const load = inst && (inst.load ?? (inst.load = newLoadMeter()))\n const t0 = performance.now()\n try {\n /* 이웃의 설비 상태를 먼저 싣는다 — 커널이 이번 tick 에서 부하를 만들 때 읽는다. */\n if (inst) this.feedPeerEquipment(inst)\n runtime.tick(this.TICK_MS)\n\n /* 재고 말한다 — 시뮬 틱은 메인 이벤트 루프에서 수행된다. 예산(간격의 절반)을 넘기면 HTTP·구독이\n 함께 느려지는데, 예전에는 그것을 볼 계기판이 없어 \"터지면 알고 느려지면 몰랐다\". */\n if (load) {\n const took = performance.now() - t0\n recordPhase(load, 'tick', took)\n const j = judgeCycle(load, took, this.TICK_MS, Date.now())\n if (j.warn) twinWarn(slowTickMessage(id, took, j.budgetMs, load))\n this.guardStarvation(domainId, id, took)\n }\n } catch (err: any) {\n /*\n * 멈추는 길은 **하나**다(`stop`) — 예전에는 타이머만 껐다. 그러면 등록부는 계속 `running` 이라\n * 말하고(아무 틱도 없는 채로), 부팅 재개는 그 거짓을 근거로 다시 세운다. 스냅샷 보존·피드 정리·\n * 등록부 갱신이 모두 `stop` 안에 있다.\n */\n this.stopWithNote(\n domainId,\n id,\n { code: 'tick-failed', params: { reason: String(err?.message ?? err) } },\n `[twin-engine] \"${id}\" tick failed — this twin is stopped (other twins keep running). ` +\n `Fix the declaration and start it again. Reason: ${err?.message ?? err}`\n )\n }\n }\n\n /**\n * 호스트를 굶기는 트윈을 멈춘다 — **도는 척하는 것보다 멈춘 것이 낫다.**\n *\n * 굶김 문턱을 넘는 틱이 연속 `STARVE_STREAK` 번이면 그 트윈은 구조적으로 무겁다(우연이 아니다).\n * 문턱 아래로 한 번만 내려와도 연속을 끊는다 — 무거운 순간 하나로 트윈을 내리지 않는다.\n */\n private static guardStarvation(domainId: string, id: string, tookMs: number): void {\n const key = runtimeKey(domainId, id)\n const starveMs = this.TICK_MS * this.STARVE_FACTOR\n if (!(tookMs >= starveMs)) {\n this.starveStreak.delete(key)\n return\n }\n const streak = (this.starveStreak.get(key) ?? 0) + 1\n this.starveStreak.set(key, streak)\n if (streak < this.STARVE_STREAK) return\n\n this.starveStreak.delete(key)\n const secs = Math.round(tookMs) / 1000\n this.stopWithNote(\n domainId,\n id,\n { code: 'starved', params: { streak, thresholdSec: starveMs / 1000, lastSec: secs } },\n `[twin-engine] \"${id}\" stopped — ${streak} consecutive ticks over ${starveMs / 1000}s (last ${secs}s). ` +\n `A simulation tick runs on the main loop, so this twin was stalling HTTP, subscriptions and every other twin. ` +\n `Its state is checkpointed; start it again after making it lighter (fewer orders/resources) or wait for off-loop ticking.`\n )\n }\n\n /** 멈추고 **이유를 남긴다** — 이유 없는 「정지」는 사람이 자기가 멈춘 것으로 읽는다. */\n private static stopWithNote(domainId: string, id: string, note: StopNote, log: string): void {\n twinError(log)\n this.stopNotes.set(runtimeKey(domainId, id), note)\n this.stop(domainId, id).catch(err => twinError(`[twin-engine] stop after guard failed \"${id}\"`, err?.message ?? err))\n }\n\n /** 이 트윈이 스스로 멈춘 이유(있으면) — 화면이 옮겨 말한다. */\n static stopNoteOf(domainId: string, id: string): StopNote | undefined {\n return this.stopNotes.get(runtimeKey(domainId, id))\n }\n\n /**\n * 이 트윈이 **지금 실행 중인가** — 판정의 집 하나.\n *\n * \"스냅샷이 있나\" 로는 답이 되지 않는다: 웜스타트가 되살린 상태가 캐시에 남아 있으면 멈춘 트윈도\n * 스냅샷을 낸다. 그것을 관측 중으로 읽으면 화면이 **멈춘 트윈의 작업을 0 건이라고 단언**한다\n * (실제로 그렇게 나왔다 — 관측이 없는 것과 0 건은 다르다는 이 프로젝트의 규율을 화면이 어겼다).\n *\n * 목록이 쓰는 것과 **같은 술어**다(`list()` 의 `running`) — 두 벌이면 어긋난다.\n */\n static isRunning(domainId: string, id: string): boolean {\n return !!this.instances[runtimeKey(domainId, id)]\n }\n\n static runtime(domainId: string, id: string): TwinRuntimeType | undefined {\n return this.instances[runtimeKey(domainId, id)]?.runtime\n }\n\n /*\n * 커맨드 실행 — **판정은 `routeCommand`(순수)가 하고 여기서는 실행만** 한다.\n * 판정을 코드 한가운데 두면 이 부류를 테스트로 못 잡는다(엔진은 DB 를 물고 있어 단위 테스트가\n * 불러올 수 없다). 예전에는 리졸버가 `inst.runtime.dispatch` 를 곧바로 불러 미러에서 터졌다.\n */\n static async dispatchCommand(domainId: string, instanceId: string, command: any): Promise<{ accepted: boolean; error?: string; errorCode?: string; errorParams?: Record<string, string | number> }> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n const type = String(command?.type ?? '')\n const route = routeCommand(\n inst && { mode: inst.mode, hasRuntime: !!inst.runtime, hasKernelDispatch: typeof (inst.kernel as any)?.dispatch === 'function' },\n !!inst && inst.domainId === domainId,\n type\n )\n if (route.target === 'reject') {\n return { accepted: false, errorCode: route.errorCode, errorParams: route.errorParams, error: route.errorCode }\n }\n\n const cmd = { ...command, tenantId: domainId } // tenantId 는 호출자 도메인으로 각인(감사·무결성)\n if (route.target === 'runtime') return inst!.runtime!.dispatch(cmd)\n\n /*\n * 미러 — 관측 커널로 보내고, **커맨드가 낸 사실을 저널 큐에 실어** 코얼레서가 번호를 부여하게 한다.\n * 미러에는 State 구독 배관이 없어(시뮬은 그 경로로 저널링) 커널 방출이 아무 데도 닿지 않는다.\n * 여기서 DB 를 따로 읽어 번호를 매기면 인메모리 카운터와 어긋나 리비전이 겹친다(겹침은 오류를\n * 내지 않고 재생 순서만 조용히 뒤섞는다).\n */\n const kernel: any = inst!.kernel\n const emitted: any[] = []\n const off = kernel.onEvent?.((e: any) => emitted.push(e))\n let ack: any\n try {\n ack = kernel.dispatch(cmd)\n } finally {\n off?.()\n }\n if (ack?.accepted && emitted.length) {\n inst!.pendingJournal = [...(inst!.pendingJournal ?? []), ...emitted]\n inst!.dirty = true // 코얼레서가 이번 주기에 비우고 브로드캐스팅까지 하게 한다\n }\n return ack ?? { accepted: false, errorCode: 'unknown-command', error: 'unknown-command' }\n }\n\n /**\n * 도메인 소유 게이트 — 인스턴스가 이 도메인 소유일 때만 true(테넌트 격리).\n * 없거나 다른 도메인이면 false. 노출 리졸버(per-id metrics/attentions/state/stop/forecast)가\n * this.instances[id] 를 만지기 전에 반드시 이걸로 확인해야 한다. 인스턴스 id 는 추측 가능하므로\n * 검증 없이 접근하면 크로스테넌트 읽기/정지가 가능해진다.\n */\n /**\n * 이 런타임의 **관측 모드** — `'live'`(외부 실물을 미러) 또는 `'sim'`(커널이 실행한다). 기동 중이 아니면 없다.\n *\n * 소비처가 `instances[id].mode` 를 직접 읽던 자리를 대신한다. 레지스트리를 밖에 열면 도메인 확인이\n * 자리마다 제각각이 되고, 실제로 그렇게 됐다(테넌트 격리 전수 확인, 2026-08-06).\n */\n static modeOf(domainId: string, id: string): 'live' | 'sim' | undefined {\n return this.instances[runtimeKey(domainId, id)]?.mode\n }\n\n static owns(domainId: string, id: string): boolean {\n return !!this.instances[runtimeKey(domainId, id)]\n }\n\n /**\n * 이 트윈이 이 테넌트 것인가 — **떠 있든 아니든.**\n *\n * `owns()` 는 **기동 중인** 런타임만 안다. 그것을 이력 조회의 관문으로 쓰면, 꺼진 트윈의 저널을\n * 읽으려 할 때 \"이 테넌트에 없다\" 는 답이 돌아온다 — 두 가지가 틀렸다. 첫째, 저널은 트윈이 꺼져\n * 있을 때 **가장 필요한 것**이다(그게 이력의 존재 이유다). 둘째, 그 문장은 남의 것이라는 뜻이라\n * 사용자가 권한 문제로 오해한다. 실제로는 그냥 실행 중이 아닐 뿐이다.\n *\n * 소유는 **등록부**가 안다. 이력·집계처럼 런타임과 무관한 질문은 이쪽에 묻는다.\n */\n static async ownsRegistered(domainId: string, instanceId: string): Promise<boolean> {\n if (this.owns(domainId, instanceId)) return true\n return !!(await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } }))\n }\n\n /**\n * **이 공간의 인스턴스들** — 한 현실을 여러 렌즈가 비추므로, 공간을 물으면 그 렌즈 전부를 답한다.\n *\n * 화면이 이 규칙을 손으로 짜지 않게 서버가 답한다. 예측 화면은 같은 확장을 **한 파일에서 두 번**\n * 복제하고 있었다(전체 목록을 받아 클라이언트에서 걸렀다) — 규칙이 흩어지면 한쪽만 고쳐진다.\n *\n * 떠 있지 않은 것도 포함한다: 공간에 무엇이 있는지는 기동 여부와 다른 사실이다.\n */\n static async instanceIdsOfSpace(domainId: string, spaceId: string): Promise<string[]> {\n if (!spaceId) return []\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n return rows.map(r => r.instanceId).filter((x): x is string => !!x)\n }\n\n /**\n * **이 공간에서 봐야 할 것** — 공간의 모든 렌즈에서 신호를 모은다.\n *\n * 합집합이 그대로 뜻이 있는 유일한 렌즈다(예측은 합칠 수 없다 — P50 두 개를 더할 수 없다).\n * 정렬·잘라내기는 화면과 **같은 규칙**을 쓴다(`digestAttentions`) — 서버가 고른 상위 N 이 화면이\n * 고를 N 과 달라지면 그 어긋남은 아무 데서도 오류로 드러나지 않는다.\n *\n * 신호마다 어느 트윈에서 왔는지(`instanceId`)를 붙인다. 공간에서 보면 같은 자리 id 가 렌즈마다\n * 다른 것을 가리킬 수 있고, 조치는 결국 그 트윈에 보내야 한다.\n */\n static async attentionsOfSpace(domainId: string, spaceId: string, limit?: number): Promise<{ attentions: any[]; attentionTotal: number; severityByLocation: Record<string, string> }> {\n const ids = await this.instanceIdsOfSpace(domainId, spaceId)\n const lenses = ids\n /* 떠 있지 않은 트윈은 **지금** 신호가 없다(그 시절 신호는 시간여행이 답한다). */\n .filter(id => this.owns(domainId, id))\n .map(id => {\n const kernel: any = this.kernel(domainId, id)\n const snap = kernel?.getSnapshot?.() ?? this.snapshot(domainId, id)\n return { instanceId: id, attentions: snap?.attentions ?? [] }\n })\n /* 모으는 규칙(태깅·급한 순서·자리 색)은 순수 함수가 들고 있다 — 여기서 손으로 접지 않는다. */\n return mergeLensAttentions(lenses, limit)\n }\n\n /** 라이브 커널(ForecastTwin) — forecast/divergence 예측 연산용. */\n static kernel(domainId: string, id: string): any {\n return this.instances[runtimeKey(domainId, id)]?.kernel\n }\n\n /** 라이브 처리량 계측 스냅샷(모니터, ④-1) — 내부 누적(_acc*) 제외한 공개 지표. live 아니면 null. */\n static metrics(domainId: string, id: string): any {\n const m = this.instances[runtimeKey(domainId, id)]?.metrics\n if (!m) return null\n return {\n instanceId: id,\n ingestedTotal: m.ingestedTotal, broadcastTotal: m.broadcastTotal, journaledTotal: m.journaledTotal,\n ingestRate: m.ingestRate, broadcastRate: m.broadcastRate, journalRate: m.journalRate,\n backlog: m.backlog, broadcastCoalesceMs: this.broadcastPeriodMs,\n /* 작업별 부하 — 무거운 것부터. 잰 적이 없으면 null(0 으로 채우면 \"빠르다\" 로 읽힌다). */\n load: loadSummary(this.instances[runtimeKey(domainId, id)]?.load, this.TICK_MS)\n }\n }\n\n /**\n * 부하 계기판만 따로 — **시뮬 트윈도 포함한다.**\n *\n * `metrics()` 는 라이브 지표(`inst.metrics`)가 있어야 무언가를 돌려준다. 그런데 이벤트 루프를 점유하는\n * 것은 주로 **시뮬 틱**이고, 시뮬 인스턴스에는 그 지표가 없어 통째로 안 보였다.\n */\n static load(domainId: string, id: string): any {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (!inst) return null\n\n return {\n instanceId: id,\n mode: inst.mode ?? 'sim',\n domainId: inst.domainId,\n domainLabel: inst.domain?.subdomain,\n restartPolicy: inst.restartPolicy,\n tickMs: this.TICK_MS,\n running: !!inst.timer || inst.mode === 'live',\n ...(loadSummary(inst.load, this.TICK_MS) ?? { recent: null, total: null, forksCreated: 0, overBudget: 0, budgetMs: this.TICK_MS * 0.5, loadRatio: null })\n }\n }\n\n /**\n * **한 곳에서 보는 전체 부하** — 몇 개가 실행 중이고, 누가 루프를 점유하고 있나.\n *\n * 시뮬 트윈도 포함한다(`metrics()` 는 라이브 지표가 있어야 답해서 시뮬이 통째로 안 보였다).\n */\n static fleet(domainId?: string): any {\n const keys = Object.keys(this.instances).filter(key => !domainId || isOfDomain(key, domainId))\n const rows = keys.map(key => {\n const at = parseRuntimeKey(key)\n const inst = this.instances[key]\n /* 도메인을 함께 넘긴다 — 운영자가 먼저 묻는 것은 \"어느 테넌트가 루프를 먹나\" 다.\n 읽을 수 있는 이름(subdomain)은 라이브 인스턴스에만 붙어 있으므로, 없으면 리졸버가 채운다. */\n return {\n instanceId: at.instanceId,\n mode: inst.mode ?? 'sim',\n domainId: at.domainId,\n domainLabel: inst.domain?.subdomain,\n meter: inst.load\n }\n })\n\n return {\n tickMs: this.TICK_MS,\n broadcastCoalesceMs: this.broadcastPeriodMs,\n /* 브로드캐스팅 주기를 늘린 횟수 — 늘어난 주기만 보면 「원래 그런 값」으로 읽힌다. */\n broadcastBackoffs: this.broadcastBackoffs,\n /* 물품 범위를 좁히지 못해 전부 만든 횟수 — 좁히기가 실제로 듣고 있는지를 이 값으로 본다. */\n broadcastPasses: this.broadcastPasses,\n broadcastFullPasses: this.broadcastFullPasses,\n broadcastFullEvery: this.FULL_BROADCAST_EVERY,\n /* **루프가 실제로 얼마나 막혔나** — 트윈 부하와 나란히 놓고 원인을 가린다(loop-lag.ts 주석). */\n loopLag: loopLag.view(),\n ...fleetLoad(rows, this.TICK_MS),\n /* 줄마다 상세 — 화면이 펼쳐 볼 수 있게. 최근 부하 순서는 fleetLoad 가 정한다. */\n details: keys.map(key => { const at = parseRuntimeKey(key); return this.load(at.domainId, at.instanceId) }).filter(Boolean)\n }\n }\n\n /** 이 트윈에서 fork 가 만들어졌다 — 예측 한 번이 수십 개를 만든다. */\n static countForks(domainId: string, id: string, count: number): void {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst) recordFork(inst.load ?? (inst.load = newLoadMeter()), count)\n }\n\n /** 엔진 밖(예측 질의 등)에서 무거운 작업을 잰다 — 같은 계기판에 모인다. */\n static recordLoad(domainId: string, id: string, phase: LoadPhase, tookMs: number): void {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst) recordPhase(inst.load ?? (inst.load = newLoadMeter()), phase, tookMs)\n }\n\n /*\n * ── 동기화 건강 장부 ───────────────────────────────────────────────────────\n *\n * **런타임이 아니라 엔진이 든다.** 인스턴스에 붙이면 트윈을 재기동할 때 사라지는데, 사람이 알고 싶은\n * 것은 바로 그 순간이다 — 「고쳐서 다시 띄웠는데 이제 통과하나」. 프로세스가 사는 동안 이어진다.\n *\n * 지금은 메모리만이다. 창이 닫힐 때 한 행씩 영속하는 것은 `onWindowClosed` 한 자리에 붙는다.\n */\n private static ingestLedgers: Record<string, IngestLedger> = {}\n\n /** 창이 닫힐 때 부를 곳 — 영속 계층이 부팅에서 한 번 등록한다(커널 층은 그 계층을 모른다). */\n private static onWindowClosed?: (at: { domainId: string; instanceId: string }, closed: IngestWindow) => void\n\n /**\n * 닫힌 창을 받을 곳을 등록한다 — **영속(B)이 붙는 유일한 문.**\n *\n * 이 패키지는 저장 계층을 모른다. 등록하는 쪽이 자기 방식으로 쓴다. 훅이 오류를 내도 장부는 계속 굴러간다\n * (`rollIngestWindow` 가 감싼다) — 영속을 지키려고 관측을 멈추지 않는다.\n */\n static onIngestWindowClosed(\n fn: (at: { domainId: string; instanceId: string }, closed: IngestWindow) => void\n ): void {\n this.onWindowClosed = fn\n }\n\n /**\n * 한 번의 인제스트 결과를 장부에 적는다.\n *\n * `offered` 는 **제시된 레코드 수**다(거부 여부 무관). 통과율을 서로 다른 두 계수기에서 나눠 계산하면\n * 분모와 분자가 다른 것을 세게 되므로, 한자리에서 본 수를 그대로 넘긴다.\n */\n static recordIngestResult(\n domainId: string,\n instanceId: string,\n offered: number,\n rejected: { record?: unknown; errors?: string[] }[] | undefined,\n nowMs = Date.now(),\n /**\n * 매핑은 통과했는데 **커널이 받지 않은** 수(`ingestLive` 의 반환과 견주어 얻는다).\n *\n * 「통과」로 세지 않는다 — 트윈이 멈춘 사이 사실이 사라지는데 화면이 100% 라고 말하게 된다.\n */\n undelivered = 0\n ): void {\n const key = runtimeKey(domainId, instanceId)\n const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = newIngestLedger())\n recordIngest(\n ledger,\n offered,\n rejected,\n nowMs,\n closed => this.onWindowClosed?.({ domainId, instanceId }, closed),\n undelivered\n )\n }\n\n /**\n * **원본에 닿지 못했다**를 적는다 — 「받은 것이 없다」와 가른다(§`recordReadFailure`).\n *\n * 이 문이 없던 동안 실 원본이 끊겨도 트윈의 조회 가능한 상태에 그 사실이 없었다. 화면이 볼 수 있는\n * 것은 「새 사실이 없다」뿐이었고 그것은 「원본이 조용하다」와 구별되지 않는다 — 실증 중에 원본이\n * 끊기면 사용자가 원인을 찾을 수 없다.\n *\n * 로그로는 말하고 있었다(어댑터가 재시도를 경고한다). 그러나 **로그는 사람이 볼 때만 값이 있다** —\n * 화면이 말하려면 상태에 있어야 한다.\n */\n static recordIngestReadFailure(domainId: string, instanceId: string, reason: string, nowMs = Date.now(), stream?: string): void {\n const key = runtimeKey(domainId, instanceId)\n const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = newIngestLedger())\n recordReadFailure(ledger, reason, nowMs, stream)\n }\n\n /**\n * 읽기가 성공했다 — 단절 기록을 지운다.\n *\n * **빈 읽기도 성공이다.** 원본이 「새 것이 없다」고 답한 것은 닿았다는 뜻이므로, 그때도 부른다.\n * 그 둘을 같게 두면 조용한 원본이 끊긴 원본으로 보인다.\n */\n static clearIngestReadFailure(domainId: string, instanceId: string): void {\n const ledger = this.ingestLedgers[runtimeKey(domainId, instanceId)]\n if (ledger) clearReadFailure(ledger)\n }\n\n /**\n * 저널에 **적은 것**을 같은 장부에 남긴다 — 유입과 같은 10분 창에.\n *\n * ── 왜 유입 장부에 넣나 ────────────────────────────────────────────────────\n * 새 장부를 만들면 「닫힌 창만 최근」·「0 과 없음을 가른다」·영속을 두 벌 지켜야 하고, 그중 한 벌만\n * 고쳐지는 것이 보통이다. 유입 창은 그 규율이 이미 들어 있고 닫힐 때 행으로 남는다.\n *\n * ── 이 값이 없으면 무엇을 못 보나 ──────────────────────────────────────────\n * 계기(`journalRate`)는 **지금**만 답한다. 프로세스를 다시 띄우면 0 에서 시작하므로 「어제 이 시각에도\n * 이랬나」·「고친 뒤로 줄었나」를 물을 자리가 없다. 2026-08-20 에 고친 것이 바로 쓰기 경로이므로,\n * 되돌아가는 것을 볼 수 있어야 한다.\n */\n static recordJournalWrite(domainId: string, instanceId: string, rows: number, nowMs = Date.now()): void {\n const key = runtimeKey(domainId, instanceId)\n const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = newIngestLedger())\n recordLedgerWrite(ledger, rows, nowMs, closed => this.onWindowClosed?.({ domainId, instanceId }, closed))\n }\n\n /**\n * 「이 트윈이 현장과 맞춰지고 있나」 — 한눈 판정 + 추이 + 사유 + 표본.\n *\n * 조회할 때 창을 한 번 굴린다: 유입이 멈추면 다음 인제스트가 없어 창이 영원히 닫히지 않는데, 그러면\n * 「최근」이 옛것으로 남는다. 타이머를 두지 않는 이유는 트윈마다 타이머를 걸면 그 타이머들이 다시\n * 메인 루프에 얹히기 때문이다(오늘 확인한 그 부하를 이 기능이 다시 만들 이유가 없다).\n */\n /**\n * 도메인의 트윈마다 **한 줄 요약** — 목록 화면과 미니 추이용.\n *\n * ── 왜 상세와 따로인가 ─────────────────────────────────────────────────────\n * `ingestHealthOf` 는 사유 문구와 **레코드 원문 표본**까지 낸다. 목록에 트윈이 스무 개면 그 원문이\n * 스무 벌 실려 조회가 무거워지고, 화면은 어차피 그것을 그리지 않는다. 그래서 여기서는 **숫자만** 낸다.\n *\n * 추이는 창당 숫자 넷이라 스파크라인 하나에 충분하고 가볍다.\n *\n * ── 등록된 트윈을 기준으로 훑는다 ──────────────────────────────────────────\n * 도는 트윈만 훑으면 「고치려고 멈춰 둔 트윈」이 목록에서 사라진다 — 사람이 방금 멈춘 그것을 보려고\n * 목록을 여는데 없으면 결함으로 읽는다. 그래서 호출부(목록 화면)가 아는 instanceId 들을 받는다.\n */\n static ingestHealthBrief(\n domainId: string,\n instanceIds: string[]\n ): { instanceId: string; verdict: string; acceptedRatio: number | null; trend: { offered: number; rejected: number; undelivered: number; rows: number }[]; lastAt: string | null }[] {\n return instanceIds.map(instanceId => {\n const full = this.ingestHealthOf(domainId, instanceId)\n return {\n instanceId,\n verdict: full.verdict,\n /* 최근 **닫힌** 창의 통과율. 창이 안 닫혔으면 비운다 — 0 이나 1 로 채우지 않는다. */\n acceptedRatio: full.recent?.acceptedRatio ?? null,\n /*\n * 스파크라인용 — 창마다 셋. **미전달을 빼놓으면 스파크라인이 거짓을 그린다**: 버려진 것을\n * 통과로 세면 트윈이 멈춘 구간에서도 선이 100% 에 붙는다.\n */\n /* 적힌 행도 함께 — 시뮬 트윈은 유입이 0 이라 이 값 없이는 추이가 빈 선으로 보인다. */\n trend: full.trend.map(w => ({ offered: w.offered, rejected: w.rejected, undelivered: w.undelivered, rows: w.rows })),\n lastAt: full.lastAt\n }\n })\n }\n\n /**\n * 한 트윈의 동기화 건강.\n *\n * ── 조회가 장부를 전진시킨다(의도) ─────────────────────────────────────────\n * 창은 **다음 유입이 있을 때** 닫힌다. 그래서 피드가 죽으면 마지막 창이 열린 채로 남아 영원히 영속되지\n * 않고, 추이에도 들어가지 않는다. 조회 시점에 한 번 굴려 주면 그 마지막 창이 닫히면서 영속 훅도 불린다\n * — 즉 **죽은 피드의 마지막 구간을 잃지 않기 위해** 읽기가 굴린다. 부수효과지만 필요한 부수효과다.\n *\n * 시각은 **한 번만 읽어** 굴리기와 판정에 같은 값을 쓴다. 두 번 읽으면 그 사이에 창이 닫혀 판정이\n * 굴리기 전 상태를 보는 일이 생긴다.\n */\n static ingestHealthOf(domainId: string, instanceId: string): IngestHealthView {\n const key = runtimeKey(domainId, instanceId)\n const nowMs = Date.now()\n const ledger = this.ingestLedgers[key]\n if (ledger) {\n rollIngestWindow(ledger, nowMs, undefined, closed => this.onWindowClosed?.({ domainId, instanceId }, closed))\n }\n\n const inst = this.instances[key]\n const feedState = liveFeedStateOf({\n restartPolicy: inst?.restartPolicy,\n running: !!inst,\n instanceId\n })\n return ingestHealth(ledger, feedState, undefined, nowMs)\n }\n\n /**\n * 도는 인스턴스 전체의 계측(모니터 대시보드용) — **시뮬과 미러를 함께**.\n *\n * 예전에는 시뮬에 계기가 없어 이 목록에서 조용히 빠졌다(계기가 `null` 이라 걸러졌다). 도는 트윈\n * 대부분이 시뮬인 서버에서 그 목록은 「부하가 거의 없다」로 보였다.\n */\n static async allMetrics(domainId?: string): Promise<any[]> {\n /* 도메인 없이 부르면 전 테넌트를 훑는다(내부 모니터용) — 키에서 도메인을 되돌려 각자에게 묻는다. */\n const rows = Object.keys(this.instances)\n .filter(key => !domainId || isOfDomain(key, domainId))\n .map(key => {\n const at = parseRuntimeKey(key)\n return this.metrics(at.domainId, at.instanceId)\n })\n .filter(Boolean)\n if (!rows.length || !domainId) return rows\n // 표시 이름 부여 — 실행중 카드가 id 만 보이지 않도록 공간명을 실어준다(공간 카드와 동일). name=공간명 폴백 spaceId 폴백 instanceId.\n const insts = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n const spaceOf = new Map(insts.map(i => [i.instanceId, i.spaceId]))\n /* 용도 선언도 함께 실어 보낸다 — 화면이 공간 이름으로 벤치를 **추측하지 않게** 한다.\n 추측하면 `loadtest-` 로 이름 지은 운영 트윈에 벤치 딱지가 붙는다. */\n const purposeOf = new Map(insts.map(i => [i.instanceId, i.purpose]))\n const nameOf = new Map((await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })).map(s => [s.spaceId, s.name]))\n for (const r of rows) {\n const sp = spaceOf.get(r.instanceId)\n r.spaceId = sp\n r.purpose = purposeOf.get(r.instanceId)\n r.name = (sp && nameOf.get(sp)) || sp || r.instanceId\n }\n return rows\n }\n\n /*\n * `buildForecastKernel` 은 **사라졌다**(통합 P3, 2026-08-01).\n *\n * 라이브가 `StateProjector` 였을 때는 커널이 없어서, 예측하려면 관측 스냅샷 + 저널의 오더 원값으로\n * **일회용 커널을 세워야** 했다. 이제 라이브 인스턴스가 곧 커널이므로(`startLive`) 그 자리에서\n * `fork` 하면 된다 — `TwinEngine.kernel(id)` 가 sim·live 둘 다 돌려준다.\n *\n * (오더 원값을 저널에서 되찾던 이유도 사라졌다 — 상태가 requested·fulfilled·lines 를 지킨다.)\n */\n\n /**\n * 예측용 커널을 **임의 시각 T 기준**으로 재구성 — 과거-vantage 예측(백테스트)·\"그때 서서 본 미래\".\n * recover(untilTime)로 T 시점 상태를, T 이하 오더 관측을 모아 hydrate → monteCarloForecast 가 T 에서 앞으로 실행한다.\n * sim/live 무관(저널 기반 재구성). untilTime 생략 시 최신. 도메인 스코프(reg·journal 조회가 domainId).\n */\n static async buildForecastKernelAt(domainId: string, instanceId: string, untilTime?: string): Promise<any | null> {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) return null\n const Kernel = kernelFor(reg.kind)\n const k = new Kernel(domainId, undefined, this.productionSpecOf(reg.model as TwinModelDef))\n k.loadTwinModel(reg.model as TwinModelDef)\n this.applyOperations(k, reg.model, instanceId) // 예측도 같은 명세로 굴러야 한다(화면과 다른 숫자 금지)\n await this.installEstimators(k, domainId, instanceId, reg.model) // 예측은 기다린다 — 실측을 놓치면 예측이 상수로 계산된다\n const state = await this.recover(domainId, instanceId, undefined, untilTime).catch(() => null)\n if (!state) return null\n const cutoff = untilTime != null ? Date.parse(untilTime) : Infinity\n /*\n * journal-fold: 오더의 마지막 상태는 그 오더에 일어난 사실들을 접어야 나온다.\n *\n * **없어질 조건** — 지금 이 읽기에는 상한이 없고 `eventType` 에 인덱스도 없다. 그래서 저널이 큰\n * 트윈에서는 이 한 번이 그 트윈의 저널 전체 주사다. 오더 상태를 따로 접어 둔 표(투영)를 두거나,\n * `(domain, instanceId, eventType, revision)` 인덱스를 붙이고 커서를 넣으면 이 예외는 사라진다.\n * 시각 상한(`cutoff`)을 SQL 로 내려도 절반은 준다.\n */\n const rows = await getRepository(TwinEvent).find({ where: { domain: { id: domainId }, instanceId, eventType: OP_EVENT.order }, order: { revision: 'ASC' } })\n const latest = new Map<string, any>()\n for (const r of rows) {\n if (Number.isFinite(cutoff) && (r.eventTime?.getTime() ?? NaN) > cutoff) continue\n const d = (r.payload as any)?.data\n if (d?.orderId) latest.set(d.orderId, d)\n }\n k.hydrateObserved(state, [...latest.values()])\n return k\n }\n\n /** 현재 전체 스냅샷 — 라이브 우선, 없으면 저널 복구 캐시. */\n static snapshot(domainId: string, id: string): any {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst?.mode === 'live' && inst.projector) {\n /* live: **커널이 주목 신호를 스스로 낸다**(관측 모드) — 호스트가 덧붙이던 withLiveAttentions 는\n * 필요 없다. OEE 만 호스트가 채운다: 원 시스템이 시간 누적을 보내 주지 않아 상태 전이를 적분해\n * 만드는 값이라 커널이 대신할 수 없다(적합성 하네스의 유일한 예외). */\n const st = inst.projector.snapshot()\n return inst.oee ? withLiveOee(st, inst.oee) : st\n }\n return inst?.runtime?.resync() ?? this.recovered[runtimeKey(domainId, id)]\n }\n}\n"]}
1
+ {"version":3,"file":"twin-engine.js","sourceRoot":"","sources":["../../server/engine/twin-engine.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * TwinEngine — operato-twin 커널 인스턴스를 things-factory 위에서 호스팅.\n * integration-base 의 ScenarioEngine 패턴 미러: 메모리 인스턴스 맵 + 백그라운드 tick + pubsub 상태 발행.\n *\n * 커널(zero-dep, ESM+CJS 이중배포)은 CJS require 로 로드(Node 20 CommonJS 소비 — require(ESM) 회피). (vocabulary-guard: allow — Node 런타임 버전 표기)\n * 커널은 결정적 논리 연산 코어 — 이 host 가 전송(pubsub)·영속(TypeORM)·스케줄(tick)·복구(replay)만 얇게 래핑.\n * (설계 SoT: operato-twin/design/integration/things-factory-host.md)\n */\n\nimport { twinLog, twinWarn, twinError } from './log.js'\nimport { pubsub, getRepository, Domain } from '@things-factory/shell'\n/* 저널을 자를 조건은 SQL 이 안다 — 관용구만 쓴다(원시 SQL 은 5개 드라이버에서 갈라진다). */\nimport { And, IsNull, LessThanOrEqual, MoreThan } from 'typeorm'\nimport { cacheService } from '@things-factory/cache-service'\n\nimport type { ReducerCheckpoint } from '@operato/twin-kernel'\nimport type { OeeCheckpoint } from './oee-accumulator.js'\nimport { TwinEvent } from '../service/twin-event/twin-event.js'\nimport { twinEventKeys } from '../service/twin-event/twin-event-keys.js'\nimport { planLiveContinuity, planWarmStart, unwrapState } from './warm-start.js'\nimport { applyDeclarationLayers } from './local-declarations.js'\nimport { isOfDomain, parseRuntimeKey, runtimeKey } from './runtime-key.js'\nimport { routeCommand } from './command-routing.js'\nimport { TwinInstance } from '../service/twin-instance/twin-instance.js'\n/* 자극의 집은 원본이다(ADR-0029) — 그 행을 읽고 쓴다. */\nimport { TwinReference } from '../service/reference/twin-reference.js'\nimport { TwinStructure } from '../service/twin-structure/twin-structure.js'\nimport { TwinSpace } from '../service/twin-space/twin-space.js'\nimport { utcOffsetOf } from '../service/reference/reference-master.js'\nimport { TwinSpaceRepresentation } from '../service/twin-space/twin-space-representation.js'\nimport { TwinSpaceArea } from '../service/twin-space/twin-space-area.js'\nimport { TwinArea } from '../service/twin-space/twin-area.js'\nimport { masterToTwin, type ReferenceMaster } from '../service/reference/reference-master.js'\nimport { resolveIngestSpace } from '../service/reference/ingest-space.js'\nimport { type IngestWarning, describeWarnings, unresolvedReference, projectionFailed, structureAdopted, generationWithoutTimeZone } from '../service/reference/reference-master.js'\nimport { projectStructure } from '../service/twin-model/project-structure.js'\nimport { buildTravelEstimator, chainEstimators } from './travel-estimator.js'\nimport { buildMeasuredEstimator } from './measured-estimator.js'\nimport { buildYieldEstimator } from './measured-yield.js'\nimport { planStimulus, withStimulus } from './declared-stimulus.js'\nimport { readRestartPolicy, type RestartPolicy } from './restart-policy.js'\nimport { describeModelBasis, type ModelBasis } from './model-basis.js'\nimport { computeTwinKpi } from './kpi-query.js'\nimport { createHash } from 'node:crypto'\n\nimport { buildEntityDeltas } from '@things-factory/headless-twin/dist-shared/entity-delta.js'\nimport { fleetLoad, judgeCycle, loadSummary, newLoadMeter, recordFork, recordPhase, slowTickMessage, type LoadMeter, type LoadPhase } from './load-meter.js'\nimport { loopLag } from './loop-lag.js'\nimport { touchedItemKeys } from '@things-factory/headless-twin/dist-shared/touched-items.js'\nimport { diffStructures, type StructureDiff } from './structure-diff.js'\nimport { OeeAccumulator, withLiveOee } from './oee-accumulator.js'\nimport { withLiveAttentions } from './live-attentions.js'\nimport { digestAttentions, mergeLensAttentions } from './attention-digest.js'\n\nimport { liveFeedStateOf } from './live-feed-registry.js'\nimport {\n ingestHealth,\n newIngestLedger,\n recordIngest,\n recordReadFailure,\n clearCursorStall,\n clearReadFailure,\n recordCursorStall,\n rollIngestWindow,\n /* 별칭 — 같은 이름의 정적 메서드와 헷갈리지 않게(그 메서드가 이것을 부른다). */\n recordJournalWrite as recordLedgerWrite,\n type IngestHealthView,\n type IngestLedger,\n type IngestWindow\n} from './ingest-health.js'\nimport { EMS_PROPERTY } from '@operato/twin-kernel'\nimport type { TwinKernel, TwinModelDef, StructureShift, SubscriptionMessage, TwinRuntime as TwinRuntimeType, CanonicalEnvelope } from '@operato/twin-kernel'\n\n/* 커널 런타임 로드 — CJS 번들(dist-cjs). 타입은 위 import type 로. replay = 이벤트열→상태 재구성(복구·시간여행). */\nconst { WmsKernel, YmsKernel, MesKernel, EmsKernel, TwinRuntime, StateProjector, replay, replayFrom, replayWithCheckpoint, replaySegments, readBoardLocations, readBoardEquipment, DOMAIN_CATALOG, OP_EVENT, validateScenario } = require('@operato/twin-kernel')\n\nconst KERNELS: Record<string, any> = { wms: WmsKernel, yms: YmsKernel, mes: MesKernel, ems: EmsKernel }\n\n/**\n * 시각축을 구할 때 한 번에 띄우는 트윈 수.\n *\n * 트윈마다 왕복이 둘이라, 공간에 트윈이 수백이면 동시 왕복도 수백이 된다 — 커넥션 풀이 마르면 이\n * 함수 하나 때문에 다른 질의가 줄을 선다. 20이면 왕복 40개로 지연은 감추면서 풀은 남는다.\n */\nconst TIME_RANGE_FANOUT = 20\n\n/**\n * DB 가 준 시각을 epoch ms 로 — **모양이 드라이버마다 다르다.**\n *\n * 집계(MIN/MAX)의 반환은 드라이버가 정한다: sqlite 는 문자열, pg·mysql·mssql 은 `Date`. 엔티티\n * 하이드레이션을 건너뛰면 TypeORM 의 날짜 변환도 함께 건너뛰므로 받는 쪽에서 한 번 정규화한다.\n *\n * ── 시간대를 잃지 않는다 (시험이 잡았다) ────────────────────────────────────\n * 처음에 `Date.parse(String(v))` 로 두었더니 **9시간이 밀렸다.** sqlite 는 UTC 로 저장한 값을\n * `2026-01-15 09:00:00.000` 처럼 **시간대 표시 없이** 돌려주는데, 그 형태를 `Date.parse` 는 **로컬\n * 시각**으로 읽는다(여기가 KST 라 UTC 00:00 이 됐다). 원래 코드가 이 함정을 피한 것은 TypeORM 이\n * 하이드레이션에서 먼저 `Date` 로 바꿔 줬기 때문이다 — 그 단계를 건너뛴 대가를 여기서 치른다.\n *\n * 그래서 시간대 표시가 **없는 문자열은 UTC 로 읽는다**(TypeORM 이 UTC 로 적으므로). 표시가 있으면\n * 그대로 믿고, `Date` 는 손대지 않는다.\n *\n * 읽을 수 없는 값은 **없음(`null`)** 이다 — 0 으로 떨어뜨리면 1970년이 시각축의 시작이 된다.\n */\nfunction parseTime(v: unknown): number | null {\n if (v == null) return null\n if (v instanceof Date) return Number.isFinite(v.getTime()) ? v.getTime() : null\n\n const s = String(v).trim()\n if (!s) return null\n /* 끝에 `Z` 나 `±hh:mm` 이 붙어 있으면 시간대를 아는 문자열이다 — 그대로 믿는다. */\n const zoned = /(?:Z|[+-]\\d{2}:?\\d{2})$/.test(s)\n const t = Date.parse(zoned ? s : `${s.replace(' ', 'T')}Z`)\n return Number.isFinite(t) ? t : null\n}\n\n/**\n * 종류 문자열 → 커널. **모르는 값이면 오류를 낸다.**\n *\n * 예전에는 표를 찾고 없으면 WmsKernel 로 떨어졌다. `kind` 는 검증 없는 자유 문자열(`@Arg('kind') kind: string`)\n * 이라 오타 하나·대소문자 하나로 야드/생산 트윈이 **조용히 창고 커널로 돌았다.** 오류가 없으니 화면에는\n * 트윈이 정상으로 보이고, 안에서 도는 규칙만 다른 도메인의 것이다. 예측 경로가 가장 나쁘다 —\n * 야드의 미래를 창고 규칙으로 실행해 놓고 숫자만 뜬다.\n *\n * 틀린 공장을 조용히 띄우는 것보다 뜨지 않는 편이 낫다.\n */\nfunction kernelFor(kind: string): any {\n const K = KERNELS[kind]\n if (!K) throw new Error(`unknown twin kind \"${kind}\" — expected one of ${Object.keys(KERNELS).join(' | ')}`)\n return K\n}\n\n/** `observe()` 를 갖지 않은 커널을 만난 적이 있는가 — 경고를 한 번만 낸다(틱마다 쏟지 않는다). */\nlet observeUnavailableWarned = false\n\n/**\n * **이 커널의 진실이 원본에서 온다고 선언한다** — 그리고 선언이 닿지 않았으면 말한다.\n *\n * ── 무엇이 틀렸나 (2026-08-21) ──────────────────────────────────────────────\n * 예전에는 `kernel.observe?.()` 였다. 옵셔널 호출이라 **메서드가 없으면 조용히 아무것도 하지 않는다.**\n * 설치된 커널 0.7.39 에는 그 메서드가 없으므로, 지금 배포본에서는 미러가 관측 구동으로 선언되지\n * 않는다 — 그런데 코드를 읽으면 선언한 것처럼 보인다.\n *\n * 그 차이가 실제 거동을 가른다: 관측 구동은 원본의 빈틈을 받아들이고 세지만, 시뮬로 오인된 미러는\n * **멈춘다.** 즉 「관용이 켜진 줄 알았는데 안 켜져 있다」가 조용히 지나가고, 장애가 났을 때 원인이\n * 커널에 있는 것처럼 보인다 — 원인은 버전이다.\n *\n * 그래서 옵셔널 호출을 없애고, 없으면 **한 번 경고한다.** 커널이 배포되면 이 경고는 사라진다.\n */\nfunction declareObserved(kernel: any, what: string): void {\n if (typeof kernel?.observe === 'function') {\n kernel.observe()\n return\n }\n if (observeUnavailableWarned) return\n observeUnavailableWarned = true\n twinWarn(\n `[twin-engine] ${what}: kernel has no observe() — this mirror is not declared observation-driven. ` +\n 'Source gaps will stop it instead of being tolerated and counted. Deploy a kernel that provides observe().'\n )\n}\n\n/* 라이브 처리량 계측(모니터) — 유입/브로드캐스팅/저널률·백로그. 실 동기 인터페이스 부하를 읽는 일급 지표. */\ninterface TwinMetrics {\n ingestedTotal: number // 누적 유입 이벤트\n broadcastTotal: number // 누적 브로드캐스팅 횟수\n journaledTotal: number // 누적 저널 기록 이벤트\n ingestRate: number // 최근 유입률(ev/s)\n broadcastRate: number // 최근 브로드캐스팅률(회/s)\n journalRate: number // 최근 저널률(ev/s)\n /**\n * **지금 대기 중인** 저널 건수 — 아직 DB 로 나가지 않은 것.\n *\n * ── 무엇이 틀렸었나 (2026-08-21) ──────────────────────────────────────────\n * 예전에는 「마지막 flush 에서 쓴 건수」를 여기 넣었다. 그런데 200ms 마다 모아 한 문으로 넣는 것은\n * **정상 동작**이다(그렇게 만든 것이 어제 고친 성능 작업이다). 그래서 정상적으로 10건을 쓴 직후\n * 화면에 「밀림 10」 경고가 떴고, 다음 flush 까지 그 값이 남았다 — 큐는 이미 0 인데도.\n *\n * 운영자에게 그것은 「저장이 10건 밀려 있다」로 읽힌다. 거짓 경보는 참 경보를 죽인다.\n *\n * 이제 이 값은 **지금 남아 있는 것**이다: 다 나갔으면 0 이고, 정말로 쌓이는 중이면 그 수가 자란다.\n */\n backlog: number\n // 창(window) 집계용 내부 누적\n _accIngest: number\n _accBroadcast: number\n _accJournal: number\n _windowStartMs: number\n}\n\n/*\n * 재기동 정책은 **선언이고 기본값이 없다** — 정의·판정은 `engine/restart-policy.ts` 가 든다(ADR-0029 §2).\n *\n * 예전에는 여기에 `DEFAULT_REALITY_MODE = 'sim-experiment'` 가 있었고, 미선언이 조용히 **저널 초기화**로\n * 떨어졌다. 그 관용은 값이 하나 어긋나는 순간 이력을 지우는 길이 된다 — 그래서 없앴다.\n */\nexport type { RestartPolicy } from './restart-policy.js'\n\n/* 인메모리 라이브 런타임 홀더(영속 엔티티 TwinInstance 와 구분). */\ninterface InstanceRuntime {\n /** 부하 계기판 — 작업별 소요. 시뮬·라이브 모두 붙는다(누가 루프를 점유하는지 보려면 둘 다 필요하다). */\n load?: LoadMeter\n /** 현실 출처 선언(§0 프레임 ①). 부팅 거동(reset/resume/resync)의 근거. */\n restartPolicy?: RestartPolicy\n id: string\n domainId: string\n domain?: any // 라이브 바인딩(data 채널)용 Domain 객체(subdomain 필터). start 시 비동기 해석.\n runtime?: TwinRuntimeType // sim: 커널 런타임(tick/subscribe/dispatch). live 는 projector 사용.\n kernel?: any // sim: ForecastTwin(fork/getSnapshot/tick/scenario). live 미사용.\n mode?: 'sim' | 'live' // 상태 드라이버 — sim=커널 tick / live=projector 미러(face2-inbound-live). 미지정=sim.\n /** 이 트윈이 선 현장 — 같은 현장의 트윈끼리 서로의 설비 상태를 읽을 수 있게 하는 열쇠. */\n spaceId?: string\n /**\n * live 의 상태 접근 어댑터 — 이제 **관측 모드 커널**을 가리킨다(`kernel` 과 같은 것).\n * 이름은 소비처 호환으로 남았고, P3 에서 커널 어휘로 정리하면 사라진다.\n */\n projector?: any\n oee?: OeeAccumulator // live: OEE 계산 층(이벤트 누적 → equipment payload 보강). sim 은 커널이 계산.\n unsub: () => void\n /**\n * 방금 인입한 봉투들 — 커널이 그것을 재방출할 때 **저널에 두 번 적지 않기** 위한 표시.\n * 라이브만 쓴다(sim 은 커널이 스스로 낸 것만 흘린다). 약한 참조라 따로 비울 것이 없다.\n */\n applying?: WeakSet<object>\n timer?: any\n /** 엔티티별 마지막 발행 시그니처 — 값이 바뀐 엔티티만 재발행(무변화 반복 push 방지). */\n entitySigs?: Map<string, string>\n /** live 브로드캐스팅 병합(ingest-scale §4.4) — ingest 마다 브로드캐스팅하지 않고 dirty 표시 → coalescer tick 이 주기 브로드캐스팅. */\n dirty?: boolean\n /**\n * 이 창에 **건드린 물품 태그** — 브로드캐스팅이 그것만 만든다.\n *\n * `undefined` 는 「말할 수 없다」다(낯선 사건이 하나라도 왔다) → 전부 만든다. 빈 집합은 「물품은\n * 하나도 건드리지 않았다」이고, 그 둘은 다른 사실이다.\n */\n dirtyItems?: Set<string>\n /** 다음 브로드캐스팅에서 전부 만들어야 하나 — 주기마다 한 번은 그물로 전부 만든다. */\n fullBroadcastDue?: boolean\n /** 전부 만들기까지 남은 창 수. */\n fullBroadcastCountdown?: number\n /** live 저널 결선 — ingest 이벤트를 모았다가 coalescer tick 에서 배치 기록(이벤트마다 DB write 금지). */\n pendingJournal?: any[]\n /** live 저널 revision 카운터(sim 의 delta revision 대응 — 시간여행·히스토리 노브 앵커). */\n revision?: number\n /** live 처리량 계측(모니터, ④-1). */\n metrics?: TwinMetrics\n}\n\n/**\n * 트윈이 **스스로 멈춘 이유** — 문장이 아니라 코드다.\n *\n * 서버가 만든 영어 문장을 그대로 실으면 한국어·일본어 화면에 그 영어가 뜬다. 이 시스템은 거절 메시지에서\n * 같은 결론에 이르렀다(코드+파라미터를 내고 화면이 옮긴다). `reason` 만은 원문 그대로다 — 커널·런타임이\n * 낸 오류 문구는 옮길 수 있는 어휘가 아니고, 옮기려 들면 원인을 잃는다.\n */\nexport interface StopNote {\n code: 'starved' | 'tick-failed'\n params: Record<string, string | number>\n}\n\nexport class TwinEngine {\n /*\n * 기동 중인 런타임 — **키는 `runtimeKey(domainId, instanceId)`** 다(`runtime-key.ts` 에 이유).\n *\n * 예전엔 `instanceId` 하나로 키를 잡았다. 그런데 정체성은 `(domain, instanceId)` 이고 DB 유일성도\n * 그쪽이라, 두 테넌트가 같은 id 를 쓰면(레퍼런스 경로가 소스 이름을 id 로 쓴다) 한 자리를 다퉜다.\n * **엔진 밖에서 이 맵을 직접 색인하지 않는다** — `owns`·`runtime`·`kernel` 같은 접근자를 쓴다.\n */\n static instances: Record<string, InstanceRuntime> = {}\n /** 라이브 런타임이 없을 때(복구 후 미기동) 저널에서 재구성한 상태 캐시. */\n /** 웜스타트 씨앗 — `instances` 와 **같은 키**(겹치면 남의 스냅샷으로 재고가 섞인다). */\n static recovered: Record<string, any> = {}\n static TICK_MS = 1000\n\n /*\n * ── 굶김 안전망 (2026-08-14) ──────────────────────────────────────────────\n * 시뮬 틱은 **메인 이벤트 루프**에서 돈다. 그래서 한 트윈의 틱이 길어지면 그 시간만큼 호스트 전체가\n * 멈춘다 — HTTP·구독·다른 트윈의 틱까지. 실측으로 `order-check` 의 틱 하나가 34.9초였고, 그 사이\n * 구독자가 아무것도 빼내지 못해 pubsub 이 넘쳐 프로세스가 죽었다.\n *\n * 브로드캐스팅 반복은 걷어냈지만(`flushLiveBroadcasts` 로 병합) **커널 틱 자체는 여전히 메인 루프에 있다.**\n * 근본 해결은 분산이고 그것은 이연됐다 — 그때까지의 안전망이 이 셋이다.\n *\n * 판정을 예산(500ms)이 아니라 **굶김 문턱**으로 따로 둔다: 조금 느린 트윈은 계기판이 말하게 두고\n * (경고), 호스트를 굶기는 트윈만 멈춘다. 한 번으로 멈추지 않는다 — 웜스타트 직후의 첫 틱은 원래\n * 무겁다(복구한 상태를 처음 접는다). **연속**으로 이어질 때가 구조적으로 느린 것이다.\n */\n /*\n * ── 틱을 **한 순간에 몰지 않는다** (2026-08-21 실측) ────────────────────────\n * 트윈마다 `setInterval(TICK_MS)` 를 부팅 때 나란히 세우면, 스무 개가 **같은 밀리초에** 깨어난다.\n * 각자의 틱이 짧아도(실측: 물품 2,400 개에서 0.23ms) 그 순간에는 스무 개가 한 줄로 붙어 실행되고,\n * 그 사이 도착한 HTTP 요청은 전부 뒤에서 기다린다. 초당 한 번의 정체가 「누를 때마다 걸린다」로\n * 나타나는 자리다.\n *\n * 그래서 첫 발화만 간격 안에서 **고르게 흩는다** — 총 작업량은 같고 한 순간의 최대치만 낮아진다.\n * 트윈이 간격보다 많아지면 다시 겹치므로, 그때는 이 흩기가 아니라 분산이 답이다(이연됨).\n */\n /** 부팅 때 트윈 하나를 되살린 뒤 루프를 비워 주는 시간(ms) — 그 사이 도착한 요청이 처리된다. */\n static BOOT_YIELD_MS = 25\n private static tickPhase = 0\n /**\n * 흩어진 첫 발화 뒤 주기 틱. **핸들은 항상 진짜 타이머**다 — 정지하는 쪽이 `clearInterval(inst.timer)`\n * 하나로 끝내야 하므로, 첫 발화 전에는 그 `setTimeout` 을, 이후에는 `setInterval` 을 같은 자리에 둔다\n * (감싼 객체를 주면 `clearInterval` 이 아무 일도 하지 않고 트윈이 멈추지 않는다 — 조용한 결함이 된다).\n */\n private static startTickTimer(fn: () => void, hold: (t: any) => void): any {\n const spread = Math.max(1, Math.round(this.TICK_MS / 20))\n const offset = (this.tickPhase = (this.tickPhase + spread) % this.TICK_MS)\n const first = setTimeout(() => {\n const interval = setInterval(fn, this.TICK_MS)\n if (typeof interval?.unref === 'function') interval.unref()\n hold(interval) // 정지 경로가 지울 대상을 바꿔 준다\n fn()\n }, offset)\n if (typeof first?.unref === 'function') first.unref()\n return first\n }\n\n /** 굶김 문턱 — 틱 간격의 배수(1초 간격이면 5초). 이 시간만큼 호스트가 멈춘다. */\n static STARVE_FACTOR = 5\n /** 연속 몇 번이면 멈추나 — 3번이면 15초를 굶긴 셈이고, 그건 우연이 아니다. */\n static STARVE_STREAK = 3\n private static starveStreak = new Map<string, number>()\n /**\n * 왜 멈췄나 — **화면이 그대로 말할 수 있게.** 스스로 멈춘 트윈이 이유 없이 「정지」로만 보이면\n * 사람은 자기가 멈춘 줄 안다. 메모리에만 둔다(재기동하면 사라진다 — 그때는 「모른다」가 사실이다).\n */\n private static stopNotes = new Map<string, StopNote>()\n\n /* 최신 스냅샷 영속(warm-start) — 재기동 시 저널 fold-from-0 replay 대신 마지막 라이브 스냅샷으로 복원.\n * 프레임워크 공통 cache-service(@things-factory/cache-service) 재사용(재발명 금지, framework-leverage §4).\n * 저널은 그대로 진실(시간여행/history replay 무변경) — 캐시는 display-only 웜스타트 최적화. */\n static SNAPSHOT_CACHE_ID = 'twin-snapshot'\n /*\n * ── 재개점 **사슬** — 과거를 물었을 때 목표 직전에서 접기 위해 (2026-08-18) ──\n *\n * 최신 재개점 하나로는 시간여행을 도울 수 없다: 그것은 언제나 목표보다 **뒤**에 있다. 그래서 지점을\n * 여러 개 남긴다. 다만 그것들은 각각 상태 전체를 들고 있어 무겁다 — 한 행에 몰아 넣으면 거대한\n * JSON 이 되므로 **지점마다 따로 두고 색인을 둔다**(cache-service 는 해시 키 조회라 열거가 안 된다).\n *\n * 간격은 리비전 눈금으로 잡는다(`CHAIN_STRIDE`): 눈금을 넘을 때만 한 지점을 남기므로, 저널이 빠르게\n * 자라는 트윈에서도 지점 수가 폭발하지 않는다. 오래된 것부터 버리고 최근 `CHAIN_KEEP` 개만 든다 —\n * 과거로 깊이 갈수록 지점이 없어 0부터 접는 것은 **알려진 한계**다(무한 보관보다 정직하다).\n */\n static CHAIN_CACHE_ID = 'twin-fold-chain'\n static CHAIN_INDEX_CACHE_ID = 'twin-fold-chain-index'\n static CHAIN_STRIDE = 5000 // 리비전 눈금 — 이 간격을 넘을 때만 한 지점을 남긴다\n static CHAIN_KEEP = 5 // 최근 몇 지점을 들고 있나(그보다 과거는 0부터 접는다)\n static SNAPSHOT_TTL_S = 7 * 24 * 3600 // 7일 — 정상 다운타임 생존, 만료 시 저널 replay 폴백\n static CHECKPOINT_MS = 20000 // 체크포인트 주기(핫 브로드캐스트 경로와 분리, O(state) 스로틀)\n /**\n * **저널 보존 — 지우는 것은 선언이 있을 때만 한다.**\n *\n * ── 왜 필요한가 (2026-08-22 실측) ─────────────────────────────────────────\n * 개발 저널이 시간당 **581,794행 · 0.85GB** 로 자랐다(하루 20GB). 데모 MES 트윈 셋이 전체의 **97%**\n * 를 만들고 지우는 것이 없었다. 오늘 고친 것들은 「그 크기에서도 질의가 빠르게」이고, **크기 자체를\n * 줄이는 것은 아무것도 없었다.** 그러면 며칠마다 같은 자리로 돌아온다.\n *\n * ── 그런데 저널을 지우는 것은 사실을 잃는 일이다 ──────────────────────────\n * 그래서 세 규율을 지킨다.\n *\n * ① **선언이 없으면 아무것도 지우지 않는다.** 기본값은 없음이다 — 조용히 지우는 편이 조용히 쌓는\n * 것보다 나쁘다. 지우는 것은 사람이 정한다.\n * ② **체크포인트가 대신할 수 있는 만큼만.** 스냅샷이 없거나 그 리비전을 넘는 자리는 건드리지 않는다.\n * 주석이 「만료 시 저널 replay 폴백」이라고 적어 둔 그대로 — 스냅샷이 사라지면 저널이 **유일한**\n * 복구 수단이므로, 둘을 함께 잃으면 그 트윈의 상태는 되돌릴 수 없다.\n * ③ **지운 것을 말한다.** 몇 건을 어느 시각까지 지웠는지 로그에 남긴다. 조용히 줄어든 저널은\n * 「없었던 일」과 구별되지 않는다.\n *\n * 그리고 보존 기간은 **스냅샷 TTL(7일)보다 짧을 수 없다.** 더 짧으면 스냅샷이 살아 있는데 그것이\n * 가리키는 앞쪽 저널이 없는 구간이 생기고, 시간여행·계보 추적이 그 구간에서 조용히 빈다.\n */\n static JOURNAL_RETENTION_DAYS?: number = undefined\n /**\n * **도메인마다 다른 보존 기간을 앱이 답한다** — 엔진은 그 값이 어디서 오는지 모른다.\n *\n * 보존 기간은 테넌트의 정책이다: 한 고객은 30일이 필요하고 다른 고객은 7일이면 된다. 그런데 엔진이\n * `Setting` 을 읽게 만들면 **엔진이 화면 관심사를 알게 된다** — 방향이 거꾸로다(엔진은 커널의 호스트이고\n * 그 위에 어떤 화면이 있는지 몰라야 한다).\n *\n * 그래서 시임을 둔다. 앱이 이 함수를 심고, 그 안에서 `Setting` 이든 다른 무엇이든 읽는다. 심지 않으면\n * `JOURNAL_RETENTION_DAYS`(설정 파일에서 온 프로세스 기본값)가 답한다.\n *\n * `undefined` 를 돌려주면 **그 도메인은 지우지 않는다** — 「모른다」를 「지워도 된다」로 읽지 않는다.\n */\n static retentionDaysOf?: (domainId: string) => Promise<number | undefined>\n static RETENTION_SWEEP_MS = 10 * 60 * 1000 // 10분마다 한 번 — 지우는 일은 급하지 않다\n private static retentionTimer?: any\n private static checkpointTimer?: any\n\n /** 최신 스냅샷을 cache-service 에 체크포인트(도메인+instanceId 키). display-only·비차단·오류흡수. */\n static async persistSnapshot(domainId: string, instanceId: string): Promise<void> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n if (!inst) return\n /*\n * **봉투가 아니라 상태를 저장한다.** `snapshot()` 은 시뮬에서 `runtime.resync()` 봉투를 주는데,\n * 그것을 다시 `{revision, state}` 로 감싸 넣어 왔다 → 꺼낸 값에 축이 하나도 없어 웜스타트가\n * 조용히 넘어갔다(저널에 수천 건이 있어도 트윈이 빈 채로 떴다).\n */\n const state = unwrapState(this.snapshot(domainId, instanceId))\n if (!state) return\n /*\n * ── **아무것도 듣지 못한 것을 「비었다」로 적지 않는다** (2026-08-24 실측) ────\n *\n * 미러가 재기동하면 관측 축(재고·오더·작업)을 들고 오지 않는다(`startLive` 가 되찾은 상태를\n * 버린다 — 「다음 계측이 정정한다」는 전제). 그런데 원본이 **커서 증분**으로 말하는 현장에서는 그\n * 정정이 오지 않는다: 커서가 따라잡힌 뒤 원본이 변하지 않으면 미러는 영구히 빈 채다.\n *\n * 그 상태에서 이 함수가 돌면 **빈 상태를 좋은 스냅샷 위에 덮는다.** 그래서 손실이 영구화됐다:\n *\n * 저장돼 있던 것 rev 221,884 · nowTime 2026-04-15 · items 741 · orders 2,780 · tasks 6,353\n * 덮으려던 것 같은 키 · nowTime 2026-01-01 · 전부 0\n *\n * 리비전으로는 막을 수 없다 — 저널 줄 번호는 관측이 없어도 계속 자란다. 막는 기준은 **「들은 것이\n * 있나」**다. 유입이 한 건도 없었다면 이 빈 상태는 **원본이 「비었다」고 말한 것이 아니라 우리가\n * 아무것도 못 들은 것**이고, 그 둘을 같은 값으로 적으면 「모름」이 「없음」이 된다.\n *\n * 원본이 실제로 「다 비었다」고 말한 경우는 막지 않는다 — 그때는 유입이 있었으므로 이 문을 지난다.\n *\n * 그리고 **거절을 말한다**: 조용히 거절하면 왜 체크포인트가 낡아 가는지 아무도 모른다.\n */\n if (!(inst.metrics?.ingestedTotal > 0)) {\n const observed = (s: any) => (s?.items?.length ?? 0) + (s?.orders?.length ?? 0) + (s?.tasks?.length ?? 0)\n if (observed(state) === 0) {\n const prev = await this.loadSnapshot(domainId, instanceId).catch(() => null)\n const had = observed(prev?.state)\n if (had > 0) {\n twinWarn(\n `[twin-engine] \"${instanceId}\": checkpoint refused — this twin has heard nothing since start and its live ` +\n `state is empty, while the stored snapshot holds ${had} observed fact(s) (revision ${prev?.revision}). ` +\n 'Writing the empty state would destroy the only recoverable copy. The journal still holds the truth.'\n )\n return\n }\n }\n }\n const revision = inst.revision ?? state.revision ?? 0\n /* 구조 리비전도 함께 — 읽는 쪽이 \"이 상태가 지금의 공장인가\" 를 가릴 수 있어야 한다. */\n const { structureRev } = await this.tipOf(domainId, instanceId).catch(() => ({ structureRev: null }) as any)\n /*\n * ── **이어 접을 씨앗을 함께 적는다** (2026-08-24) ──────────────────────────\n *\n * 이 함수는 오랫동안 `{revision, state, structureRev}` 만 적었다. 그래서 **재개점을 읽는 쪽은 다\n * 있는데 쓰는 쪽이 없었다**: 조회 경로(`recover`)는 `fold` 가 있으면 꼬리만 접고, 없으면 저널을\n * 0부터 접는다. 실측으로 저장된 스냅샷 34건 전부 `fold` 가 비어 있었고, 저널은 2,960만 줄이었다 —\n * 그래서 재기동·조회마다 처음부터 다시 접었다. 규모 기준(엔티티 10만·품목 100만)에서 이것은\n * 느린 것이 아니라 **못 하는 것**이다.\n *\n * 씨앗은 상태가 대신할 수 없다: 리듀서는 소비처가 보는 값 말고도 든다(부모를 기다리는 담김·집계\n * 중인 수량·담을 줄 몰라 세어 둔 사건). 상태만 되돌리고 뒤를 접으면 0부터 접은 결과와 **조용히**\n * 달라진다. 그 동치는 커널 시험이 증명한다(`observed-checkpoint.test.ts`).\n *\n * 관측 구동이 아니면 씨앗이 없다 — 시뮬은 리듀서를 갖지 않고, 그 상태의 권위는 커널 자신이다.\n * 그때는 `fold` 를 **넣지 않는다**(빈 씨앗을 넣으면 읽는 쪽이 「이어 접을 수 있다」고 잘못 본다).\n */\n const reducer: ReducerCheckpoint | undefined = inst.kernel?.observedCheckpoint?.()\n const fold = reducer && inst.oee ? { reducer, oee: inst.oee.serialize() } : undefined\n await cacheService.setInCache(\n this.SNAPSHOT_CACHE_ID,\n { domainId, instanceId },\n { revision, state, structureRev, ...(fold ? { fold } : {}) },\n this.SNAPSHOT_TTL_S\n )\n }\n\n /**\n * 접기의 **재개점** — 리듀서 내부 상태 전부 + 가동 누적기.\n *\n * 스냅샷(`state`)은 소비처가 보는 값이라 이어 접기의 씨앗이 되지 못한다(보류된 담김·집합·반영 못 한\n * 사건 집계가 없다 — 그 상태로 뒤를 접으면 0부터 접은 결과와 조용히 달라진다). 그래서 씨앗은 따로 든다.\n */\n private static readonly FOLD_NOTE = 'reducer + oee checkpoint — the seed for folding only the tail'\n\n /**\n * 재기동에 쓸 **웜스타트 씨앗**을 만든다 — 상태 + 이어 접을 재개점.\n *\n * ── 왜 이 자리가 생겼나 (2026-08-24) ──────────────────────────────────────\n * 두 호출부가 같은 일을 조금씩 다르게 하고 있었고(겹포장을 한쪽만 벗겼다), 둘 다 **재개점을 버리고**\n * 상태만 들고 갔다. 그래서 저장된 재개점을 읽는 쪽이 다 있는데도 재기동은 매번 저널을 처음부터\n * 접었다(실측: 저널 2,960만 줄).\n *\n * 여기서 하는 일 셋:\n * ① 겹포장을 벗긴다 — 옛 형식으로 저장된 값이 한 번은 반드시 나온다\n * ② **그 공장이 아직 그 공장인지** 심판한다 — 아니면 씨앗을 버린다(아래)\n * ③ 씨앗이 저널 끝보다 앞서 있으면 **그 꼬리만 접어** 끝까지 밀어 둔다\n *\n * ②가 필요한 이유: 재개점은 그때의 보드 위에서 만들어진 것이다. 그 뒤 구조가 바뀌었다면(자리가\n * 빠졌다·설비가 옮겨졌다) 되세운 리듀서는 **지금 없는 자리와 설비를 든다** — 없는 냉장실이 화면에\n * 나오고 그 자리의 판정이 계속 돌아간다. 오류 없이 틀리므로 눈에 띄지 않는다.\n *\n * ③이 필요한 이유: 스냅샷은 체크포인트 주기로 쓰이므로 마지막 주기 이후의 사실은 저널에만 있다.\n * 그것을 빼고 되세우면 그만큼이 조용히 사라진다 — 「모름」을 「없음」으로 적는 것과 같은 부류다.\n * 접는 구간은 **그 틈뿐**이고(저널 전체가 아니다), `recover` 가 그 자리에서 새 재개점을 남겨 준다.\n */\n private static async warmSeedFor(\n domainId: string,\n instanceId: string\n ): Promise<{ revision: number; state: any; fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } } | null> {\n let cached = await this.loadSnapshot(domainId, instanceId).catch(() => null)\n if (!cached?.state) return null\n\n const seedOf = (c: typeof cached) => (c?.fold?.reducer ? { fold: c.fold } : {})\n if (!cached.fold?.reducer) return { revision: cached.revision, state: unwrapState(cached.state) }\n\n const tip = await this.tipOf(domainId, instanceId).catch(() => null)\n if (tip && (cached.structureRev ?? null) !== tip.structureRev) {\n twinLog(\n `[twin-engine] \"${instanceId}\": the stored fold seed is from structure ${cached.structureRev} but the factory is now ` +\n `at ${tip.structureRev} — starting without it (the journal is folded from the beginning instead).`\n )\n return { revision: cached.revision, state: unwrapState(cached.state) }\n }\n\n if (tip && (cached.revision ?? 0) < tip.revision) {\n /*\n * 틈을 접는다 — `recover` 가 이 씨앗으로 **꼬리만** 접고, 끝 지점의 새 재개점을 남긴다.\n * 아직 이 트윈의 런타임이 없으므로 `recover` 는 메모리 대신 저널 경로를 탄다(그것이 여기의 전제다).\n */\n const gap = tip.revision - (cached.revision ?? 0)\n await this.recover(domainId, instanceId).catch(err =>\n twinWarn(`[twin-engine] \"${instanceId}\": could not fold the ${gap} event(s) after the checkpoint — ${err?.message ?? err}`)\n )\n const advanced = await this.loadSnapshot(domainId, instanceId).catch(() => null)\n if (advanced?.state && (advanced.revision ?? 0) > (cached.revision ?? 0)) {\n twinLog(`[twin-engine] \"${instanceId}\": folded ${gap} event(s) after the checkpoint → revision ${advanced.revision}.`)\n cached = advanced\n }\n }\n return { revision: cached.revision, state: unwrapState(cached.state), ...seedOf(cached) }\n }\n\n /** 체크포인트된 최신 스냅샷 로드(없으면 null). getFromCache 는 CacheStore 엔티티를 반환 → 페이로드는 .value. */\n static async loadSnapshot(\n domainId: string,\n instanceId: string\n ): Promise<{ revision: number; state: any; structureRev?: number | null; fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } } | null> {\n const entry = await cacheService.getFromCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId })\n return (entry as any)?.value ?? null\n }\n\n /**\n * 접은 상태를 스냅샷으로 남긴다 — **라이브가 아니어도.**\n *\n * `persistSnapshot` 은 기동 중인 인스턴스에서만 뜬다(메모리가 진실이므로 옳다). 그런데 **멈춘**\n * 트윈을 조회할 때마다 저널을 전량 다시 접고 있었다(23,731건짜리 트윈에서 4.6초). 그 폴드의 결과를\n * 남겨 두면 **처음 한 번만 느리다.**\n *\n * `structureRev` 를 함께 적는다: 이벤트가 하나도 안 늘어도 구조를 갈아치우면(재프로비저닝) 그\n * 상태는 낡은 것이다. 리비전만 보면 새 설비가 없는 옛 상태를 \"지금\" 으로 내게 된다.\n */\n static async saveFoldedSnapshot(\n domainId: string,\n instanceId: string,\n value: { revision: number; state: any; structureRev?: number | null; fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } }\n ): Promise<void> {\n if (!value?.state) return\n await cacheService\n .setInCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId }, value, this.SNAPSHOT_TTL_S)\n .catch((err: any) => twinError(`[twin-engine] snapshot save fail \"${instanceId}\"`, err?.message ?? err))\n }\n\n\n /** 사슬 색인 — 어떤 리비전 지점을 들고 있나(최신순 아님, 오름차순). */\n private static async chainIndex(domainId: string, instanceId: string): Promise<number[]> {\n const entry = await cacheService.getFromCache(this.CHAIN_INDEX_CACHE_ID, { domainId, instanceId }).catch(() => null)\n const revs = (entry as any)?.value?.revisions\n return Array.isArray(revs) ? revs.filter((r: any) => Number.isFinite(r)).sort((a: number, b: number) => a - b) : []\n }\n\n /**\n * 목표 이전의 **가장 가까운 지점**을 고른다 — 없으면 `null`(0부터 접는다).\n *\n * 시각으로 물었으면 그 지점의 마지막 사실 시각이 목표 이내여야 한다(리비전만 보면 목표보다 뒤의\n * 사실이 씨앗에 섞인다). 구조가 바뀐 트윈에서는 쓰지 않는다 — 마디를 건너뛴 씨앗은 그 경계의\n * 판정을 잃는다(그 경우는 0부터 접는 것이 옳다).\n */\n private static async chainSeedFor(\n domainId: string,\n instanceId: string,\n target: { revision?: number; timeMs?: number }\n ): Promise<{ revision: number; eventTime?: string; structureRev?: number | null; fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } } | null> {\n const revs = await this.chainIndex(domainId, instanceId)\n if (!revs.length) return null\n for (const revision of [...revs].reverse()) {\n if (target.revision != null && revision > target.revision) continue\n const entry = await cacheService.getFromCache(this.CHAIN_CACHE_ID, { domainId, instanceId, revision }).catch(() => null)\n const value = (entry as any)?.value\n if (!value?.fold?.reducer) continue\n if (target.timeMs != null) {\n const t = value.eventTime ? Date.parse(String(value.eventTime)) : NaN\n /* 시각을 모르는 지점은 쓰지 않는다 — 목표 이내인지 가릴 수 없다(짐작하지 않는다). */\n if (!Number.isFinite(t) || t > target.timeMs) continue\n }\n return value\n }\n return null\n }\n\n /** 눈금을 넘었으면 한 지점을 남긴다 — 오래된 것은 버린다(색인도 함께 줄인다). */\n private static async keepChainPoint(\n domainId: string,\n instanceId: string,\n /*\n * **보기(state)는 담지 않는다** (2026-08-18 실측으로 고침).\n *\n * 처음에는 상태까지 담았더니 지점 하나가 **11.4 MB** 였다(27만 건 트윈). 사슬이 필요한 것은 씨앗\n * (재개점)뿐이고, 소비처가 보는 값은 그 씨앗에서 다시 만들어진다 — 같은 사실을 두 번 저장하지 않는다.\n */\n value: { revision: number; eventTime?: string; structureRev?: number | null; fold: { reducer: ReducerCheckpoint; oee: OeeCheckpoint } }\n ): Promise<void> {\n const revs = await this.chainIndex(domainId, instanceId)\n const newest = revs.length ? revs[revs.length - 1] : -Infinity\n if (value.revision - newest < this.CHAIN_STRIDE) return // 아직 눈금을 넘지 않았다\n const next = [...revs, value.revision].slice(-this.CHAIN_KEEP)\n const dropped = revs.filter(r => !next.includes(r))\n await cacheService.setInCache(this.CHAIN_CACHE_ID, { domainId, instanceId, revision: value.revision }, value, this.SNAPSHOT_TTL_S)\n await cacheService.setInCache(this.CHAIN_INDEX_CACHE_ID, { domainId, instanceId }, { revisions: next }, this.SNAPSHOT_TTL_S)\n /*\n * 버린 지점은 **색인에서만** 빠진다 — 공용 캐시에 삭제 API 가 없다(`ICacheService` 는 get·set·\n * clearStaleCache 뿐이다). 그래서 값은 TTL(7일)까지 남는다: 아무도 닿지 못하지만 자리는 차지한다.\n * 지금 규모에서 감당할 수 있는 낭비이고, 공용 모듈에 삭제를 여는 것은 다른 소비처까지 함께 볼\n * 일이라 여기서 몰래 하지 않는다 — **알려진 한계로 적어 둔다.**\n */\n if (dropped.length) console.info(`[twin-engine] \"${instanceId}\" fold chain dropped ${dropped.join(', ')} from the index (values expire with the cache TTL).`)\n }\n\n /** 이 트윈 저널의 끝 리비전 · 최신 구조 리비전 — 스냅샷이 지금의 사실인지 가리는 두 값. */\n private static async tipOf(domainId: string, instanceId: string): Promise<{ revision: number; structureRev: number | null }> {\n const [tip, newest] = await Promise.all([\n getRepository(TwinEvent).findOne({ where: { domain: { id: domainId }, instanceId }, order: { revision: 'DESC' } }),\n getRepository(TwinStructure).findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n ])\n return { revision: tip?.revision ?? 0, structureRev: newest?.rev ?? null }\n }\n\n /**\n * **저널을 보존 기간까지만 둔다** — 체크포인트가 대신할 수 있는 만큼만 지운다.\n *\n * 한 인스턴스에서 지우는 조건은 **둘 다** 만족해야 한다.\n *\n * · `createdAt` 이 보존 기간보다 오래됐다 — **행이 쓰인 실제 시각**이 기준이다\n * · `revision` 이 **체크포인트 리비전 이하**다 — 그 앞은 스냅샷이 대신한다\n *\n * ── 왜 `eventTime` 이 아니라 `createdAt` 인가 (2026-08-22 실측으로 고침) ────\n * 처음에 `eventTime` 으로 적었다. 그것은 **트윈의 시계**다 — 시뮬레이션은 자기 시계로 사건을 찍고,\n * 그 시계는 실제 시각과 무관하게 앞서거나 뒤선다. 실측:\n *\n * order-check 가장 늦은 eventTime = 2027-06-08 ← 실제 시각보다 10개월 앞\n * hatio-mx2 2026-01-01 ~ 지금 ← 7개월치를 한 번에 지우게 된다\n *\n * 즉 「7일」이 트윈마다 다른 뜻이 된다: 시계가 앞선 트윈은 영원히 지워지지 않고, 과거부터 찍은 트윈은\n * 거의 전부가 한 번에 지워진다. **보존은 저장 나이의 문제**이고 저장 나이는 실제 시계다.\n *\n * `createdAt` 은 그 행이 DB 에 쓰인 시각이고 1,599만 행 전부 채워져 있다(확인함). 도메인 시각을\n * 정책에 쓰지 않는다 — 그 둘을 섞으면 시뮬과 미러에서 같은 설정이 다르게 동작한다.\n *\n * 스냅샷이 없으면 **그 인스턴스는 건드리지 않는다.** 저널이 유일한 복구 수단인 상태이므로, 지우면\n * 그 트윈의 상태를 되돌릴 수 없다. 「지울 수 없었다」는 사실도 함께 센다 — 조용히 넘기면 「보존이\n * 도는데 왜 안 줄어드나」가 된다.\n *\n * `createdAt` 이 빈 옛 행은 **지우지 않는다**(시각을 모르는 것을 「오래됐다」로 읽지 않는다).\n *\n * 드라이버 다섯을 다 지나야 하므로 raw SQL 을 쓰지 않는다 — 조건 삭제는 쿼리빌더가 이식한다.\n */\n static async pruneJournal(domainId: string): Promise<{ deleted: number; instances: number; skipped: string[] }> {\n /* 도메인의 정책이 먼저다(§`retentionDaysOf`). 없으면 프로세스 기본값. 둘 다 없으면 지우지 않는다. */\n const perDomain = this.retentionDaysOf ? await this.retentionDaysOf(domainId).catch(() => undefined) : undefined\n const days = perDomain ?? this.JOURNAL_RETENTION_DAYS\n if (!days || days <= 0) return { deleted: 0, instances: 0, skipped: [] }\n\n /* 보존 기간은 스냅샷 TTL 보다 짧을 수 없다 — 짧으면 스냅샷이 가리키는 앞쪽이 비는 구간이 생긴다. */\n const minDays = this.SNAPSHOT_TTL_S / 86400\n const effectiveDays = Math.max(days, minDays)\n if (effectiveDays !== days) {\n twinWarn(\n `[twin-engine] journal retention ${days}일은 스냅샷 TTL(${minDays}일)보다 짧다 — ${effectiveDays}일로 올린다 ` +\n '(더 짧으면 스냅샷이 살아 있는데 그것이 가리키는 앞쪽 저널이 없는 구간이 생긴다)'\n )\n }\n const cutoff = new Date(Date.now() - effectiveDays * 86400 * 1000)\n\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n let deleted = 0\n let instances = 0\n const skipped: string[] = []\n\n for (const r of rows) {\n const snap = await this.loadSnapshot(domainId, r.instanceId).catch(() => null)\n const upTo = Number(snap?.revision ?? 0)\n if (!upTo) {\n /* 스냅샷이 없다 — 저널이 유일한 복구 수단이므로 손대지 않는다. */\n skipped.push(r.instanceId)\n continue\n }\n const res = await getRepository(TwinEvent)\n .createQueryBuilder()\n .delete()\n .from(TwinEvent)\n .where('domain_id = :domainId', { domainId })\n .andWhere('instance_id = :instanceId', { instanceId: r.instanceId })\n .andWhere('revision <= :upTo', { upTo })\n .andWhere('created_at IS NOT NULL')\n .andWhere('created_at < :cutoff', { cutoff })\n .execute()\n const n = res.affected ?? 0\n if (n > 0) {\n deleted += n\n instances++\n /* **지운 것을 말한다** — 조용히 줄어든 저널은 「없었던 일」과 구별되지 않는다. */\n twinLog(\n `[twin-engine] journal pruned \"${r.instanceId}\" — ${n}건 (revision ≤ ${upTo} · ${cutoff.toISOString()} 이전). ` +\n '그 앞은 체크포인트가 대신한다.'\n )\n }\n }\n if (skipped.length) {\n twinLog(\n `[twin-engine] journal prune skipped ${skipped.length} instance(s) with no checkpoint — ` +\n `저널이 유일한 복구 수단이라 손대지 않았다: ${skipped.slice(0, 5).join(', ')}${skipped.length > 5 ? ' …' : ''}`\n )\n }\n return { deleted, instances, skipped }\n }\n\n /** 보존 정리 주기 기동(1회) — 선언이 없으면 아무것도 하지 않는다. */\n static startRetentionLoop(domainId: string): void {\n if (this.retentionTimer) return\n /*\n * 걸지 않는 조건: 프로세스 기본값도 없고 **도메인에 물을 길도 없을** 때다. 시임이 심겨 있으면\n * 기본값이 없어도 걸어야 한다 — 그 도메인이 자기 값을 가질 수 있다.\n */\n if (!this.JOURNAL_RETENTION_DAYS && !this.retentionDaysOf) return\n this.retentionTimer = setInterval(() => {\n this.pruneJournal(domainId).catch(err => twinError('[twin-engine] journal prune failed', err?.message ?? err))\n }, this.RETENTION_SWEEP_MS)\n if (typeof this.retentionTimer?.unref === 'function') this.retentionTimer.unref()\n twinLog(\n `[twin-engine] journal retention on — ${this.JOURNAL_RETENTION_DAYS ?? '(도메인 정책)'}일 · ` +\n `${this.RETENTION_SWEEP_MS / 60000}분마다`\n )\n }\n\n /** 체크포인트 루프 기동(1회) — 라이브 인스턴스들의 최신 스냅샷을 주기 영속. */\n static startCheckpointLoop(): void {\n if (this.checkpointTimer) return\n this.checkpointTimer = setInterval(() => {\n for (const [key, inst] of Object.entries(this.instances)) {\n const { instanceId } = parseRuntimeKey(key)\n this.persistSnapshot(inst.domainId, instanceId).catch(err =>\n twinError(`[twin-engine] snapshot checkpoint fail \"${instanceId}\"`, err?.message ?? err)\n )\n }\n }, this.CHECKPOINT_MS)\n if (typeof this.checkpointTimer?.unref === 'function') this.checkpointTimer.unref()\n }\n\n /**\n * 부팅 훅 — DB 에 status='running' 으로 남은 인스턴스를 저널에서 상태 재구성(DB→replay).\n * 라이브 tick 재개(sim 결정적 re-run / live 인제스트 지속)는 후속. 여기선 상태 복원 + 노출.\n */\n static async bootstrap(): Promise<void> {\n /* 부팅부터 잰다 — 사람이 가장 답답한 구간이 여기이고, 그 구간을 재지 않으면 값으로 말할 수 없다. */\n loopLag.start()\n try {\n const repo = getRepository(TwinInstance)\n const rows = await repo.find({ where: { status: 'running' } })\n for (const row of rows) {\n if (!row.domainId || !row.instanceId) continue\n // 웜스타트: 캐시된 최신 스냅샷 우선(O(1) + attentions/OEE 등 라이브 파생상태 보존).\n // 없으면 저널 fold-from-0 replay(진실 폴백 — replay 는 라이브 파생상태를 못 담으므로 캐시가 더 충실).\n const cached = await this.warmSeedFor(row.domainId, row.instanceId).catch(() => null)\n if (cached?.state) {\n this.recovered[runtimeKey(row.domainId, row.instanceId)] = cached\n /*\n * **「웜스타트했다」고 말하지 않는다** — 여기서는 상태를 **찾아 둔 것**뿐이다.\n *\n * 실제 주입은 기동 때 일어나고(`warmStart` 가 그때 무엇을 심었는지 말한다), 미러(live) 트윈은\n * 그 씨앗을 아예 쓰지 않는다(`startLive` 가 버린다). 그런데 이 줄이 「warm-started」라고 말해\n * 로그만 읽으면 심긴 줄 알게 된다 — 실제로 그렇게 읽고 재기동 뒤 지속시간이 사라진 것을\n * 데이터 문제로 오진할 뻔했다.\n */\n twinLog(`[twin-engine] found cached state for \"${row.instanceId}\" → revision ${cached.revision} (seeded at start).`)\n continue\n }\n const state = await this.recover(row.domainId, row.instanceId).catch(() => null)\n if (state) {\n this.recovered[runtimeKey(row.domainId, row.instanceId)] = { revision: state.revision, state }\n twinLog(`[twin-engine] recovered \"${row.instanceId}\" from journal → revision ${state.revision}.`)\n }\n }\n /*\n * 상태만 되찾는 것으로는 **도는 트윈이 되지 않는다** — 런타임까지 되살린다(아래).\n *\n * 되살리기 사이에 **루프를 한 번 비워 준다** (2026-08-21). 웜스타트 하나가 물품 수천 개를 접으므로\n * 스무 개를 연달아 하면 그 시간 내내 HTTP 가 서지 않는다 — 서버는 이미 `Server ready` 를 찍은\n * 뒤라서, 사람에게는 「열렸는데 아무 반응이 없는 화면」으로 보인다. 총 시간은 같고, 그 사이에\n * 도착한 요청이 처리될 틈만 생긴다.\n */\n for (const row of rows) {\n await this.resumeRow(row)\n await new Promise(resolve => setTimeout(resolve, this.BOOT_YIELD_MS))\n }\n this.startCheckpointLoop() // 이후 기동되는 라이브 인스턴스의 최신 스냅샷을 주기 영속\n /*\n * 보존 정리 — **선언이 있을 때만** 돈다(§`JOURNAL_RETENTION_DAYS`). 도메인마다 한 번 건다.\n * 체크포인트 루프 뒤에 두는 이유: 지울 수 있는 경계가 스냅샷이므로, 스냅샷을 남기는 쪽이 먼저\n * 돌아야 첫 정리가 실제로 지울 것을 갖는다.\n */\n for (const domainId of new Set(rows.map(r => r.domainId).filter(Boolean) as string[])) {\n this.startRetentionLoop(domainId)\n }\n } catch (err) {\n twinError('[twin-engine] recovery scan failed', err)\n }\n }\n\n /**\n * 부팅 때 **도는 트윈을 실제로 되살린다** — 「도는 중」이 사실이 되게.\n *\n * ── 무엇이 거짓말이었나 (2026-08-14) ────────────────────────────────────────\n * `bootstrap()` 은 상태만 되찾아 `recovered` 에 담았고, 커널을 세우는 것은 **명시 mutation 뿐**이었다\n * (이 파일 위쪽 주석이 「향후」라고 적어 둔 그 자리다). 그래서 서버를 한 번 재기동하면 등록부는\n * `running` 이라 말하는데 **아무 커널도 돌지 않았다** — 화면은 도는 트윈을, 실제로는 멈춘 트윈을.\n * 미러 트윈에서는 더 나쁘다: 계측이 조용히 끊기고, 사람은 「값이 안 변하네」로 알게 된다.\n *\n * ── 모드를 지어내지 않는다 ──────────────────────────────────────────────────\n * 미러였던 트윈을 시뮬로 되살리면 **없던 움직임을 만들어 낸다**(관측 트윈이 스스로 물건을 옮긴다).\n * 그래서 선언된 `restartPolicy` 그대로 되살린다 — 미러는 관측 구동으로, 시뮬은 시뮬로.\n *\n * ── 되살릴 수 없으면 그렇게 적는다 ──────────────────────────────────────────\n * 실패를 삼키면 등록부가 계속 `running` 이라 말한다 — 우리가 고치려던 그 거짓말이다. 그래서 실패한\n * 행은 `stopped` 로 적고 이유를 남긴다. 「멈췄다」는 사실이고, 「도는 중」은 사실이 아니었다.\n */\n private static async resumeRow(row: TwinInstance): Promise<void> {\n const { domainId, instanceId } = row\n if (!domainId || !instanceId) return\n if (this.instances[runtimeKey(domainId, instanceId)]) return // 이미 세워졌다(데모 시드 등)\n\n /*\n * 벤치 사본은 되살리지 않는다 — 그것은 **누군가 지켜보던 실험**이고, 무인으로 되살아나면 호스트를\n * 그대로 두들긴다(격리 사본의 뜻은 「운영과 섞이지 않는다」이지 「영원히 돈다」가 아니다).\n * 실험은 재기동을 넘기지 못했으므로 등록부도 그렇게 적는다.\n */\n if (row.purpose === 'bench') {\n await this.markStopped(row, 'bench copy — an experiment does not survive a restart unattended')\n return\n }\n\n try {\n /*\n * **선언된 모드로 되살리는 판단은 한 곳에 있다**(`startFromRegistry`) — 2026-08-20.\n *\n * 예전에는 이 자리에서 `resync` 를 갈라 `startLive` 를 불렀다. 그래서 부팅으로 살아난 미러는\n * 관측 구동이었지만 **사람이 화면에서 시작한 미러는 시뮬로 떴다**(그 문에는 갈림이 없었다).\n * 같은 선언이 두 결과를 내지 않도록 갈림을 문 안으로 옮겼다.\n */\n await this.startFromRegistry(domainId, instanceId)\n if (row.restartPolicy === 'resync') {\n /* 계측을 나르는 피드는 커넥터의 것이다 — 레퍼런스 계층이 부팅 훅에서 다시 붙인다\n (`resumeReferenceLiveFeeds`). 여기서 어댑터를 아는 것은 계층을 거꾸로 잇는 것이다. */\n twinLog(`[twin-engine] resumed mirror \"${instanceId}\" — feed reattach is the reference layer's job.`)\n } else {\n twinLog(`[twin-engine] resumed ${row.restartPolicy} \"${instanceId}\".`)\n }\n } catch (err: any) {\n await this.markStopped(row, err?.message ?? 'resume failed')\n }\n }\n\n /** 되살리지 못한 행을 정직하게 적는다 — 「도는 중」이라 말하는 채로 두지 않는다. */\n private static async markStopped(row: TwinInstance, why: string): Promise<void> {\n twinWarn(`[twin-engine] \"${row.instanceId}\" not resumed (${why}) — registry says stopped now.`)\n try {\n await getRepository(TwinInstance).update({ id: row.id }, { status: 'stopped' })\n } catch (e: any) {\n twinError(`[twin-engine] could not mark \"${row.instanceId}\" stopped — registry now lies about it.`, e?.message)\n }\n }\n\n /**\n * 웜스타트 — 기동하는 커널에 **직전 관측 상태**를 주입한다.\n *\n * ── 왜 필요한가 ─────────────────────────────────────────────────────────────\n * `loadTwinModel` 는 **구조만** 싣는다(자리·설비). 상태(무엇이 어디에 얼마나)는 없다. 그래서 재기동한\n * 트윈은 저널에 입고 540건이 남아 있어도 재고가 0 이었고, 화면은 \"보유 중인 것이 없습니다\" 라고\n * 말했다 — 있는 재고를 없다고 하는 셈이다(2026-07-31 hatiolab-wms 실측으로 확인).\n * `bootstrap()` 이 이미 체크포인트 캐시(없으면 저널 replay)로 상태를 복구해 `recovered` 에 담아 두는데,\n * 기동 순간 그걸 **버리고** 있었다. 반만 연결돼 있던 장치를 잇는다.\n *\n * ── 반쪽이던 복구를 마무리한다 (2026-08-05) ─────────────────────────────────\n * 재고는 살아났는데 **진행 중 주문이 통째로 사라진** 화면이 남아 있었다. 씨앗이 자리·물품·설비\n * 셋만 넘겼기 때문이다. 그 근거는 \"스냅샷 오더에 progress 밖에 없다\" 였고, 그때는 맞았다 —\n * 그러나 커널 `OrderState` 가 원값(`requested`·`fulfilled`·`lines`)을 되찾은 뒤에도 이 자리만\n * 그대로 남았다. 오류를 내지 않는 종류라 오래 버텼다.\n *\n * 지금은 **관측 스냅샷 전체**를 넘긴다(오더·작업·사람·자산 포함). 시뮬은 커널 `snapshot()`,\n * 라이브는 `StateProjector` 가 그 일곱 축을 모두 담는다. 무엇을 심을 수 있는지 판정하는 규칙\n * (이행 완료 오더 제외·고아 작업 제외)은 커널에 있고, 호스트가 미리 골라내지 않는다.\n *\n * ── 남은 한계는 숨기지 않고 센다 ────────────────────────────────────────────\n * · 원값이 없는 오더(progress 만 있는 것)는 남은 수량을 알 수 없어 주입하지 않는다. **지어내지 않는\n * 대신 몇 건인지 말한다** — 세지 않으면 \"주문이 없다\" 와 \"주문을 못 심었다\" 가 화면에서 같아진다.\n * · 진행 중 개별 작업의 내부 상태는 관측만으로 완전히 복원되지 않는다(커널이 명시한 한계, 재계획에 맡김).\n *\n * ── 벤치는 시드하지 않는다 ──────────────────────────────────────────────────\n * 부하 벤치는 **새 시작에서 용량을 재는 것**이 목적이라 현재 상태를 주입하면 측정이 오염된다.\n */\n private static warmStart(domainId: string, id: string, kernel: TwinKernel, purpose?: string): void {\n const hydrate = (kernel as any).hydrateObserved\n const plan = planWarmStart(this.recovered[runtimeKey(domainId, id)]?.state, purpose, typeof hydrate === 'function')\n\n if (plan.action === 'skip') {\n if (plan.reason === 'bench') {\n twinLog(`[twin-engine] \"${id}\" is a bench twin — starting empty on purpose (seeding would skew the measurement).`)\n } else if (plan.reason === 'unsupported') {\n twinWarn(\n `[twin-engine] kernel for \"${id}\" cannot be warm-started (no hydrateObserved) — it starts with structure only, so held stock will read as zero.`\n )\n }\n return\n }\n\n hydrate.call(kernel, plan.seed)\n const restored = [\n `${plan.itemCount} item(s)`,\n `${plan.equipmentCount} equipment`,\n `${plan.orderCount} open order(s)`,\n `${plan.taskCount} task(s)`,\n ...(plan.personCount ? [`${plan.personCount} person(s)`] : []),\n ...(plan.assetCount ? [`${plan.assetCount} asset(s)`] : []),\n /* 확인해 둔 신호를 이어받았다는 사실도 말한다 — 잃으면 확인 처리가 다시 빨개지는 것으로 보인다. */\n ...(plan.ackedCount ? [`${plan.ackedCount} acknowledged attention(s)`] : []),\n /* 「언제부터인가」도 말한다 — 잃으면 지속된 조건이 모두 「방금」으로 보인다. */\n ...(plan.attentionSinceCount ? [`${plan.attentionSinceCount} attention start time(s)`] : [])\n ].join(', ')\n twinLog(`[twin-engine] warm-started \"${id}\" — restored ${restored}.`)\n /* 뺀 것은 조용히 넘기지 않는다 — 지어내지 않았다는 사실 자체를 말해야 화면의 빈칸이 읽힌다. */\n if (plan.ordersWithoutDemand > 0) {\n twinWarn(\n `[twin-engine] \"${id}\": ${plan.ordersWithoutDemand} order(s) could not be restored — they carry progress only, ` +\n 'with no requested/fulfilled counts, so the remaining demand is unknown. They are left out rather than guessed.'\n )\n }\n }\n\n /** 트윈 인스턴스 시작 — 커널 생성 + 모델 로드 + 직전 상태 웜스타트 + State 스트림 브리지 + 워커 tick + 레지스트리 영속. */\n /**\n * 공정 명세를 커널에 싣는다 — **시뮬레이션의 시간을 데이터가 말하게 하는 마지막 한 칸.**\n *\n * `model.operations`(마스터 인제스트가 통과시킨 ISA-95 OperationsSegment 명세)를 커널이 소비한다.\n * 없으면 커널 기본 상수로 굴러가고, 커널 `specCoverage()` 가 무엇을 기본값으로 썼는지 보고한다.\n *\n * 커널이 아직 이 API 를 갖지 않은 버전이면(발행 이전) **조용히 넘어가지 않고 경고한다** — 명세를\n * 선언했는데 반영되지 않는 상태를 모르고 지나가면, 예측이 상수로 돌아간 것을 아무도 알 수 없다.\n */\n private static applyOperations(kernel: any, model: any, id: string): void {\n /*\n * 현장이 정한 공정 시간 — 명세 행과 **따로** 싣는다(`declareDurations`).\n *\n * 행이 없는 종류에도 시간을 줄 수 있어야 한다: 실측으로 창고·야드 트윈에는 공정 명세 행이 0개였고,\n * 그 트윈들의 시간은 전부 커널 상수에서 왔다. 행을 지어 만드는 길은 막았다(`label`·`intent` 를\n * 지어내면 능력 계산까지 오염된다) — 그래서 시간만 받는 창구가 커널에 있다.\n */\n const declared = model?.localDurations as Record<string, string> | undefined\n if (declared && Object.keys(declared).length) {\n if (typeof kernel?.declareDurations !== 'function') {\n twinWarn(\n `[twin-engine] \"${id}\": this facility declared ${Object.keys(declared).length} operation duration(s) but the kernel cannot consume them ` +\n '(declareDurations missing — kernel needs publishing). The simulation keeps running on built-in constants, and specCoverage() will keep reporting \"default\".'\n )\n } else {\n try {\n kernel.declareDurations(declared)\n } catch (err: any) {\n /* 커널이 거절한 값은 조용히 넘기지 않는다 — 화면은 「넣었습니다」라고 말한 값이다. */\n twinWarn(`[twin-engine] \"${id}\": declared operation duration rejected by the kernel — ${err?.message ?? err}`)\n }\n }\n }\n /* 공정 모수(수율·셋업)도 같은 규율로 싣는다 — 커널이 그 창구를 갖지 않으면 그 사실을 말한다. */\n const params = model?.localParams as Record<string, Record<string, string>> | undefined\n if (params && Object.keys(params).length) {\n if (typeof kernel?.declareParameters !== 'function') {\n twinWarn(\n `[twin-engine] \"${id}\": this facility declared operation parameters for ${Object.keys(params).length} operation(s) but the kernel cannot consume them ` +\n '(declareParameters missing — kernel needs publishing). Yield and setup keep running on built-in constants.'\n )\n } else {\n try {\n kernel.declareParameters(params)\n } catch (err: any) {\n twinWarn(`[twin-engine] \"${id}\": declared operation parameter rejected by the kernel — ${err?.message ?? err}`)\n }\n }\n }\n const ops = model?.operations\n if (!ops?.length) return\n if (typeof kernel?.loadOperations !== 'function') {\n twinWarn(`[twin-engine] \"${id}\": model declares ${ops.length} operation spec(s) but the kernel cannot consume them (loadOperations missing — kernel needs publishing). Simulation will use built-in default durations.`)\n return\n }\n kernel.loadOperations(ops)\n }\n\n /**\n * 소요시간 추정기 주입 — **상수를 데이터로 바꾸는 두 번째·세 번째 층.**\n *\n * 커널 `durationOf` 의 우선순위는 추정기 > 명세 > 상수다. 그 추정기 자리에 두 가지를 사슬로 넣는다:\n * ① **실측**(저널의 작업 종류별 작업시간 p50) — 그 현장에서 실제로 얼마 걸렸나. 가장 강한 근거.\n * ② **거리 × 속도**(model.layout + 설비 속도 속성) — 이동은 거리에 비례한다. 커널은 좌표를 모르므로\n * 호스트가 계산해 넣는다.\n * 둘 다 못 만들면 주입하지 않는다 — 커널이 명세·상수로 굴러가고 `specCoverage()` 가 그 사실을 남긴다.\n *\n * 실측은 DB 조회라 비동기다. 그래서 이 함수는 **await 하지 않는 쪽에서도 안전**하도록 실패를 삼키되,\n * 무엇을 왜 못 넣었는지는 로그로 남긴다(조용한 무효화 금지).\n */\n static async installEstimators(kernel: any, domainId: string, instanceId: string, model: any): Promise<void> {\n if (!kernel || typeof kernel !== 'object') return\n const travel = buildTravelEstimator({ layout: model?.layout, equipment: model?.equipment, unit: model?.unit })\n const measured = await this.measuredEstimator(domainId, instanceId)\n const chained = chainEstimators([measured?.estimator, travel.estimator])\n if (!chained) {\n /* 왜 못 넣었는지 한 번만 알린다 — 이동시간이 상수로 남은 이유를 모르고 지나가지 않게. */\n if (travel.reasons.length) twinWarn(`[twin-engine] \"${instanceId}\": no duration estimator installed — ${travel.reasons.join('; ')}`)\n return\n }\n kernel.durationEstimator = chained\n /*\n * **양품률도 이력에서 배운다** (2026-08-19) — 소요와 같은 자리에서 붙인다.\n *\n * 커널이 그 시임을 갖지 않은 버전이면(발행 이전) 조용히 넘어가지 않고 말한다: 수율이 상수로 남은\n * 이유를 모르고 지나가면, 화면의 불량 판정이 그 현장의 사실이 아니라 우리 상수의 결과다.\n */\n const yields = await this.measuredYield(domainId, instanceId)\n if (yields?.estimator) {\n if (typeof kernel.yieldOf !== 'function') {\n twinWarn(\n `[twin-engine] \"${instanceId}\": learned yield for ${Object.keys(yields.learned).length} operation kind(s) but the kernel cannot consume it ` +\n '(yieldOf missing — kernel needs publishing). Yield keeps running on the declared value or the built-in constant.'\n )\n } else {\n kernel.yieldEstimator = yields.estimator\n twinLog(\n `[twin-engine] \"${instanceId}\": measured yield installed — ${Object.entries(yields.learned)\n .map(([k, v]) => `${k}=${Math.round(v * 1000) / 10}%(${yields.samples[k].good + yields.samples[k].scrap}건)`)\n .join(', ')}${yields.skipped.length ? ` · 표본 부족으로 뺀 종류: ${yields.skipped.map(s => `${s.kind}(${s.judged})`).join(', ')}` : ''}`\n )\n }\n } else if (yields?.skipped.length) {\n /* 배운 것이 없고 버린 것만 있으면 그 사실도 말한다 — 「이력이 없다」와 「표본이 모자라다」는 다르다. */\n twinLog(\n `[twin-engine] \"${instanceId}\": no measured yield yet — samples below ${yields.minSamples}: ${yields.skipped\n .map(s => `${s.kind}(${s.judged})`)\n .join(', ')}`\n )\n }\n const learned = Object.keys(measured?.learned ?? {})\n const spread = Object.keys(measured?.spreads ?? {})\n twinLog(\n `[twin-engine] \"${instanceId}\": duration estimator installed — measured kinds: ${learned.length ? learned.join(',') : 'none'}` +\n ` (with observed spread: ${spread.length ? spread.join(',') : 'none'})` +\n `${travel.estimator ? `, travel from distance (speeds: ${Object.keys(travel.speedsByKind).join(',')})` : `, travel not derived (${travel.reasons.join('; ')})`}`\n )\n }\n\n /**\n * 실측 추정기 — **예측 요청마다 저널을 다시 접지 않는다.**\n *\n * 예측 커널은 요청마다 새로 세워지고(미러 예측·백테스트), 화면은 시각을 긁으면 계속 재예측한다.\n * 거기에 KPI 조회를 그대로 달면 요청당 저널 스캔이 하나씩 붙는다 — 실측은 분 단위로 바뀌지 않으므로\n * 짧은 TTL 로 재사용한다. 캐시는 인스턴스별이고, 만료 전에는 같은 값을 쓴다(예측 간 일관성도 얻는다).\n */\n private static measuredCache = new Map<\n string,\n {\n at: number\n value: ReturnType<typeof buildMeasuredEstimator> | undefined\n /** 같은 폴드에서 나온 양품률 — **저널을 두 번 접지 않는다**(소요와 수율은 같은 창의 같은 사실이다). */\n yields?: ReturnType<typeof buildYieldEstimator>\n }\n >()\n private static readonly MEASURED_TTL_MS = 60_000\n /**\n * 캐시 항목 상한 — **라이프사이클이 놓친 것까지 막는 두 번째 방어.**\n *\n * 지움은 `forgetInstance` 가 한다(그것이 첫 번째 방어이고 정확한 쪽이다). 그런데 트윈이 우리 API 를\n * 지나지 않고 사라지는 길이 있다: 도메인(테넌트)째로 지워지거나 DB 를 직접 손대는 경우다. 그때\n * 남은 항목을 지울 주인이 없으므로 상한이 필요하다.\n *\n * 넘치면 **가장 오래 손대지 않은 것**부터 버린다(Map 의 삽입 순서가 곧 그 순서다 — 값을 쓸 때마다\n * 다시 넣으므로). 버리는 것이 손해가 아닌 이유: 이 값은 캐시이고, 없으면 다시 계산한다.\n *\n * 수를 크게 잡는다 — 트윈 규모는 늘 크고, 항목 하나는 작업 종류별 소요 몇 줄이다. 상한이 작으면\n * 정상 규모에서 서로 밀어내며 캐시가 무의미해진다(그게 더 나쁘다: 조용히 느려진다).\n */\n private static readonly MEASURED_MAX = 5_000\n\n /** 이 트윈이 이력에서 배운 양품률 — 소요와 **같은 폴드·같은 캐시**에서 온다(저널을 두 번 접지 않는다). */\n private static async measuredYield(domainId: string, instanceId: string) {\n await this.measuredEstimator(domainId, instanceId)\n return this.measuredCache.get(runtimeKey(domainId, instanceId))?.yields\n }\n\n private static async measuredEstimator(domainId: string, instanceId: string) {\n /* 키는 `runtimeKey` 하나로 — 손으로 조립하면 지우는 쪽과 어긋나 못 지우는 항목이 생긴다. */\n const key = runtimeKey(domainId, instanceId)\n const hit = this.measuredCache.get(key)\n if (hit && Date.now() - hit.at < this.MEASURED_TTL_MS) return hit.value\n let value: ReturnType<typeof buildMeasuredEstimator> | undefined\n let yields: ReturnType<typeof buildYieldEstimator> | undefined\n try {\n /* 작업 종류별 실측 — 창은 넉넉히(하루) 두고 표본이 모자란 종류는 추정기가 스스로 뺀다. */\n const kpi: any = await computeTwinKpi({ domainId, instanceId, windowMinutes: 24 * 60, groupBy: 'taskKind' })\n value = buildMeasuredEstimator(kpi?.groups?.items, {})\n /* 같은 그룹에서 양품률도 배운다 — 한 번 접은 저널을 둘이 나눠 쓴다. */\n yields = buildYieldEstimator(kpi?.groups?.items, {})\n } catch (err) {\n twinWarn(`[twin-engine] \"${instanceId}\": measured duration lookup failed — falling back to declared/default durations.`, (err as any)?.message)\n }\n /* 다시 넣어 **최근 쓴 것**으로 만든다 — 삽입 순서가 곧 버릴 순서이므로 이 한 줄이 LRU 를 만든다. */\n this.measuredCache.delete(key)\n this.measuredCache.set(key, { at: Date.now(), value, yields })\n if (this.measuredCache.size > this.MEASURED_MAX) {\n const oldest = this.measuredCache.keys().next()\n if (!oldest.done) this.measuredCache.delete(oldest.value)\n }\n return value\n }\n\n /**\n * **원본이 선언한 자극을 싣는다** — 재기동해도 살아 있게 (2026-08-19).\n *\n * ── 무엇이 났나 ────────────────────────────────────────────────────────────\n * 데모의 시나리오는 시드 코드가 메모리에만 실었다. 그래서 트윈을 재기동하면 자극이 사라지고 구조만\n * 서 있는 트윈이 남았다(작업 0·오더 0) — 「살아 있는 데모」가 **첫 재기동까지만** 살았다.\n *\n * 자극의 집은 **원본**이다(`TwinReference.connectionConfig.scenario`, ADR-0029 ·\n * `plans/simulator-as-source.md` §4): 무엇이 들어오고 무슨 주문이 나는지는 시뮬레이터가 정하는 사실이고\n * 트윈은 반영한다. 트윈에 새 축을 만들면 ADR-0029 가 걷어내야 할 표면이 하나 늘어난다.\n *\n * 판정은 순수 함수가 한다(`planStimulus`) — 미러에 싣지 않고, 검사를 통과하지 못한 선언은 태우지 않고\n * (그 이력이 있다: 잘못된 선언 하나가 다음 틱에서 서버를 내렸다), 못 실은 이유는 **말한다.**\n */\n private static async installStimulus(domainId: string, instanceId: string, inst: InstanceRuntime): Promise<void> {\n let config: any\n try {\n const ref = await getRepository(TwinReference).findOne({ where: { domain: { id: domainId }, source: instanceId } })\n config = ref?.connectionConfig\n } catch (err: any) {\n twinWarn(`[twin-engine] \"${instanceId}\": could not read the declared stimulus — ${err?.message ?? err}`)\n return\n }\n const plan = planStimulus(config, { hasScenarioEngine: !!inst.runtime?.scenario, mode: inst.mode }, validateScenario as any)\n if (plan.action === 'skip') {\n /* 선언이 없는 것은 정상이므로 조용히 지난다. 나머지 셋은 **말한다** — 선언했는데 안 실린 상태다. */\n if (plan.reason !== 'none') {\n twinWarn(\n `[twin-engine] \"${instanceId}\": a stimulus is declared on its source but was not loaded (${plan.reason}${plan.detail ? `: ${plan.detail}` : ''}).` +\n (plan.reason === 'observed' ? ' This twin runs on observation — we do not manufacture arrivals for it.' : '')\n )\n }\n return\n }\n try {\n /* 자극을 싣고 시작하는 데 든 시간 — 실측에서 큰 트윈은 이 구간이 29~72초였다. */\n const tStim = performance.now()\n inst.runtime!.scenario.load(plan.scenario)\n inst.runtime!.scenario.start()\n const stimMs = performance.now() - tStim\n recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'stimulus', stimMs)\n const kinds = (plan.scenario.generators ?? []).map((g: any) => g?.kind).filter(Boolean)\n twinLog(\n `[twin-engine] \"${instanceId}\": stimulus from its source started in ${Math.round(stimMs)}ms — ${kinds.length ? kinds.join(', ') : 'no generators'}.`\n )\n } catch (err: any) {\n twinWarn(`[twin-engine] \"${instanceId}\": the declared stimulus was rejected at load — ${err?.message ?? err}`)\n }\n }\n\n /**\n * 자극을 **원본에 선언한다** — 프로비저닝·데모 시드가 부르는 문.\n *\n * 트윈이 아니라 원본에 적는 이유는 위와 같다(ADR-0029). 원본 행이 없으면 만들지 않는다 — 어떤 원본에서\n * 온 트윈인지 모르는 채 자극을 지어 붙이면, 그 자극이 어디서 왔는지 아무도 되짚을 수 없다.\n */\n static async declareStimulus(domainId: string, instanceId: string, scenario: any): Promise<boolean> {\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: domainId }, source: instanceId } })\n if (!ref) {\n twinWarn(`[twin-engine] \"${instanceId}\": no source reference — a stimulus has nowhere to be declared.`)\n return false\n }\n ref.connectionConfig = withStimulus(ref.connectionConfig, scenario)\n await repo.save(ref)\n return true\n }\n\n /**\n * 이 트윈이 **이력에서 시간을 배운 작업 종류들** — 재기동에도 남는 근거.\n *\n * ── 왜 필요한가 (2026-08-18 실측) ────────────────────────────────────────\n * 커널의 자기보고(`specCoverage()`)는 **작업이 새로 생길 때** 채워진다. 그래서 재기동 직후에는 이력이\n * 풍부한 트윈에서도 목록이 비고, 「이 트윈이 무슨 공정을 돌리나」 화면이 빈칸이 된다 — 값을 채울 곳을\n * 보여야 하는 화면이 정작 그때 아무 말도 못 한다.\n *\n * 그 빈칸을 이력로 메운다: 저널에서 배운 종류는 **추정기가 이미 답할 수 있는 종류**이므로, 지어내는\n * 것이 아니라 있는 사실을 꺼내는 것이다. 같은 캐시(60초)를 쓰므로 조회마다 저널을 다시 접지 않는다.\n */\n static async measuredOperationKinds(domainId: string, instanceId: string): Promise<string[]> {\n const measured = await this.measuredEstimator(domainId, instanceId)\n return Object.keys((measured as any)?.learned ?? {})\n }\n\n /**\n * 지금 이 트윈이 어떤 모델로 굴러가는가 — 예측 출력 보정이 **자기가 배운 모델**에만 적용되도록\n * 비교하는 지문. 재료는 호스트가 아는 것(실측·속도·선언 명세)이라 커널 발행 상태와 무관하다.\n * 실패하면 undefined — 그때는 비교를 하지 않는다(모르는 것을 근거로 보정을 끊지 않는다).\n */\n static async modelBasis(domainId: string, instanceId: string): Promise<ModelBasis | undefined> {\n try {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n const model: any = reg?.model\n const measured = await this.measuredEstimator(domainId, instanceId)\n const travel = buildTravelEstimator({ layout: model?.layout, equipment: model?.equipment, unit: model?.unit })\n return { measured: measured?.learned, speeds: travel.speedsByKind, declared: model?.operations }\n } catch {\n return undefined\n }\n }\n\n /**\n * **이 트윈이 하루 몇 대를 낼 수 있는가** — 실행해 보지 않고 답한다.\n *\n * 계산은 커널이 자기 상태에서 한다(`kernel.capacity`). 여기서 하는 일은 **기준 주를 정해 주는\n * 것**뿐이다: 공휴일이 없는 평상주여야 한다 — 공휴일은 연간 가용량을 따로 깎지, 이 공장의 평상시\n * 상한을 정하지 않는다. 커널이 임의로 고르게 두면 그 주에 공휴일이 끼었을 때 상한이 조용히 낮아진다.\n *\n * 트윈이 기동 중이 아니면 `undefined` 다 — 0 이 아니다. 기동하지 않은 트윈의 상한을 0 이라고 답하면 화면은\n * \"이 공장은 아무것도 못 만든다\" 고 말한다.\n */\n static async capacity(\n domainId: string,\n target: { instanceId?: string; spaceId?: string },\n unitsPerDay: number,\n sampleWeekStartMs: number\n ): Promise<{ instanceId: string; kind?: string; analysis?: any; reason?: 'not-running' | 'no-operations' }[]> {\n /* 대상은 **등록부**가 정한다 — 기동 중인 런타임만 훑으면 \"안 떠 있어서 안 보이는 것\" 과 \"없는 것\" 이\n 구별되지 않는다. 화면은 그 둘을 다르게 말해야 한다. */\n const where: any = { domain: { id: domainId } }\n if (target.instanceId) where.instanceId = target.instanceId\n else where.spaceId = target.spaceId\n const registered = await getRepository(TwinInstance).find({ where })\n\n return registered.map(reg => {\n const rt = this.instances[runtimeKey(domainId, reg.instanceId)]\n const kernel: any = rt?.kernel // 키에 도메인이 있으므로 남의 런타임을 집을 수 없다\n if (typeof kernel?.capacity !== 'function') return { instanceId: reg.instanceId, kind: reg.kind, reason: 'not-running' as const }\n\n const analysis = kernel.capacity({ unitsPerDay, sampleWeekStartMs })\n /* 공정을 선언하지 않은 트윈(대개 YMS·WMS)은 **판정 대상이 아니다.** 0 으로 채워 넣으면\n \"야드가 병목\" 이라는 없는 사실이 생긴다 — 잴 것이 없다고 말한다. */\n if (!analysis?.operations?.length) return { instanceId: reg.instanceId, kind: reg.kind, reason: 'no-operations' as const }\n return { instanceId: reg.instanceId, kind: reg.kind, analysis }\n })\n }\n\n /**\n * **생산 능력 보고서** — ISA-95 Part 4 `OperationsCapability`. 구간의 양을 종류로 구분한다\n * (약정·가용·달성불가). 용량(`capacity`)은 비율을 내고 이것은 **구간의 양**을 낸다.\n *\n * 대상 선정·거절 사유는 `capacity` 와 **같은 규율**이다: 등록부가 대상을 정하고(안 기동 중인 것과\n * 없는 것을 구별한다), 공정을 선언하지 않은 트윈은 판정 대상이 아니라고 말한다(0 으로 채우면\n * \"야드가 병목\" 이라는 없는 사실이 생긴다).\n */\n static async operationsCapability(\n domainId: string,\n target: { instanceId?: string; spaceId?: string },\n unitsPerDay: number,\n sampleWeekStartMs: number,\n window: { fromTime: string; toTime: string }\n ): Promise<{ instanceId: string; kind?: string; report?: any; reason?: 'not-running' | 'no-operations' }[]> {\n const where: any = { domain: { id: domainId } }\n if (target.instanceId) where.instanceId = target.instanceId\n else where.spaceId = target.spaceId\n const registered = await getRepository(TwinInstance).find({ where })\n\n return registered.map(reg => {\n const rt = this.instances[runtimeKey(domainId, reg.instanceId)]\n const kernel: any = rt?.kernel\n if (typeof kernel?.operationsCapability !== 'function') {\n return { instanceId: reg.instanceId, kind: reg.kind, reason: 'not-running' as const }\n }\n const report = kernel.operationsCapability({ unitsPerDay, sampleWeekStartMs, window })\n if (!report?.perOperation?.length) return { instanceId: reg.instanceId, kind: reg.kind, reason: 'no-operations' as const }\n return { instanceId: reg.instanceId, kind: reg.kind, report }\n })\n }\n\n /**\n * 미러 기동의 연속성 씨앗 — 이어받은 것은 **말한다**(조용히 잇지 않는다).\n *\n * 커널이 그 문을 열어 두지 않았으면 그 사실도 말한다: 그 트윈은 재기동마다 열린 구간을 잃는다.\n */\n private static seedLiveContinuity(domainId: string, id: string, kernel: any): void {\n const cached = this.recovered[runtimeKey(domainId, id)]?.state\n if (!cached) return\n const plan = planLiveContinuity(cached)\n if (!plan.ackedCount && !plan.attentionSinceCount && !plan.energy) return\n if (typeof kernel.hydrateContinuity !== 'function') {\n twinWarn(\n `[twin-engine] kernel for \"${id}\" cannot carry continuity (no hydrateContinuity) — the open demand window, ` +\n 'its peak and the attention start times are lost on every restart.'\n )\n return\n }\n try {\n kernel.hydrateContinuity(plan.seed)\n } catch (err: any) {\n /* 이어받기가 실패해도 미러는 돌아야 한다 — 다만 무엇을 잃었는지 말한다. */\n twinWarn(`[twin-engine] continuity seed failed for \"${id}\" — starting without it: ${err?.message ?? err}`)\n return\n }\n const carried = [\n ...(plan.energy ? ['energy accumulation (open window, totalizer baselines, peak)'] : []),\n ...(plan.ackedCount ? [`${plan.ackedCount} acknowledged attention(s)`] : []),\n ...(plan.attentionSinceCount ? [`${plan.attentionSinceCount} attention start time(s)`] : [])\n ].join(', ')\n twinLog(`[twin-engine] mirror \"${id}\" carried over ${carried} — observation axes come from the source.`)\n }\n\n static start(id: string, domainId: string, kind: string, model: TwinModelDef, restartPolicy?: RestartPolicy, purpose?: string, resumeFrom?: number): InstanceRuntime {\n const key = runtimeKey(domainId, id)\n if (this.instances[key]) return this.instances[key]\n\n const Kernel = kernelFor(kind)\n const kernel: TwinKernel = new Kernel(domainId, undefined, this.productionSpecOf(model))\n kernel.loadTwinModel(model) // 구조만. 상태는 아래 웜스타트가 주입한다.\n this.applyOperations(kernel, model, id) // 시간·수율 명세(있으면) — 없으면 커널 기본값\n /* 추정기는 DB 조회를 포함해 비동기 — 기동을 막지 않고 붙는다(붙기 전 작업은 명세·상수로 산출). */\n this.installEstimators(kernel, domainId, id, model).catch(err => twinWarn('[twin-engine] estimator install failed', err?.message))\n /*\n * **웜스타트에 든 시간을 값으로 남긴다** (2026-08-22). 실측으로 부팅이 620~717초였고 트윈 하나에\n * 15~93초였는데, 어느 작업이 그 시간을 쓰는지 답할 계기가 없었다. 로그에도 밀리초까지 적어\n * 부팅 로그만으로 구간을 읽을 수 있게 한다.\n */\n const tWarm = performance.now()\n this.warmStart(domainId, id, kernel, purpose)\n const warmMs = performance.now() - tWarm\n if (warmMs >= 1000) twinLog(`[twin-engine] \"${id}\": warm start took ${Math.round(warmMs)}ms.`)\n /*\n * **번호를 이어 센다** — 저널에 이미 있는 번호와 겹치지 않게.\n *\n * 저널이 비어 있으면(0) 아무 일도 안 한다. 비어 있지 않은데 0부터 다시 세면 같은 트윈에 같은\n * 리비전이 둘 생기고, 재생 순서가 뒤섞이며, 시간여행이 엉뚱한 시점을 답한다 — 오류는 안 난다.\n */\n if (resumeFrom && typeof (kernel as any).resumeRevision === 'function') (kernel as any).resumeRevision(resumeFrom)\n /*\n * ── 이 트윈의 시계를 **지금**에 맞춘다 (2026-08-15) ────────────────────────\n * 커널의 기본 기준점은 상수(2026-01-01)다. 그대로 두면 시뮬 트윈의 저널 시각이 **재기동마다\n * 되감겨** 며칠 치 사건이 전부 같은 분에 몰린다 — 「언제 있었던 일인가」를 되짚을 수 없고,\n * 실 시각으로 창을 자르는 성과·이력 질의에는 그 트윈이 아예 보이지 않는다.\n *\n * 재기동하면 그만큼 시계가 앞으로 뛰는데, 그것이 사실이다: 그 사이 이 트윈은 돌지 않았고\n * 저널의 빈 구간이 그 사실을 말한다.\n */\n kernel.setClockOrigin?.(Date.now())\n const runtime: TwinRuntimeType = new TwinRuntime(kernel)\n\n /* subscribe 는 RuntimeSubscription({ unsubscribe() }) 반환 → () => void 로 감쌈. */\n /*\n * **모드를 적어 둔다** (2026-08-18 실측으로 고침).\n *\n * 시뮬 경로는 `mode` 를 비워 두었고(「미지정=sim」이라는 규약에 기대), 라이브만 적었다. 그래서\n * `modeOf()` 가 **도는 시뮬레이션에 undefined** 를 답했고, 선언·철회의 답이 「저장했다」로 나갔다 —\n * 실제로는 도는 커널이 옛 수를 그대로 쓰고 재기동 때 받는데, 그 사실이 답에서 사라진 것이다.\n * 규약에 기대는 대신 사실을 적는다: 「돌고 있나」를 묻는 쪽이 그 답을 받아야 한다.\n */\n const inst: InstanceRuntime = {\n id,\n domainId,\n mode: 'sim',\n runtime,\n kernel,\n /* 정책은 부르는 쪽이 선언한다 — 여기서 고르면 같은 트윈이 부르는 자리에 따라 다르게 재기동한다. */\n restartPolicy: readRestartPolicy(restartPolicy, `start(\"${id}\")`),\n spaceId: (model as any)?.spaceId,\n /*\n * **시뮬도 계기를 든다** (2026-08-20).\n *\n * 예전에는 `startLive` 에서만 만들었다. 그래서 도는 트윈 22개가 시뮬인 서버에서 「초당 몇 행을\n * 쓰나」·「밀린 게 있나」를 물을 자리가 **아예 없었다** — 저널 쓰기를 배치로 고친 뒤에도 그 효과와\n * 회귀를 숫자로 볼 수 없다. 세지 않는 개선은 다음 사람이 되돌려도 아무도 모른다.\n *\n * 유입(`ingested`)은 시뮬에 뜻이 없다(원본에서 받는 것이 아니라 자기가 낸다) — 그 칸은 0 으로\n * 남고, 그것이 사실이다(「받은 것이 없다」).\n */\n metrics: this.newMetrics(),\n unsub: () => {}\n }\n this.instances[key] = inst\n /* 다시 세웠으므로 지난 정지 이유는 사실이 아니다 — 남겨 두면 도는 트윈이 「굶겨서 멈췄다」고 말한다. */\n this.stopNotes.delete(key)\n delete this.recovered[key] // 웜스타트로 커널에 옮겨 심었다 — 이제 라이브가 진실이다.\n /* 원본이 선언한 자극 — 기동을 막지 않는다(추정기와 같은 규율). 못 실었으면 그 사실을 말한다. */\n this.installStimulus(domainId, id, inst).catch(err => twinWarn(`[twin-engine] \"${id}\": stimulus install failed — ${err?.message ?? err}`))\n\n /* 라이브 바인딩(P3): data 채널 필터가 subdomain 을 보므로 Domain 객체를 1회 해석해 둔다. */\n getRepository(Domain).findOne({ where: { id: domainId } }).then(d => (inst.domain = d)).catch(() => {})\n\n /* State 채널: runtime.subscribe(snapshot→delta→clock) → pubsub 브로드캐스팅(구독 리졸버가 instanceId 필터). */\n const sub = runtime.subscribe((msg: SubscriptionMessage) => {\n this.publishGuarded(\n 'twin-state',\n { twinState: { instanceId: id, kind: msg.kind, revision: (msg as any).revision, payload: msg } },\n `twin-state:${id}`\n )\n /* 영속 + 라이브 바인딩 브리지: delta 를 저널 버퍼에 담고 + 엔티티별 data(tag:) publish → 보드 컴포넌트 라이브. */\n if (msg.kind === 'delta') {\n /*\n * ── 쓰기도 **모아서** 한 번 (2026-08-20 실측으로 잡음) ────────────────────\n *\n * 여기서 델타마다 `persist()` 를 불렀다 — 행 하나당 `save()` 하나, 그리고 그 안에서\n * `structureRevOf` 를 await(구조 행이 없는 트윈은 캐시 미스가 기억되지 않아 **델타마다\n * SELECT** 였다). 데모 자극을 켠 트윈 23개에서 그 결과가 이랬다: 프로세스 CPU 81~112%,\n * 아무 일도 하지 않는 질의가 8~14초. 프로파일은 `JSON.parse`·대형 GC·스레드풀을 가리키고\n * 계기는 틱의 몫이 16% 라고 말했다 — **틱이 아니라 쓰기였다.**\n *\n * 바로 위 주석이 **브로드캐스팅**에서 같은 함정을 적어 두었다(틱 하나가 35초). 브로드캐스팅은 모으도록\n * 고쳤고 쓰기는 단건으로 남아 있었다. 같은 규율로 들인다 — ADR-0030 이 *\"기록 경로가 둘인\n * 것은 시뮬만 옆문으로 들어오기 때문\"* 이라 예고한 그 자리다.\n *\n * **리비전은 커널의 것을 그대로 든다**(라이브는 flush 때 호스트가 부여한다). 시뮬의 저널은\n * 커널 리비전으로 접히므로 여기서 다시 번호를 매기면 시간여행이 어긋난다.\n */\n ;(inst.pendingJournal ?? (inst.pendingJournal = [])).push({ event: msg.event, revision: (msg as any).revision })\n /*\n * ── 브로드캐스팅은 **모아서** 한 번 (2026-08-14 실측으로 잡음) ────────────────────\n * 여기서 곧바로 브로드캐스팅하고 있었다. 그런데 커널은 한 번의 tick 에서 사실을 **여러 개** 낸다\n * (예약·배치·완료…). 그래서 tick 하나가 전 상태 투영을 수백 번 반복했다 — `order-check`\n * 트윈에서 **틱 하나가 35초**를 먹고(단계 합은 32ms 였다: 시간은 반복 횟수에 있었다) 그\n * 35초 동안 이벤트 루프가 막혀 구독자가 아무것도 빼내지 못했다. 밀린 push 가 1024를 넘는\n * 순간 pubsub 이 오류를 내고, 그 예외가 타이머 콜백을 타고 올라와 **호스트가 죽었다.**\n *\n * 라이브는 이미 dirty 표시 + 주기 flush 로 이 문제를 풀어 두었다(BROADCAST_COALESCE_MS).\n * 시뮬만 그 규율 밖에 있었다 — 같은 규율로 들인다(최신-상태 채널이라 중간 상태를 모두\n * 보낼 이유가 없다: 200ms 마다 마지막 것 하나면 화면은 같다).\n */\n inst.dirty = true\n /* 이 사실이 건드린 물품만 다음 브로드캐스팅에서 만든다(모르면 전부). */\n this.markItemsDirty(inst, [msg.event])\n this.ensureBroadcastCoalescer()\n }\n })\n inst.unsub = () => sub.unsubscribe()\n\n /* 위에서 잰 웜스타트 시간을 계기에 적는다 — 계기는 인스턴스가 생긴 뒤에야 있다. */\n recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'warmStart', warmMs)\n\n /* 복구 앵커: 레지스트리에 model/kind/status/restartPolicy 영속(재부팅 시 이게 있어야 replay·선언 거동 가능). */\n this.register(domainId, id, kind, model, 'running', inst.restartPolicy).catch(err => twinError('twin register fail', err))\n\n /* 워커 tick — 스켈레톤은 setInterval(메인 루프). 긴 시뮬 오프-루프(worker thread)는 스케일 하드닝(향후, §host 경계). */\n inst.timer = this.startTickTimer(\n () => this.tickGuarded(domainId, id, runtime),\n t => (inst.timer = t)\n )\n return inst\n }\n\n /**\n * live-모드 기동 — **관측 모드 커널**로 실 이벤트를 미러한다(통합 P2).\n *\n * 예전에는 `StateProjector` 를 세웠다. 그래서 라이브에는 **커널이 없었고**, 그 하나 때문에 우회가\n * 줄줄이 생겼다: 예측하려면 임시 커널을 세워야 했고(`buildForecastKernel`), 주목 신호를 호스트가\n * 덧붙여야 했고(`withLiveAttentions`), AI 예측 도구는 미러에서 \"찾을 수 없다\" 로 끝났다.\n *\n * 이제 라이브 인스턴스도 **커널이다.** 같은 규칙(`ObservedReducer`)으로 이벤트를 접고, 주목 신호를\n * 스스로 내고, 그 자리에서 `fork` 해 예측한다. 구동만 다르다 — sim 은 `tick`, live 는 `apply`.\n *\n * 실 이벤트원 = reference 어댑터 openLiveFeed → face2-adapter.ingest → CanonicalEnvelope → ingestLive().\n */\n /**\n * 모델이 실은 **생산 정의**(레시피·라우트·바인딩)를 꺼낸다 — 커널의 정의-구동 모드 입구.\n *\n * ── 없을 때 무엇이 일어났나 ──────────────────────────────────────────────\n * 커널에는 정의-구동 MES 경로가 있는데 **호스트가 그것을 한 번도 넘기지 않았다.** 그래서 모든 MES\n * 트윈이 **하드코딩된 레거시 흐름**으로 돌았다 — 현장 레시피를 아무리 정성껏 적어도 커널은 그것을\n * 보지 못하고 토이 부품으로 토이 제품을 만들었다. 선언과 실행이 갈라져 있던 자리다.\n *\n * 모델에 없으면 `undefined` — 레거시 경로 그대로다(기존 트윈의 거동을 바꾸지 않는다).\n */\n /**\n * 생산 선언을 꺼낸다 — 커널 생성자에 넘긴다.\n *\n * **옛 이름(`mesSpec`)은 읽지 않는다.** 그것은 계약에 선언조차 없던 필드였고(MES 커널 생성자 인자\n * 이름이 그대로 굳은 것), 일반 기제에 한 시스템 이름이 붙어 있었기 때문에 창고 트윈이 이 자리를\n * 쓰지 못했다. 별명으로 남겨 두면 그 혼동이 계속되므로 하나로 통일했다.\n *\n * 옛 이름만 가진 모델이 있으면 **조용히 생산 선언을 잃는 대신 분명히 멈춘다** — 그 트윈은 공정이\n * 없는 채로 돌게 되고(라인이 서 있는 창고), 원인을 찾기 어렵다.\n */\n private static productionSpecOf(model: TwinModelDef | undefined): any {\n const legacy = (model as any)?.mesSpec\n if (legacy && !(model as any)?.productionSpec) {\n throw new Error(\n 'the twin model carries the retired `mesSpec` field — rename it to `productionSpec` ' +\n '(same shape; the name was tied to one kernel while the declaration is ISA-95 operations + BOM)'\n )\n }\n return (model as any)?.productionSpec\n }\n\n /**\n * 현장(공간)의 **시각 기준**을 모델에 얹는다 — 커널이 교대의 `HH:MM` 을 읽을 기준.\n *\n * **테넌트가 아니라 공간이 권위다.** 한 테넌트가 Rosarito(태평양)와 한국 공장을 함께 가질 수 있고,\n * 테넌트 단위(`Domain.timezone`)로 두면 둘 중 하나는 반드시 틀린다. 그래서 인스턴스가 연결된 공간의\n * `timezone` 을 읽는다. 공간이 말하지 않으면 **테넌트로 내려가지 않는다** — 잘못된 입자로 답하는 것이\n * 모르는 것보다 나쁘다(그때는 커널이 UTC 로 읽고, 그 기본값은 계약에 밝혀져 있다).\n *\n * 커널은 zero-dep 이라 시간대 데이터베이스를 갖지 않으므로 **분 오프셋**으로 풀어 넘긴다. 그 값은\n * 지금 계절의 것이다(일광절약시간) — 계절을 넘는 긴 예측은 한 시간 어긋난다(계약에 명시).\n */\n static async withSpaceTimeBase(model: TwinModelDef, domainId: string, spaceId?: string): Promise<TwinModelDef> {\n const sid = spaceId ?? (model as any)?.spaceId\n if (!sid) return model\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId: sid } }).catch(() => null)\n const offset = utcOffsetOf(space?.timezone)\n if (offset === undefined) {\n if (space?.timezone) twinWarn(`[twin-engine] space \"${sid}\" declares time zone \"${space.timezone}\" but it is not a known IANA zone — times will be read as UTC.`)\n return model\n }\n return { ...model, utcOffsetMinutes: offset }\n }\n\n static startLive(id: string, domainId: string, kind: string, model: TwinModelDef): InstanceRuntime {\n const key = runtimeKey(domainId, id)\n if (this.instances[key]) return this.instances[key]\n const Kernel = kernelFor(kind)\n const kernel: any = new Kernel(domainId, undefined, this.productionSpecOf(model))\n kernel.loadTwinModel(model)\n /* **세우는 쪽이 아는 사실은 세울 때 말한다.** 예전에는 첫 이벤트가 도착해야 커널이 스스로를\n 관측 구동으로 여겼고, 그래서 아직 아무것도 못 받은 미러는 시뮬레이션 취급을 받았다. */\n declareObserved(kernel, `live twin '${id}'`)\n this.applyOperations(kernel, model, id) // 명세는 라이브에도 실린다(예측 자격이 sim 과 같아진다)\n /* `projector` 필드는 옛 이름으로 남긴다 — 소비처가 `snapshot()` 을 부르므로 얇은 어댑터로 잇는다.\n * (P3 에서 소비처를 커널 어휘로 바꾸면 사라진다.) */\n const projector = { apply: (e: CanonicalEnvelope) => kernel.apply(e), snapshot: () => kernel.getSnapshot() }\n const inst: InstanceRuntime = { id, domainId, mode: 'live', restartPolicy: 'resync', kernel, projector, oee: new OeeAccumulator(), spaceId: (model as any)?.spaceId, unsub: () => {} }\n /*\n * ── 커널이 **판정으로 낸 사실**도 저널에 남는다 (2026-08-14 실측으로 잡음) ────\n *\n * 라이브는 인입 봉투만 저널에 적고 있었다(`ingestLive`). 그런데 커널은 관측을 접다가 **자기 사실**을\n * 낸다 — 에너지의 수요 구간 마감·피크 경신·감축 제안이 그렇다(`emitOp`). 그것을 구독하는 곳이\n * 없어서 그 사실들이 **커널 안에서 사라졌다**: 표본 48건이 저널에 쌓였는데 구간 마감은 0건이었고,\n * 저널을 읽는 성과 화면의 전력 타일은 영원히 나오지 않았다.\n *\n * sim 은 `runtime.subscribe` 로 같은 일을 한다 — 라이브에만 그 배선이 없었다.\n *\n * **인입의 재방출은 걸러낸다**: `apply()` 는 받은 봉투를 구독자에게 그대로 흘린다(호스트가 두 모드에서\n * 같은 배선을 쓰게 하려고). 그것까지 적으면 인입이 저널에 두 번 들어간다 — 그래서 방금 넣은 것과\n * **같은 객체**인지 보고 건너뛴다(id 비교는 어댑터가 id 를 어떻게 만드는지에 기대게 되어 약하다).\n */\n const applying = new WeakSet<object>()\n inst.applying = applying\n inst.unsub = kernel.onEvent?.((e: CanonicalEnvelope) => {\n if (e && typeof e === 'object' && applying.has(e as object)) return // 인입의 재방출 — 저널은 인입에서 한 번만\n ;(inst.pendingJournal ?? (inst.pendingJournal = [])).push(e)\n /* 커널이 낸 사실도 상태를 바꾼다(피크·마감) — 다음 브로드캐스팅 주기에 실린다. */\n inst.dirty = true\n this.markItemsDirty(inst, [e])\n this.ensureBroadcastCoalescer()\n }) ?? (() => {})\n /* 추정기(실측·거리)도 라이브에 붙인다 — 예측이 상수로 계산되지 않게. 기동을 막지 않는다. */\n this.installEstimators(kernel, domainId, id, model).catch(err => twinWarn('[twin-engine] estimator install failed', err?.message))\n inst.metrics = this.newMetrics()\n this.instances[key] = inst\n /* 미러에도 부른다 — 선언이 있으면 「미러에는 싣지 않는다」고 말해야 한다(조용한 무시 금지). */\n this.installStimulus(domainId, id, inst).catch(err => twinWarn(`[twin-engine] \"${id}\": stimulus check failed — ${err?.message ?? err}`))\n /*\n * **원천이 되풀어 주지 않는 것만 잇는다** (2026-08-18 실측으로 붙임).\n *\n * 미러는 오랫동안 아무것도 이어받지 않았다 — 진실이 원천에 있으니 옳은 판단이었지만, 원천이 **애초에\n * 다시 말해 주지 않는 축**까지 함께 버렸다: 열린 15분 구간의 누적·적산 기준점·관측 이후 최대, 그리고\n * 확인해 둔 신호와 조건이 언제부터인지. 그래서 재기동하면 오류 없이 값이 작아졌다(그 구간의 전력량과\n * 피크가 부팅 이후로만 잡히고, 세 시간째 지속된 경보가 「0초째」가 됐다 — 요금이 걸린 수다).\n *\n * 관측 축(재고·위치·설비)은 **여전히 심지 않는다** — 다음 계측이 정정하고, 심으면 떠난 물건이\n * 되살아난다. 무엇을 넘길지는 `planLiveContinuity` 가 고르고, 어떻게 흡수할지는 커널이 정한다.\n */\n /*\n * ── **재개점에서 미러를 되세운다** (2026-08-24) ────────────────────────────\n *\n * 이 자리에서 미러는 오랫동안 되찾은 상태를 **버렸다**. 전제는 「진실은 원천에 있으니 다음 계측이\n * 정정한다」였고 라이브 피드에서는 옳았다. 그런데 원본이 **커서 증분**으로 말하는 현장에서는 그\n * 정정이 오지 않는다: 커서가 따라잡힌 뒤 원본이 변하지 않으면 미러는 영구히 빈 채로 남는다.\n * 그리고 그 빈 채로 화면이 「이상 없음」을 보였다 — 사실이 사라지는 동안 화면이 안심시킨 것이다.\n *\n * 되돌리는 것은 **상태가 아니라 재개점**이다. 상태만 심으면 그 뒤를 이어 접은 결과가 0부터 접은\n * 결과와 조용히 달라진다(리듀서는 보류된 담김·집계 중인 수량도 든다). 그 동치는 커널 시험이\n * 증명한다(`observed-checkpoint.test.ts` — 재개점 + 꼬리 == 0부터 접기).\n *\n * 씨앗은 **그 공장이 아직 그 공장일 때만** 오고, 마지막 체크포인트 이후의 사실은 이미 접혀 들어\n * 있다(`warmSeedFor`). 씨앗이 없으면 전과 같이 빈 채로 시작한다 — 지어내지 않는다.\n */\n const seed = this.recovered[key]?.fold?.reducer\n if (seed) {\n if (typeof kernel.restoreObserved !== 'function') {\n twinWarn(\n `[twin-engine] \"${id}\": a fold seed is stored but this kernel cannot take it (no restoreObserved) — ` +\n 'the mirror starts empty and waits for the source to re-tell everything. Upgrade the kernel.'\n )\n } else {\n try {\n kernel.restoreObserved(seed)\n const st = kernel.getSnapshot?.()\n twinLog(\n `[twin-engine] mirror \"${id}\" resumed from the stored fold seed at revision ${this.recovered[key]?.revision} — ` +\n `items ${st?.items?.length ?? 0} · orders ${st?.orders?.length ?? 0} · tasks ${st?.tasks?.length ?? 0} ` +\n '(the journal is not folded from the beginning).'\n )\n if (this.recovered[key]?.fold?.oee) inst.oee?.restore(this.recovered[key].fold.oee)\n } catch (err: any) {\n /* 되세우기가 실패해도 미러는 돌아야 한다 — 다만 무엇을 잃었는지 말한다. */\n twinWarn(`[twin-engine] \"${id}\": could not resume from the stored fold seed — starting empty: ${err?.message ?? err}`)\n }\n }\n }\n this.seedLiveContinuity(domainId, id, kernel)\n delete this.recovered[key]\n /* 라이브 바인딩(data 채널) subdomain 필터용 Domain 1회 해석(sim 과 동일). */\n getRepository(Domain).findOne({ where: { id: domainId } }).then(d => (inst.domain = d)).catch(() => {})\n /*\n * 저널 revision 카운터 시드 — 기존 저널 최대치에서 이어붙임(재기동 시 revision 충돌 방지).\n *\n * ── **커널에도 같은 번호를 알려 준다** (2026-08-23 실측) ────────────────────\n * 예전에는 이 자리에서 `inst.revision`(저널 줄 번호)만 이어받고 **커널은 0 부터 세게 두었다.**\n * 그래서 체크포인트가 뜻이 다른 두 수를 나란히 적었다.\n *\n * 바깥 revision 12,972 저널에 적힌 줄 번호 (이 자리에서 이어받는다)\n * state.revision 6,478 커널이 처리한 봉투 수 (0 부터 셌다)\n *\n * 포천 미러에서 확정했다: 차이 6,494 는 그 트윈을 **다시 세운 시각**(09:11)에 저널이 이미 갖고\n * 있던 줄 수와 정확히 같았다(줄 6494 = 08:23:59, 줄 6495 = 09:11:13). 산수가 맞았다.\n *\n * 결함은 두 수가 다르다는 것 자체가 아니라 **비대칭**이다: 재기동 경로(`start` → `resumeRevision`)는\n * 커널에 번호를 알려 주는데 **이 경로(미러)는 알려 주지 않았다.** 그래서 같은 저장물을 읽는 소비처가\n * 같은 이름의 두 수를 같은 축으로 견주게 되고, 실제로 그렇게 읽혔다.\n *\n * 저널이 비어 있으면(0) 아무 일도 하지 않는다 — 새 트윈은 0 부터 세는 것이 맞다. 그리고 이 조회는\n * 비동기라 그 사이에 이벤트가 몇 건 들어와 있을 수 있는데, 그때 뒤로 되돌리는 것은 커널이 거절한다\n * (겹치는 번호를 막는 그 판정이다). 거절은 삼키지 않고 남긴다.\n */\n getRepository(TwinEvent)\n .findOne({ where: { domain: { id: domainId }, instanceId: id }, order: { revision: 'DESC' } })\n .then(top => {\n const head = top?.revision ?? 0\n inst.revision = head\n if (!head || typeof (kernel as any).resumeRevision !== 'function') return\n try {\n ;(kernel as any).resumeRevision(head)\n } catch (err: any) {\n /* 뒤로 갈 수 없다는 거절 — 이 조회가 도착하기 전에 이미 그만큼 처리했다는 뜻이다. */\n twinWarn(`[twin-engine] \"${id}\": journal head ${head} is behind the kernel — ${err?.message ?? err}`)\n }\n })\n .catch(() => (inst.revision = 0))\n this.register(domainId, id, kind, model, 'running', 'resync').catch(err => twinError('twin register fail', err))\n return inst\n }\n\n /**\n * live 이벤트 인제스트 — projector 구동 + data(tag) 브로드캐스팅(폐루프의 인바운드 도착 지점, command-routing §8.2).\n * reference 어댑터가 낸 records → 커널 face2-adapter.ingest → CanonicalEnvelope 를 여기로 밀어넣는다.\n * (State 채널 델타/저널 결선은 후속 — 스켈레톤은 data(tag) 미러 중심.)\n *\n * ── 넣은 수를 **답한다** (2026-08-20) ────────────────────────────────────────\n * 트윈이 라이브로 돌지 않으면 여기서 봉투를 버린다. 그것 자체는 맞다(넣을 커널이 없다). 문제는\n * **조용히** 버린 것이었다: 트윈이 멈춘 뒤에도 피드는 남아 레코드를 나르고, 유입 장부는 그것을\n * 「통과」로 셌다. 화면은 멈춘 트윈 옆에 「150 통과 · 100%」라고 적었다 — 사실이 사라지는 동안\n * 화면이 안심시킨 것이다.\n *\n * 그래서 **넣은 수를 돌려준다.** 부르는 쪽이 제시 수와 견주어 버려진 수를 장부에 적는다. 반환을\n * 무시하는 호출부는 그대로 동작한다(전과 같다).\n */\n static ingestLive(domainId: string, id: string, envelopes: CanonicalEnvelope[]): number {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst?.mode !== 'live' || !inst.projector) return 0\n const tIngest = performance.now()\n /* 인입 봉투를 표시해 두고 넣는다 — 커널이 그것을 재방출해도 저널에 두 번 적히지 않게(위 구독 주석). */\n for (const e of envelopes) {\n if (e && typeof e === 'object') inst.applying?.add(e as object)\n inst.projector.apply(e)\n inst.oee?.apply(e) // 관측(projector) + 계산(OEE 누적)\n }\n recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'ingest', performance.now() - tIngest)\n // 저널 결선(라이브도 sim 처럼 이벤트 영속) — 단 이벤트마다 DB write 하면 부하폭발이라 모아뒀다가\n // coalescer tick 에서 배치 기록(브로드캐스팅과 동일 주기). 히스토리 노브·타임라인·비즈니스 원장이 이 저널을 읽는다.\n ;(inst.pendingJournal ?? (inst.pendingJournal = [])).push(...envelopes)\n if (inst.metrics) { inst.metrics.ingestedTotal += envelopes.length; inst.metrics._accIngest += envelopes.length } // 계측(④-1)\n // 브로드캐스팅 병합(ingest-scale §1.1/§4.4) — apply 는 O(1)·싸다. 그러나 브로드캐스팅(snapshot O(state))은 비싸(대규모 5ms+)\n // 이벤트마다 브로드캐스팅하면 폭발 → dirty 만 찍고 coalescer tick 이 주기 브로드캐스팅(브로드캐스팅률 ≠ 인제스트률).\n inst.dirty = true\n this.markItemsDirty(inst, envelopes)\n this.ensureBroadcastCoalescer()\n return envelopes.length\n }\n\n /**\n * 구간 성과 브로드캐스팅은 **없앴다**(2026-08-06). 카드가 `twinKpi` 를 직접 묻는다.\n *\n * 왜: 카드를 여러 단계(공간·트윈·구역·자리·설비)에 붙이려면 브로드캐스팅으로는 태그가 트윈당 1,200개가 되고,\n * **모델에 카드를 하나도 안 놓아도** 30초마다 트윈마다 저널을 접었다. 질의로 바꾸니 보고 있는 카드\n * 수만큼만 들고, 같은 (대상·창·축) 은 클라이언트가 하나로 합친다.\n *\n * 덤으로 질의만 할 수 있는 것이 둘 생겼다 — **과거 시각**(`toTime`)과 **공간 단위 합산**(여러 트윈을\n * 한 번에 접기). 브로드캐스팅 루프는 트윈별이라 둘 다 못 했다.\n *\n * 축을 나눠도 폴드 비용이 같다는 실측이 근거다(`test/kpi-query-bench.test.ts`).\n */\n /**\n * 몇 창마다 한 번은 **전부** 만드나 — 사건 없이 값이 바뀌는 자리에 대한 그물.\n *\n * 25 창이면 기본 주기에서 5초다. 보장이 아니라 그물이다(위 `publishEntityData` 주석).\n */\n static FULL_BROADCAST_EVERY = 25\n /** 전부 만든 횟수 — 범위를 좁히지 못한 창이 얼마나 되는지 값으로 남는다. */\n static broadcastFullPasses = 0\n /**\n * 브로드캐스팅을 만든 횟수 전부 — **전부 만든 횟수의 분모.**\n *\n * 분자만 내면 「전부 만들기 1,200회」가 많은 것인지 적은 것인지 읽을 수 없다. 좁히기가 듣고 있으면\n * 이 값의 `1/FULL_BROADCAST_EVERY` 쯤이 전부 만든 횟수이고, 두 값이 비슷하면 범위를 거의 못 좁힌\n * 것이다(원인은 대개 「모른다」로 떨어지는 사건이다).\n */\n static broadcastPasses = 0\n\n /**\n * 이 창에 건드린 물품을 모은다 — **말할 수 없으면 범위를 버린다(전부 만든다).**\n *\n * `events` 를 주지 않으면 「무엇이 바뀌었는지 모른다」다(구조 전환처럼 상태 전반이 달라지는 자리).\n * 한 창에서 한 번 「모른다」가 되면 그 창은 끝까지 모르는 채로 둔다 — 뒤에 온 사건으로 범위를\n * 되살리면 앞 사건이 건드린 것을 빠뜨린다.\n */\n static markItemsDirty(inst: InstanceRuntime, events?: any[]): void {\n if (inst.dirtyItems === undefined) return // 이 창은 이미 「모른다」\n if (!events) {\n inst.dirtyItems = undefined\n return\n }\n for (const e of events) {\n const touched = touchedItemKeys(e)\n if (!touched) {\n inst.dirtyItems = undefined\n return\n }\n for (const epc of touched) inst.dirtyItems.add(epc)\n }\n }\n\n /** 브로드캐스팅 병합 주기(ms) — 브로드캐스팅률 상한. 인제스트가 아무리 빨라도 이 주기로만 브로드캐스팅. */\n static BROADCAST_COALESCE_MS = 200\n /**\n * ── 브로드캐스팅 주기는 **재 본 비용에 맞춘다** (2026-08-21 실측) ────────────────────\n * 한 번의 브로드캐스팅은 상태 크기에 비례한다(실측: 물품 2,400 개인 트윈 하나가 4.5ms — 상태 투영 1.7ms,\n * payload 만들기 1.8ms, 시그니처 1.0ms). 트윈이 스무 개면 200ms 마다 90ms 가 브로드캐스팅에 들어가고,\n * 그 시간에는 HTTP 도 구독도 서지 못한다.\n *\n * 그래서 한 창에서 브로드캐스팅에 쓴 시간이 주기의 일정 몫을 넘으면 **주기를 늘린다**. 화면은 조금 늦게\n * 갱신되고(최신-상태 채널이라 값은 마지막 것 하나뿐이므로 내용은 같다), 늘렸다는 것은 계기판이\n * 말한다(`broadcastCoalesceMs`). 여유가 생기면 원래 주기로 되돌린다.\n *\n * 이것은 브로드캐스팅 비용을 **줄이는 것이 아니다** — 비용을 줄이는 것은 변경분만 만드는 일이고 그것은 별\n * 작업이다. 여기서는 그때까지 호스트가 굶지 않게 상한을 둔다.\n */\n static BROADCAST_MAX_COALESCE_MS = 1000\n /** 주기의 몇 몫까지 브로드캐스팅에 써도 되는가 — 넘으면 주기를 늘린다(절반이면 나머지 절반은 남긴다). */\n static BROADCAST_LOAD_RATIO = 0.3\n /** 지금 쓰고 있는 주기(ms) — 계기판이 이 값을 읽는다. 늘어난 채로 있으면 그것이 사실이다. */\n static broadcastPeriodMs = 200\n /** 주기를 늘린 횟수 — 조용히 늦추지 않는다. */\n static broadcastBackoffs = 0\n private static broadcastTimer?: any\n\n /** live 브로드캐스팅 coalescer — dirty 인 live 인스턴스만 주기적으로 1회 브로드캐스팅(entitySigs 로 변경 엔티티만). */\n private static ensureBroadcastCoalescer(): void {\n if (this.broadcastTimer) return\n this.broadcastPeriodMs = this.BROADCAST_COALESCE_MS\n this.broadcastTimer = setInterval(() => this.flushLiveBroadcasts(), this.broadcastPeriodMs)\n if (typeof this.broadcastTimer.unref === 'function') this.broadcastTimer.unref() // 종료 비차단\n }\n\n /**\n * 브로드캐스팅에 쓴 시간을 보고 주기를 정한다 — **늘리는 것도 줄이는 것도 값에 근거한다.**\n *\n * 한 번의 flush 가 주기의 `BROADCAST_LOAD_RATIO` 를 넘게 쓰면 주기를 두 배로(상한까지), 그 몫의\n * 절반 아래로 내려오면 절반으로(원래 주기까지) 되돌린다. 문턱을 두 개 두는 이유는 하나면 경계에서\n * 늘리고 줄이기를 반복하기 때문이다.\n */\n private static adjustBroadcastPeriod(flushMs: number): void {\n const period = this.broadcastPeriodMs\n const high = period * this.BROADCAST_LOAD_RATIO\n const low = high / 2\n let next = period\n if (flushMs > high && period < this.BROADCAST_MAX_COALESCE_MS) {\n next = Math.min(this.BROADCAST_MAX_COALESCE_MS, period * 2)\n this.broadcastBackoffs++\n twinWarn(\n `[twin-engine] broadcast period ${period}ms → ${next}ms — one flush took ${Math.round(flushMs)}ms across ${Object.keys(this.instances).length} twin(s)`\n )\n } else if (flushMs < low && period > this.BROADCAST_COALESCE_MS) {\n next = Math.max(this.BROADCAST_COALESCE_MS, Math.round(period / 2))\n }\n if (next === period) return\n\n this.broadcastPeriodMs = next\n if (this.broadcastTimer) clearInterval(this.broadcastTimer)\n this.broadcastTimer = setInterval(() => this.flushLiveBroadcasts(), next)\n if (typeof this.broadcastTimer.unref === 'function') this.broadcastTimer.unref()\n }\n\n /**\n * dirty 인스턴스 브로드캐스팅 flush(주기 tick 또는 명시 호출) — **시뮬과 라이브 둘 다.**\n *\n * 예전에는 라이브만 봤다(`mode !== 'live'` 면 건너뜀). 시뮬은 delta 마다 곧바로 브로드캐스팅했고, 그것이\n * 한 tick 에서 수백 번 반복되며 이벤트 루프를 막았다(위 `start()` 주석의 35초 틱). 브로드캐스팅을 모으는\n * 규율은 모드의 성질이 아니라 **채널의 성질**이다 — 최신-상태 채널이면 중간 상태는 보낼 값이 없다.\n */\n static flushLiveBroadcasts(): void {\n const now = Date.now()\n const flushStart = performance.now()\n for (const inst of Object.values(this.instances)) {\n const isLive = inst.mode === 'live'\n /*\n * 처리량 계측(④-1) — 창(≥1s)마다 유입·브로드캐스팅·저널률 갱신. dirty 무관(유휴면 0으로 수렴).\n *\n * **두 구동을 함께 센다** (2026-08-20). 예전에는 `isLive ? … : undefined` 로 시뮬을 잘라 냈다.\n * 그래서 도는 트윈 대부분이 시뮬인 서버에서 「초당 몇 행을 쓰나」에 답할 자리가 없었다 — 저널 쓰기를\n * 배치로 고친 뒤에도 그 효과를 숫자로 볼 수 없었다. 유입(`ingestRate`)은 시뮬에서 0 으로 수렴하고,\n * 그것이 사실이다(원본에서 받는 것이 없다).\n */\n const m = inst.metrics\n if (m) {\n const dt = (now - m._windowStartMs) / 1000\n if (dt >= 1) {\n m.ingestRate = Math.round(m._accIngest / dt)\n m.broadcastRate = Math.round((m._accBroadcast / dt) * 10) / 10\n m.journalRate = Math.round(m._accJournal / dt)\n m._accIngest = 0; m._accBroadcast = 0; m._accJournal = 0; m._windowStartMs = now\n }\n }\n if (!inst.dirty) continue\n inst.dirty = false\n /* 주기마다 한 번은 범위를 버리고 전부 만든다 — 사건 없이 값이 바뀌는 자리에 대한 그물. */\n const left = (inst.fullBroadcastCountdown ?? 0) - 1\n if (left <= 0) {\n inst.fullBroadcastDue = true\n inst.fullBroadcastCountdown = this.FULL_BROADCAST_EVERY\n } else {\n inst.fullBroadcastCountdown = left\n }\n // ① 엔티티 data(tag) 브로드캐스팅 — 보드 컴포넌트 라이브 렌더.\n this.publishEntityData(inst)\n if (m) { m.broadcastTotal++; m._accBroadcast++ }\n /* ③ 저널 배치 기록 — **두 구동이 같은 문을 쓴다**(시뮬도 여기서 흘린다, §7.1). */\n this.flushJournal(inst)\n /* 여기서부터는 **라이브만**이다: 시뮬의 state 채널은 자기 콜백이 델타마다 보내므로(리비전이 커널의\n 것이다) 여기서 또 보내면 같은 신호가 두 번 간다. 저널은 위에서 이미 두 구동 몫을 흘렸다. */\n if (!isLive) continue\n // ② State 채널 브로드캐스팅 — \"바뀌었다\"는 가벼운 신호만(kind+revision). 맵 구독(subscribeTwinState)은 이 신호에\n // scheduleRefresh(250ms 디바운스)→pollLive 로 되물어봄. 스냅샷(O(state))은 보는 사람이 물을 때만 1회 계산.\n // (여기서 payload 로 스냅샷을 실으면 아무도 안 읽는데 tick 마다 통째로 떠서 순수 낭비 — 신호만 보낸다.)\n this.publishGuarded(\n 'twin-state',\n { twinState: { instanceId: inst.id, kind: 'delta', revision: inst.revision ?? 0 } },\n `twin-state:${inst.id}`\n )\n }\n /* 가동 중인 인스턴스가 하나도 없으면 tick 을 멈춘다(예전엔 「라이브가 없으면」이었는데, 이제\n 시뮬도 이 flush 에 기대므로 그 조건이면 시뮬 브로드캐스팅이 멈춘 채 남는다). */\n if (!Object.keys(this.instances).length && this.broadcastTimer) {\n clearInterval(this.broadcastTimer)\n this.broadcastTimer = undefined\n this.broadcastPeriodMs = this.BROADCAST_COALESCE_MS\n return\n }\n /* 이번 flush 가 얼마를 썼는지로 다음 주기를 정한다 — 브로드캐스팅이 루프를 다 쓰지 못하게. */\n this.adjustBroadcastPeriod(performance.now() - flushStart)\n }\n\n /**\n * 저널 행 한 줄 — **기록 경로가 둘이라(라이브 벌크·심 단건) 행 모양은 반드시 한 곳에서 만든다.**\n * 두 곳에 각자 적으면 승격 검색 키가 한쪽에만 채워지고, 반쯤 빈 색인은 \"저널에는 있는데\n * 검색으로는 안 나오는 이벤트\" 를 만든다 — 저널에서 가장 나쁜 종류의 결함이다.\n */\n /** 저널의 시각 축은 날짜다 — 못 읽는 값은 비운다(0 이나 지금으로 위장하지 않는다). */\n private static toEventTimeValue(v: any): Date | undefined {\n if (v instanceof Date) return v\n const t = typeof v === 'string' ? Date.parse(v) : NaN\n return Number.isNaN(t) ? undefined : new Date(t)\n }\n\n private static journalRow(repo: any, domainId: string, instanceId: string, e: any, revision: number, structureRev?: number) {\n return repo.create({\n domain: { id: domainId } as any,\n instanceId,\n eventType: e?.eventType,\n /* 커널이 커맨드에서 이어 준 값 — 이것이 감사 기록과 저널을 잇는 다리다. */\n correlationId: e?.correlationId,\n revision,\n /* **이 사실이 일어난 공장**을 함께 찍는다 — 이것이 없으면 나중에 구조가 바뀌었을 때 이 행을\n 새 공장에 대고 접게 되고, 그때 없던 설비에서 일이 있었던 것처럼 보인다. */\n ...(structureRev === undefined ? {} : { structureRev }),\n /* 커널은 ISO 문자열을 준다. 컬럼은 날짜다 — **여기서 옮긴다.** 문자열을 그대로 넣으면\n 드라이버가 제 형식으로 정규화하지 않아, 나중에 날짜로 거는 질의에 안 걸린다. */\n eventTime: this.toEventTimeValue(e?.eventTime),\n ...twinEventKeys(e),\n payload: e\n })\n }\n\n /**\n * 이 트윈이 지금 어느 구조로 도는가 — 이벤트에 찍을 번호. 한 번 읽고 캐시한다(쓰기마다 조회 금지).\n *\n * 없으면 `undefined` 다 — 0 이 아니다. 구조 리비전이 생기기 전에 만들어진 트윈은 아직 리비전이\n * 없고, 그 사실을 0 이라는 **유효해 보이는 번호**로 위장하면 안 된다.\n */\n /** 구조 리비전 캐시 — `null` 은 **없다는 것을 알고 있다**는 뜻이다(모름과 구별한다, §7.1). */\n private static structureRevCache: Record<string, number | null> = {}\n static async structureRevOf(domainId: string, instanceId: string): Promise<number | undefined> {\n const key = runtimeKey(domainId, instanceId)\n const cached = this.structureRevCache[key]\n /*\n * **없다는 것도 답이다** — 예전에는 찾지 못하면 캐시하지 않았다(`if (latest) …`). 그래서 구조 행이\n * 없는 트윈은 **부를 때마다 SELECT** 했고, 그 경로가 델타마다 불리고 있었다(§7.1). `null` 로 기억한다.\n */\n if (cached !== undefined) return cached === null ? undefined : cached\n const latest = await getRepository(TwinStructure).findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n this.structureRevCache[key] = latest ? latest.rev : null\n return latest?.rev\n }\n\n /** 계기 한 벌 — **두 구동이 같은 것을 든다**(한쪽만 들면 그 구동은 물어도 답이 없다). */\n private static newMetrics(): TwinMetrics {\n return { ingestedTotal: 0, broadcastTotal: 0, journaledTotal: 0, ingestRate: 0, broadcastRate: 0, journalRate: 0, backlog: 0, _accIngest: 0, _accBroadcast: 0, _accJournal: 0, _windowStartMs: Date.now() }\n }\n\n /**\n * 모아 둔 저널을 **한 번에** 쓴다 — 두 구동이 같은 문을 쓴다 (§7.1).\n *\n * ── 왜 한 함수인가 ─────────────────────────────────────────────────────────\n * 쓰는 자리가 둘이면(주기 flush · 정지) 한쪽만 고쳐지고, 그 어긋남은 **사실이 조용히 사라지는**\n * 모양으로 나타난다. 그래서 흘리는 규칙을 여기 한 곳에 둔다.\n *\n * ── 리비전을 누가 매기나 ───────────────────────────────────────────────────\n * · 라이브 — 원천은 리비전을 주지 않으므로 **호스트가** 이어 붙인다(저널 high-water 에서 시드).\n * · 시뮬 — **커널의 리비전**이 실려 온다(저널이 그것으로 접히고 시간여행이 그것을 딛는다).\n * 그래서 버퍼는 두 모양을 함께 든다: 봉투만 있으면 라이브, `{ event, revision }` 이면 시뮬이다.\n */\n private static flushJournal(inst: InstanceRuntime): Promise<void> {\n const batch = inst.pendingJournal\n if (!batch?.length) return Promise.resolve()\n inst.pendingJournal = []\n const m = inst.metrics\n /* 쓴 건수는 누적에, **지금 남은 것**은 backlog 에. 이 자리에서 배치 크기를 backlog 로 적으면\n 정상적인 배치 저장이 화면에서 경고로 보인다(2026-08-21 교정). */\n if (m) { m.journaledTotal += batch.length; m._accJournal += batch.length; m.backlog = inst.pendingJournal?.length ?? 0 }\n\n /* 시뮬은 자기 리비전을 들고 온다 — 그대로 쓴다. 라이브는 여기서 이어 붙인다. */\n const carried = batch.filter((b: any) => b && typeof b === 'object' && 'event' in b && typeof b.revision === 'number')\n const plain = batch.filter((b: any) => !(b && typeof b === 'object' && 'event' in b && typeof b.revision === 'number'))\n\n const tJournal = performance.now()\n const done = () => recordPhase(inst.load ?? (inst.load = newLoadMeter()), 'journal', performance.now() - tJournal)\n const jobs: Promise<void>[] = []\n\n if (carried.length) jobs.push(this.persistCarried(inst.domainId, inst.id, carried))\n if (plain.length && inst.revision != null) {\n const start = inst.revision\n inst.revision = start + plain.length\n jobs.push(this.persistBatch(inst.domainId, inst.id, plain, start))\n }\n if (!jobs.length) return Promise.resolve()\n /*\n * **약속을 돌려준다** — 주기 flush 는 기다리지 않지만(핫 경로) **정지는 기다려야 한다.** 기다리지\n * 않으면 곧바로 이어지는 저널 재생이 아직 안 쓰인 구간을 못 보고, 웜스타트가 「없던 일」로 시작한다\n * (실제로 그렇게 깨졌다: 확보분을 든 오더가 되살아나지 못했다).\n */\n const written = carried.length + plain.length\n return Promise.all(jobs)\n .then(() => {\n done()\n /*\n * **적힌 뒤에 적는다** — 실패한 배치를 「남았다」고 세면 추이가 없는 사실을 있다고 말한다.\n * 창(10분)에 쌓이므로 재기동 뒤에도 「지난 여섯 시간 얼마나 적었나」를 답할 수 있다.\n */\n this.recordJournalWrite(inst.domainId, inst.id, written)\n })\n .catch(err => twinError('twin journal flush fail', err))\n }\n\n /**\n * 커널이 매긴 리비전을 그대로 들고 벌크 저장 — 시뮬 경로.\n *\n * 예전에는 이 경로가 **델타마다 한 행씩** 저장했다(그리고 행마다 구조 리비전을 물었다). 규모에서 그것이\n * 호스트를 먹었다(§7.1 실측). 여기서 구조 리비전은 **한 번만** 묻는다.\n */\n static async persistCarried(domainId: string, instanceId: string, items: { event: any; revision: number }[]): Promise<void> {\n const repo = getRepository(TwinEvent)\n const structureRev = await this.structureRevOf(domainId, instanceId)\n const rows = items.map(it => this.journalRow(repo, domainId, instanceId, it.event, it.revision, structureRev))\n await this.insertRows(repo, rows)\n }\n\n /**\n * 저널 행을 넣는다 — **넣기만 한다**(2026-08-20).\n *\n * 예전에는 `save()` 였다. 그런데 `save` 는 넣은 뒤 생성 컬럼을 읽으려고 **행마다 SELECT 를 한 번 더**\n * 한다(시험 로그에서 그 질의가 그대로 보였다: `SELECT … FROM twin_events WHERE id = ?`). 저널은\n * append-only 이고 부르는 쪽은 돌려받은 엔티티를 쓰지 않으므로 그 왕복이 순수 낭비다.\n *\n * 묶음은 **나눠서** 넣는다: 한 문에 열이 열다섯인 행을 수천 개 실으면 드라이버의 파라미터 한계에\n * 걸린다(pg 는 65,535개). 500행이면 어느 드라이버에서도 안전하다.\n */\n private static async insertRows(repo: any, rows: any[]): Promise<void> {\n const CHUNK = 500\n /*\n * ── 한 트랜잭션으로 감싸 보았고, **되돌렸다** (2026-08-22 실측) ─────────────\n * 「청크마다 커밋하면 fsync 가 그만큼 늘어난다」는 이유로 전체를 한 트랜잭션에 감쌌다. 쓰기 자체는\n * 실제로 빨라졌다 — 느린 질의 목록에서 이 INSERT 가 사라졌다. **그런데 서버가 더 느려졌다.**\n *\n * 감싸기 전 느린 질의 최대 32.3초 · ROLLBACK 없음\n * 감싼 뒤 느린 질의 최대 50.2초 · ROLLBACK 36.3초 등장\n *\n * 기전은 드라이버다. TypeORM 의 sqlite 드라이버는 연결을 **하나**만 든다(풀 없음). 트랜잭션이\n * 열려 있는 동안 그 유일한 연결은 이 묶음의 것이므로, **묶음이 끝날 때까지 앱의 모든 질의가\n * 기다린다.** 청크마다 커밋하면 그 사이에 다른 질의가 끼어들 자리가 생긴다 — fsync 를 더 치르는\n * 대신 **머리 막힘이 짧아진다.**\n *\n * 즉 여기서는 「커밋 수를 줄이는 것」이 목적이 아니다. 목적은 **한 번에 오래 붙잡지 않는 것**이다.\n * 저널 묶음의 원자성은 그 대가를 치를 만큼의 값이 아니다: 저널은 append-only 이고 리비전이\n * 이어지므로, 절반만 들어간 묶음은 다음 기동의 replay 가 그 지점부터 이어받는다.\n *\n * 연결 풀이 있는 드라이버(postgres·mysql)에서는 판단이 달라질 수 있다 — 그때는 이 주석을 근거로\n * 다시 재고 정하라. **드라이버마다 다른 결론이 나는 자리다.**\n */\n for (let i = 0; i < rows.length; i += CHUNK) await repo.insert(rows.slice(i, i + CHUNK))\n }\n\n /** live 저널 배치 기록 — 모아둔 CanonicalEnvelope 들에 startRevision+1.. 을 부여해 벌크 저장(coalescer tick 당 1회). */\n static async persistBatch(domainId: string, instanceId: string, envelopes: any[], startRevision: number): Promise<void> {\n const repo = getRepository(TwinEvent)\n const structureRev = await this.structureRevOf(domainId, instanceId)\n const rows = envelopes.map((e, i) => this.journalRow(repo, domainId, instanceId, e, startRevision + i + 1, structureRev))\n await this.insertRows(repo, rows)\n }\n\n /** 레지스트리 upsert(도메인+instanceId 유니크). status 인자로 provision(stopped)/start(running) 공용. */\n static async register(\n domainId: string,\n instanceId: string,\n kind: string,\n model: TwinModelDef,\n status: 'running' | 'stopped' = 'running',\n restartPolicy?: RestartPolicy,\n origin?: any,\n /*\n * 사람이 부르는 이름과 **누가 했나** — 업무키를 나눠 둔 대가로 이름을 함께 실어야 한다.\n * 사람 없는 경로(부팅 자동 프로비저닝·복구)는 `actor` 를 주지 않는다 — 아무 사용자를 적으면\n * 감사 기록이 거짓이 된다.\n */\n meta?: { name?: string; description?: string; actor?: { id: string } }\n ): Promise<void> {\n const repo = getRepository(TwinInstance)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n instanceId,\n kind,\n model,\n // 인스턴스↔공간 1급 링크(space #3) — model.spaceId/areaId 를 컬럼으로 승격(dual-write). model JSON 도 유지(커널·복구용).\n spaceId: (model as any)?.spaceId ?? existing?.spaceId,\n areaId: (model as any)?.areaId ?? existing?.areaId,\n /* 재기동 정책(ADR-0029 §2) — 명시값 우선, 없으면 기존값 보존(재프로비전이 선언을 지우지 않게).\n **둘 다 없으면 오류를 낸다**: 예전에는 여기서 기본값을 각인했는데, 그 기본값이 「저널 초기화」라서\n 선언을 빠뜨린 프로비저닝이 조용히 이력을 지우는 트윈을 만들었다. 선언은 부르는 쪽의 몫이다. */\n restartPolicy:\n restartPolicy ??\n readRestartPolicy(\n existing?.restartPolicy,\n `register(\"${instanceId}\") did not declare a restart policy and the stored row has none`\n ),\n /* 용도도 각인한다. 벤치로 뒤집는 것은 `setPurpose` 하나뿐이므로 기존값을 반드시 보존한다\n — 여기서 덮으면 재프로비전이 벤치 사본을 운영 트윈으로 되돌린다. */\n purpose: existing?.purpose ?? 'operational',\n /* **다시 읽는 방법**을 각인한다. 명시값 우선, 없으면 기존값 보존 — 원천을 모르는 호출이\n 한 번 지나가면서 이미 알던 것을 지워 버리면, 그 트윈은 다시 읽을 수 없는 트윈이 된다. */\n origin: origin ?? existing?.origin ?? null,\n /* 이름은 **덮지 않고 채운다** — 사용자가 고친 이름을 재프로비전이 되돌리면 안 된다. */\n name: existing?.name ?? meta?.name ?? null,\n description: existing?.description ?? meta?.description ?? null,\n /* 만든 사람은 처음 한 번만. 고친 사람은 사람이 한 경우에만 갱신한다. */\n ...(existing ? {} : meta?.actor ? { creator: { id: meta.actor.id } as any } : {}),\n ...(meta?.actor ? { updater: { id: meta.actor.id } as any } : {}),\n status\n })\n )\n }\n\n /**\n * 라이브 구조 변이(resource.add 등)를 저장된 model 에 반영 — 런타임 커널의 무버를 registry model.equipment 에 동기.\n * 이게 없으면 런타임엔 추가돼도(상태·저널엔 반영) 저장 model 는 원본이라 프로비저닝 편집기·재기동(loadTwinModel)이\n * 추가분을 잃는다. 기존 model.equipment 항목은 보존(homeLocation 유지)하고 새 id 만 append(추가 시점 location=homeLocation).\n * 좌표(layout)만 다루는 register 와 달리 equipment 집합을 갱신하나, 재프로비전(purge)이 아니라 in-place 갱신이라\n * 저널은 보존된다(추가는 이미 equipment 델타로 저널됨 → replay 는 id-keyed upsert 라 이중계산 없음).\n */\n static async syncBoardEquipment(domainId: string, instanceId: string): Promise<void> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n const snap = inst?.kernel?.getSnapshot?.()\n if (!snap?.equipment) return\n const repo = getRepository(TwinInstance)\n const reg = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) return\n const model = reg.model as TwinModelDef\n const known = new Set((model.equipment ?? []).map(m => m.id))\n const added = snap.equipment\n .filter((m: any) => !known.has(m.id))\n .map((m: any) => ({ id: m.id, kind: m.kind, homeLocation: m.location }))\n if (!added.length) return\n model.equipment = [...(model.equipment ?? []), ...added]\n reg.model = model\n await repo.save(reg)\n }\n\n /**\n * 프로비저닝 — 레지스트리에 구조(model)를 등록만 하고 기동하지 않음(status='stopped').\n * 재프로비전 시 구조 시그니처가 바뀌면(노드·무버 집합/속성 변경) 기존 저널을 purge 한다(ADR-0015):\n * model 는 replay 의 마스터라 구조가 바뀌면 과거 이벤트의 전제가 깨진다. 좌표(layout)만 바뀌면 저널 보존.\n */\n /**\n * 실행 중이면 구조를 교체하지 않는다 — **판정 문장을 한 곳에 둔다.**\n *\n * 인제스트는 전량 교체라, 이벤트를 접고 있는 커널 밑에서 바닥을 바꾸는 셈이 된다. 지금은 거절이\n * 유일한 답이지만 최종형은 아니다(`adoptStructure` 배선). 두 곳에서 같은 문장으로 거절해야\n * 나중에 이 규칙을 걷어낼 때 걷어낼 것이 하나로 보인다.\n */\n private static assertNotRunning(domainId: string, instanceId: string): void {\n if (!this.instances[runtimeKey(domainId, instanceId)]) return\n /*\n * **거절도 번역돼야 한다.** 이 문장은 전달되어 리졸버의 `catch` 를 지나 화면 토스트에 그대로\n * 떴다 — 다섯 언어 제품에서 영어 한 줄이 사용자에게 보였다(2026-08-14 실측).\n *\n * 그래서 코드와 파라미터를 예외에 실어 보낸다(`ImportSpaceRefusal` 과 같은 규약: 영어 문장은\n * canonical 이고 로그·폴백으로만 쓰인다). 이유가 코드로 오면 화면이 옮길 수 있다.\n */\n const err: any = new Error(`instance \"${instanceId}\" is running — stop before re-provisioning`)\n err.code = 'twin-running'\n err.params = { instanceId }\n throw err\n }\n\n /**\n * 돌면서 공장을 전환한다 — **미러 전용.**\n *\n * 미러가 비추는 현실은 안 멈춘다. 설비 한 대가 늘었다고 트윈을 멈췄다 세우면 그 사이의 사실을\n * 잃고, 라이브에서 유실은 곧 거짓이다. 그래서 미러는 **동작 중에** 새 구조를 받는다.\n *\n * 시뮬레이션은 여기 오지 않는다. 조건이 바뀐 실험은 다른 실험이므로 멈추고 다시 세우는 것이\n * 옳다 — 커널이 그렇게 거절한다(`FlowEngine.adoptStructure`).\n *\n * 세 가지가 **함께** 일어나야 한다. 하나라도 빠지면 층이 어긋난다:\n * ① 리비전 — 이 시점 이후의 이벤트가 새 번호를 달고 다닌다(재생이 마디를 나눌 수 있게)\n * ② 저장 model·구조 행 — 조회가 새 구조를 본다\n * ③ 커널 — 지금 접히는 이벤트가 새 구조 위에서 접힌다\n */\n static async adoptStructure(\n domainId: string,\n instanceId: string,\n model: TwinModelDef,\n comment?: string,\n origin?: any\n ): Promise<{ rev: number } & StructureShift> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n if (!inst) throw new Error(`instance \"${instanceId}\" is not running — provision it instead of adopting`)\n if (inst.mode !== 'live')\n throw new Error(`instance \"${instanceId}\" is a simulation — stop it and re-provision (a changed experiment is a different experiment)`)\n\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg) throw new Error(`instance \"${instanceId}\" is running but not registered — refusing to adopt into an unknown twin`)\n\n const rev = await this.recordStructure(domainId, instanceId, model, comment)\n await this.register(domainId, instanceId, reg.kind, model, 'running', undefined, origin)\n /* 커널을 **마지막에** 전환한다 — 저장이 실패하면 메모리만 새 구조가 되어, 재기동하면 조용히\n 옛 구조로 돌아간다(고치기 어려운 어긋남이다). */\n const shift: StructureShift = inst.kernel.adoptStructure(model)\n /*\n * **공정 명세·현장이 정한 시간도 함께 싣는다** — 커널의 구조 전환은 자리·설비를 갈지만, 공정 시간은\n * 호스트가 실어 주는 것이므로(`model.localDurations`) 여기서 다시 부르지 않으면 돌고 있는 미러는\n * 재기동할 때까지 옛 시간으로 돈다(화면은 「넣었습니다」라고 말한 값이다).\n */\n this.applyOperations(inst.kernel, model, instanceId)\n\n /*\n * **투영 행도 새 구조를 따른다** (2026-08-18 실측으로 붙임).\n *\n * 행(`twin_locations`·`twin_equipment`)은 구조의 캐시다. 그런데 이 경로는 커널만 갈고 행은 그대로\n * 두었다 — 돌고 있는 미러에 값을 선언하면 커널은 새 값으로 계산하는데 **항목 패널은 옛 행을 보여\n * 준다**(넣은 값이 화면에서 보이지 않는다). 구조가 바뀐 순간이 곧 캐시를 다시 그릴 순간이다.\n *\n * 실패는 흡수한다: 투영이 막혀도(예: 모델에 중복 id) 커널은 이미 새 구조로 돌고 있으므로 그 사실을\n * 되돌리지 않는다 — 다만 조용히 넘기지 않고 말한다.\n */\n await projectStructure(domainId, instanceId, model, instanceId).catch((err: any) =>\n twinWarn(`[twin-engine] \"${instanceId}\" adopted a new structure but its projected rows were not refreshed — ${err?.message ?? err}`)\n )\n\n /*\n * **구조가 바뀐 순간이 상태가 바뀐 순간이다** — 그러니 브로드캐스팅한다.\n *\n * ── 무엇이 났나 (2026-08-18) ────────────────────────────────────────────\n * 구조 전환은 커널만 갈고 조용히 끝났다. 그런데 화면이 보는 것 상당수가 구조에서 파생된다 —\n * 계약 대비 판정, 주목 신호, 자리 색. 현장이 계약을 고쳐 선언한 순간 조건이 성립하는데도, 상태\n * 브로드캐스팅이 없어서 지도 레일은 **다음 계측 표본이 올 때까지** 옛 화면을 들고 있었다(그 사이 헤더\n * 배지는 4초 폴링으로 먼저 알아, 「배지엔 있고 목록엔 없는」 어긋난 화면이 실제로 보였다).\n *\n * 새 브로드캐스팅 경로를 만들지 않는다: dirty 를 세워 **이미 있는 병합 규율**(200ms)에 얹는다. 구조 전환은\n * 드물지만, 여러 트윈에 잇달아 들어올 수 있고(현장 일괄 선언) 그때도 브로드캐스팅률 상한은 지켜야 한다.\n */\n inst.dirty = true\n /* 구조가 갈렸으면 무엇이 달라졌는지 사건으로 말할 수 없다 — 전부 다시 만든다. */\n this.markItemsDirty(inst)\n this.ensureBroadcastCoalescer()\n\n return { rev, ...shift }\n }\n\n static async provision(\n domainId: string,\n instanceId: string,\n kind: string,\n model: TwinModelDef,\n /**\n * **재기동 정책은 생성 시점의 선언이다**(ADR-0029 §2) — 트윈은 정책 없이 존재할 수 없다.\n *\n * 예전에는 이 자리가 없었고 `register` 가 기본값(`sim-experiment` = 저널 초기화)을 각인했다. 그래서\n * 선언을 빠뜨린 프로비저닝이 **재기동마다 이력을 지우는 트윈**을 조용히 만들었다. 이제 만드는 쪽이\n * 말해야 한다: 이 트윈이 자기 과거를 어떻게 대하는지는 만드는 사람이 아는 사실이다.\n */\n restartPolicy: RestartPolicy,\n comment?: string,\n origin?: any,\n /** 이름·저자 — 업무키를 나눠 둔 대가로 이름을 함께 남긴다(`register` 의 `meta` 그대로). */\n meta?: { name?: string; description?: string; actor?: { id: string } }\n ): Promise<void> {\n this.assertNotRunning(domainId, instanceId)\n /* 종류를 **저장하기 전에** 검증한다. 나중에 기동할 때 걸리면 원인이 프로비저닝에서 멀어지고,\n 그 사이 레지스트리에는 돌릴 수 없는 트윈이 앉아 있다. */\n kernelFor(kind)\n const repo = getRepository(TwinInstance)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n\n /*\n * **구조가 바뀌어도 역사를 지우지 않는다.**\n *\n * 예전에는 서명이 다르면 그 트윈의 저널을 통째로 지웠다. 안 지우면 옛 이벤트를 새 공장에 대고\n * 접게 되어 이력이 거짓말을 했기 때문이다 — 부스가 둘이던 시절의 사실을 여섯 개짜리 공장에\n * 접으면 그때 없던 부스에서 일이 있었던 것처럼 보인다. 선택지가 **역사를 잃거나 거짓말을\n * 하거나** 둘뿐이었고, 그래서 공장을 고칠 때마다 이력을 버려야 했다.\n *\n * 이제 셋째 길로 간다: 바뀐 구조를 **새 리비전**으로 남기고, 앞으로 쓰이는 이벤트가 그 번호를\n * 달고 다닌다. 재생은 구조가 바뀌는 지점에서 전환한 뒤 이어 접는다(`replaySegments`).\n */\n await this.recordStructure(domainId, instanceId, model, comment)\n await this.register(domainId, instanceId, kind, model, existing?.status === 'running' ? 'stopped' : (existing?.status as any) ?? 'stopped', restartPolicy, origin, meta)\n }\n\n /**\n * 이 구조를 리비전으로 남기고 그 번호를 돌려준다 — **바뀌었을 때만** 새 번호가 생긴다.\n *\n * 프로비저닝은 부팅마다 다시 도는데, 그때마다 리비전이 늘면 이력이 뜻 없는 마디로 잘게 쪼개진다.\n * 그래서 **구조 서명이 같으면 있던 리비전을 그대로 쓴다.**\n */\n static async recordStructure(domainId: string, instanceId: string, model: TwinModelDef, comment?: string): Promise<number> {\n const repo = getRepository(TwinStructure)\n const signature = this.structureFingerprint(model)\n const latest = await repo.findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n\n /*\n * **저장된 지문이 아니라 저장된 공장과 비교한다.**\n *\n * 지문 계산 방식을 한 번이라도 바꾸면(원문 → 해시로 바꿨다) 저장된 문자열은 전부 옛 방식의\n * 것이라 무엇과도 안 맞는다. 그러면 **아무것도 안 바뀐 트윈들이 전부 \"구조가 바뀌었다\"** 로\n * 기록된다 — 실제로 그렇게 됐고, 재기동 한 번에 리비전이 통째로 하나씩 늘었다.\n *\n * 그래서 안 맞을 때 한 번 더 묻는다: 저장된 **모델**로 지문을 다시 계산하면 같은가? 같다면\n * 공장은 그대로이고 지문 표기만 낡은 것이니, 리비전을 만들지 않고 표기만 고친다.\n */\n if (latest && latest.signature !== signature && this.structureFingerprint(latest.model as TwinModelDef) === signature) {\n latest.signature = signature\n await repo.save(latest)\n }\n\n if (latest?.signature === signature) {\n this.structureRevCache[runtimeKey(domainId, instanceId)] = latest.rev\n return latest.rev\n }\n\n const rev = (latest?.rev ?? 0) + 1\n await repo.save(repo.create({ domain: { id: domainId } as any, instanceId, rev, signature, model: model as any, ...(comment ? { comment } : {}) }))\n this.structureRevCache[runtimeKey(domainId, instanceId)] = rev\n /* 구조가 바뀌면 재구성 캐시는 옛 공장의 것이다 — 버린다(지우는 건 캐시뿐, 사실은 남는다). */\n delete this.recovered[runtimeKey(domainId, instanceId)]\n if (latest) console.info(`[twin-engine] \"${instanceId}\" structure changed → revision ${rev} (history kept; older events stay under revision ${latest.rev}).`)\n return rev\n }\n\n /**\n * 이 트윈이 거쳐 온 구조들 — **무엇이 언제 달라졌나.**\n *\n * 리비전은 그 시절 공장을 통째로 담지만(재생에 필요하다), 사람이 보고 싶은 것은 통째가 아니라\n * 차이다. 모델은 빼고 **차이 요약만** 내보낸다 — 62KB 짜리 보드를 화면에 실어 보낼 이유가 없다.\n */\n static async structureHistory(\n domainId: string,\n instanceId: string\n ): Promise<{ rev: number; createdAt?: Date; comment?: string; events: number; diff: StructureDiff }[]> {\n const revs = await getRepository(TwinStructure).find({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'ASC' } })\n if (!revs.length) return []\n\n /* 리비전마다 그 아래에서 몇 건이 일어났나 — 이력의 무게를 보여준다(짧게 스쳐간 구조인지). */\n const counts = new Map<number | null, number>()\n for (const row of await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select('e.structureRev', 'rev')\n .addSelect('COUNT(1)', 'n')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n .groupBy('e.structureRev')\n .getRawMany())\n counts.set(row.rev === null || row.rev === undefined ? null : Number(row.rev), Number(row.n))\n\n /* 번호 없는 옛 행은 **가장 오래된 리비전**의 몫이다 — 재생이 그렇게 접으므로 세는 것도 같아야 한다. */\n const oldest = revs[0].rev\n const legacy = counts.get(null) ?? 0\n\n return revs.map((r, i) => ({\n rev: r.rev,\n createdAt: r.createdAt,\n ...(r.comment ? { comment: r.comment } : {}),\n events: (counts.get(r.rev) ?? 0) + (r.rev === oldest ? legacy : 0),\n diff: diffStructures(i === 0 ? undefined : (revs[i - 1].model as any), r.model as any)\n }))\n }\n\n /** 지금 쓰이는 구조 리비전 — 이벤트에 찍을 번호. 아직 없으면 기록하며 만든다. */\n static async currentStructureRev(domainId: string, instanceId: string, model?: TwinModelDef): Promise<number | undefined> {\n const latest = await getRepository(TwinStructure).findOne({ where: { domain: { id: domainId }, instanceId }, order: { rev: 'DESC' } })\n if (latest) return latest.rev\n return model ? this.recordStructure(domainId, instanceId, model) : undefined\n }\n\n /** 구조 동일성 지문 — 좌표(layout) 등 뷰 관심사는 제외하고 커널이 보는 위상·용량·무버만. */\n /**\n * 지문을 **64자로 줄인다** — 컬럼이 varchar(64) 다.\n *\n * 원문 지문은 자리·설비를 전부 이어 붙인 문자열이라 큰 공장에서는 수만 자가 된다. sqlite 는\n * 길이를 강제하지 않아 그냥 들어가지만 **Postgres 는 거기서 터진다** — 개발에서는 멀쩡하고\n * 운영에서만 죽는 종류의 실패다. 비교에만 쓰는 값이므로 해시로 충분하다.\n */\n private static structureFingerprint(model: TwinModelDef): string {\n return createHash('sha256').update(this.structureSignature(model)).digest('hex')\n }\n\n private static structureSignature(model: TwinModelDef): string {\n const locations = [...(model.locations ?? [])]\n .map(n => `${n.id}:${n.type}:${n.capacity}`)\n .sort()\n .join('|')\n const equipment = [...(model.equipment ?? [])]\n .map(m => `${m.id}:${m.kind}:${m.homeLocation}`)\n .sort()\n .join('|')\n return `N[${locations}]M[${equipment}]`\n }\n\n /** 레지스트리 model 로 기동(프로비전된 인스턴스 start). model 인자 없이 저장된 구조로 재기동. */\n static async startFromRegistry(domainId: string, instanceId: string, restartPolicy?: RestartPolicy): Promise<InstanceRuntime> {\n const key = runtimeKey(domainId, instanceId)\n if (this.instances[key]) return this.instances[key]\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) throw new Error(`instance \"${instanceId}\" not provisioned (no model)`)\n\n /*\n * ── 선언된 `restartPolicy` 가 **기동 방식을 정한다** (2026-08-20) ──────────\n *\n * 예전에는 이 함수가 정책을 **읽어서 넘기기만** 했고, 기동은 언제나 시뮬 경로였다. 그래서 미러로\n * 선언한 트윈을 화면에서 시작하면 **시뮬로 떴다** — 그 트윈은 유입을 받지 못한다(`ingestLive` 는\n * 라이브가 아니면 0 을 돌려준다). 오류는 나지 않고, 화면에는 「running」이라 적힌다.\n *\n * 부팅 경로(`resumeRow`)에는 그 갈림이 있었는데 여기에는 없었다. 즉 **부팅으로 살아난 미러는\n * 받고, 사람이 시작한 미러는 받지 못했다.** 같은 선언이 두 결과를 내는 것은 결함이다.\n *\n * 갈림을 여기 한 곳에 둔다 — 부팅도 이 문을 지난다.\n *\n * ── `reset` 은 선언대로 **저널을 비운다** (2026-08-20) ───────────────────\n * 「seed 재현」은 백지에서 다시 시작한다는 뜻이다. 예전에는 그 선언이 구현되지 않아 `reset` 트윈이\n * 사실상 이어졌고, 그래서 「이 트윈의 이력은 왜 재기동을 넘겨 남아 있나」를 아무도 설명할 수 없었다.\n *\n * 이것은 **사실을 지우는 동작**이라 순서를 지켜 켰다: 먼저 사람이 각 트윈의 정책을 다시 선언할 문을\n * 만들고(`setTwinRestartPolicy`), 이력을 두고 볼 트윈을 `resume` 으로 옮긴 뒤에 켠다. 그 순서를\n * 뒤집으면 선언을 지킨 대가로 남의 이력을 지운다.\n */\n const policy = restartPolicy ?? readRestartPolicy(reg.restartPolicy, `twin \"${instanceId}\"`)\n if (policy === 'resync') {\n /* 미러는 **관측 구동**으로 세운다 — 시뮬로 세우면 없던 움직임을 스스로 만든다.\n 시각 기준은 공간이 갖는다(부팅 경로와 같은 규칙). */\n return this.startLive(instanceId, domainId, reg.kind, await this.withSpaceTimeBase(reg.model as TwinModelDef, domainId))\n }\n if (policy === 'reset') {\n /*\n * 씨앗 재현 — 저널을 비우고 리비전 0 부터 다시 센다. 복구본도 함께 버린다(`resetJournal` 이 한다):\n * 남겨 두면 백지로 시작한 트윈에 옛 상태가 되살아나 「씨앗 재현」이 아니게 된다.\n *\n * **벤치 사본은 예외다.** 그것은 누군가 지켜보는 실험이고, 그 실험의 기록을 기동이 지우면 실험이\n * 사라진다(부팅은 벤치를 되살리지도 않는다 — `resumeRow`).\n */\n if (reg.purpose !== 'bench') await this.resetJournal(domainId, instanceId)\n }\n\n /*\n * 웜스타트 재료를 **여기서 확실히 확보한다.**\n * `start()` 는 동기라 스스로 캐시를 읽을 수 없어서 `recovered` 에 미리 담겨 있기를 기대하는데,\n * 그건 `bootstrap()` 이 먼저 돌았을 때만 참이다. 부팅 순서에 기대면 어떤 날은 재고가 살아나고\n * 어떤 날은 조용히 빈 채로 뜬다 — 재현되지 않는 결함이 가장 나쁘다.\n * 체크포인트 캐시 우선(O(1) + 라이브 파생상태 보존), 없으면 저널 replay 폴백(부팅과 같은 순서).\n */\n if (!this.recovered[key] && reg.purpose !== 'bench') {\n const cached = await this.warmSeedFor(domainId, instanceId).catch(() => null)\n if (cached?.state) {\n this.recovered[key] = cached\n } else {\n const state = await this.recover(domainId, instanceId).catch(() => null)\n if (state) this.recovered[key] = { revision: state.revision, state }\n }\n }\n\n /*\n * 저널에 남아 있는 마지막 번호 — **모드와 무관하게** 이것을 이어 센다.\n *\n * 저널을 초기화하고 기동하는 정책(`reset`)이라면 이 값이 0이라 아무 영향이 없다. 규칙을\n * 모드별로 구분하지 않는 이유: \"저널이 비어 있지 않으면 그 뒤부터\" 하나면 어느 모드에서도\n * 겹칠 수 없고, 모드가 늘어도 이 자리를 다시 손볼 일이 없다.\n */\n const last = await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select('MAX(e.revision)', 'max')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n .getRawOne()\n\n return this.start(\n instanceId,\n domainId,\n /* 커널 종류·현실 선언은 레지스트리에 반드시 있다(둘 다 NOT NULL). 예전에는 `?? 'wms'` 로\n 메웠는데, 그건 YMS/MES 트윈을 **조용히 WMS 로 부팅**시키는 길이었다 — 오류 없이 다른 공장이 뜬다. */\n reg.kind,\n reg.model as TwinModelDef,\n /* 저장된 값은 위에서 **엄격히** 읽었다 — 모르는 값을 기본값으로 메우면 그 트윈이 조용히 다르게 재기동한다. */\n policy,\n reg.purpose,\n Number(last?.max ?? 0) || 0\n )\n }\n\n /**\n * 선언 기반 부팅(§0 프레임 ① → 부팅 거동 매핑) — 트윈이 선언한 restartPolicy 에 따라 재기동 방식을 구분한다.\n * 부팅 경로를 한 곳에 모아 \"런타임 ≠ 현실\" 범주오류를 코드로 강제한다.\n * - 'resync' : 현실=외부 실물 → startLive(재동기). 이벤트는 어댑터 ingest 로 유입, 커널 tick 없음.\n * - 'resume' : 생성 타임라인 지속 → 저널 보존 + resume(현실 이어감).\n * ⚠ GATE(§8 ②③): 커널 상태 직렬화/재개가 아직 없어 진짜 resume 불가 → 실 필요·실부하 시 구현.\n * 그때까지는 저널을 보존하되 revision 충돌을 피하려 fresh 로 기동하고, 선언과 구현의 간극을 크게 경고한다.\n * - 'reset' : seed 재현 → resetJournal + fresh 기동(백지 시작이 버그가 아니라 선언된 거동).\n * 반환: 기동된 InstanceRuntime.\n */\n static async bootDeclared(domainId: string, instanceId: string, mode: RestartPolicy): Promise<InstanceRuntime> {\n if (mode === 'resync') {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) throw new Error(`instance \"${instanceId}\" not provisioned (no model)`)\n /*\n * ── **미러도 씨앗을 여기서 확보한다** (2026-08-24) ────────────────────────\n *\n * 이 줄이 없어서 미러는 저장된 체크포인트를 **한 번도 읽지 않았다.** `startLive` 는 동기라 스스로\n * 캐시를 읽을 수 없고 `recovered` 에 담겨 있기를 기대하는데, 그것을 담는 곳은 `bootstrap` 과\n * `start` 뿐이었다 — 그리고 미러의 실제 기동 경로는 **여기**다. 그래서 「읽는 쪽·쓰는 쪽이 다\n * 있는데 아무 일도 일어나지 않는」 상태가 됐다.\n *\n * 이것은 `start` 가 이미 배운 교훈과 같은 자리다: 부팅 순서에 기대면 어떤 날은 상태가 살아나고\n * 어떤 날은 조용히 빈 채로 뜬다 — **재현되지 않는 결함이 가장 나쁘다.** 그래서 순서에 기대지 않고\n * 이 자리에서 확보한다(이미 담겨 있으면 그것을 쓴다).\n */\n const key = runtimeKey(domainId, instanceId)\n if (!this.recovered[key]) {\n const seed = await this.warmSeedFor(domainId, instanceId).catch(() => null)\n if (seed?.state) this.recovered[key] = seed\n }\n return this.startLive(instanceId, domainId, reg.kind, reg.model as TwinModelDef)\n }\n if (mode === 'resume') {\n /*\n * **이어지는 현실** — 저널을 지우지 않는다.\n *\n * 예전에는 여기서 저널을 지우고 fresh 로 띄웠다. resume 기계장치가 없다고 봤기 때문인데,\n * 실제로 없던 것은 **번호 이어 세기 하나**였다: 상태 복원은 이미 `startFromRegistry` 가\n * 저널 재생(또는 체크포인트)으로 하고 있었고, 막힌 것은 커널이 리비전을 0부터 다시 세어\n * 기존 행과 겹치는 문제였다. 그 하나를 `resumeRevision` 으로 풀었으므로 이제 이어 간다.\n *\n * 아직 이어지지 않는 것(정직하게): 시나리오 생성기의 난수 흐름은 재기동에 이어지지 않는다 —\n * 같은 씨앗에서 다시 시작하므로 자극의 패턴이 재기동 지점에서 한 번 끊긴다. 쌓인 사실과\n * 상태는 이어지고, 앞으로 일어날 일의 무작위 순서만 새로 시작한다.\n */\n return this.startFromRegistry(domainId, instanceId, 'resume')\n }\n // `reset`: seed 재현 — 저널 초기화 후 revision 0 부터 재실행.\n await this.resetJournal(domainId, instanceId)\n return this.startFromRegistry(domainId, instanceId, 'reset')\n }\n\n /**\n * 저널 초기화 — 인스턴스 이벤트 저널 purge(레지스트리·상태는 유지).\n * 데모 fresh-start 용: 매 부팅 seed 부터 새로 실행하는 데모에서, 복구본 폐기 후 revision 0 부터 재실행하면\n * 옛 런과 revision 이 겹쳐 저널이 오염된다 → start 전에 호출해 현재 런만 남긴다.\n */\n static async resetJournal(domainId: string, instanceId: string): Promise<void> {\n await getRepository(TwinEvent).delete({ domain: { id: domainId } as any, instanceId })\n delete this.recovered[runtimeKey(domainId, instanceId)]\n /*\n * ── **체크포인트도 함께 무효로 만든다** (2026-08-20) ──────────────────────\n *\n * 저널만 지우면 씨앗 재현이 되지 않는다: 웜스타트는 체크포인트를 **먼저** 보고, 그것이 남아 있으면\n * 백지로 시작한 트윈에 옛 상태가 되살아난다(저널은 비었는데 재고가 있는 트윈이 된다).\n * 시간여행이 딛는 사슬 캐시도 같은 이유로 무효다 — 지워진 리비전을 가리키게 된다.\n *\n * 공통 캐시 서비스에는 삭제가 없다(get/set/clearStale 뿐). 그래서 **「없음」을 적는다** — 값을\n * 지어내는 것이 아니라 「체크포인트가 없다」는 사실을 적는 것이고, 읽는 쪽은 이미 `cached?.state` 로\n * 그것을 가려낸다. 공통 모듈에 삭제를 새로 뚫는 것은 이 한 자리를 위해 하기에는 큰 변경이다.\n */\n await cacheService\n .setInCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId }, { revision: 0, state: null }, this.SNAPSHOT_TTL_S)\n .catch(err => twinWarn(`[twin-engine] \"${instanceId}\" checkpoint not invalidated — a seed run may inherit old state:`, err?.message ?? err))\n await cacheService\n .setInCache(this.CHAIN_INDEX_CACHE_ID, { domainId, instanceId }, { revisions: [] }, this.SNAPSHOT_TTL_S)\n .catch(err => twinWarn(`[twin-engine] \"${instanceId}\" chain index not cleared — time travel may point at deleted revisions:`, err?.message ?? err))\n }\n\n /** 삭제 — 정지 + 레지스트리 삭제 + 저널 purge(domain 스코프). */\n static async remove(domainId: string, instanceId: string): Promise<void> {\n await this.stop(domainId, instanceId)\n this.forgetInstance(domainId, instanceId)\n await getRepository(TwinEvent).delete({ domain: { id: domainId } as any, instanceId })\n await getRepository(TwinInstance).delete({ domain: { id: domainId } as any, instanceId })\n }\n\n /**\n * 이 트윈에 대해 **메모리에 남은 것을 전부 잊는다** — 지움의 한 자리.\n *\n * 캐시가 라이프사이클과 어긋나 있었다: 저널·등록부는 지우면서 인스턴스별 캐시는 남겨, 삭제된 트윈의\n * 항목이 **서버 재기동까지 살아 있었다.** 항목 하나가 하루치 KPI 그룹을 물고 있으므로 잊지 않으면\n * 지운 트윈이 계속 메모리를 차지한다. TTL 은 값이 낡는 것을 막을 뿐 **없어진 주인을 지우지 않는다.**\n *\n * 잊을 것을 여기 모아 두는 이유: 캐시를 새로 만드는 사람이 지우는 자리를 찾아 헤매지 않게 한다.\n * 새 인스턴스별 캐시를 만들면 **이 함수에 한 줄을 더한다** — 그러지 않으면 같은 누수가 다시 생긴다.\n */\n private static forgetInstance(domainId: string, instanceId: string): void {\n const key = runtimeKey(domainId, instanceId)\n delete this.recovered[key]\n this.measuredCache.delete(key)\n delete this.structureRevCache[key]\n }\n\n /** 관리 목록 — domain 의 등록 인스턴스 전체(라이브 여부·최신 저널 revision·노드/무버 수 포함). */\n static async list(domainId: string): Promise<any[]> {\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n /*\n * **현장 이름을 함께 낸다** — 목록이 `spaceId` 만 내보내서 화면이 이름을 따로 조회하고 있었다.\n * 그 조회(`twinSpaces`)는 공간마다 카운트 쿼리를 도는 N+1 이라 느리고, 그 사이 화면은 **id 를\n * 이름처럼** 보여 준다(2026-08-13 관측: 「현장 crew-probe-site」). 한 번에 읽어 map 으로 붙이면\n * 왕복도 줄고 그 깜빡임도 사라진다. 이름이 없으면 **비운다** — id 를 이름으로 베끼지 않는다.\n */\n const spaceNameOf = new Map(\n (await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })).map(s => [s.spaceId, s.name])\n )\n /*\n * **최신 리비전은 트윈마다 인덱스 끝에서 한 행씩 읽는다.**\n *\n * ── 그룹 질의로 바꾸었다가 되돌렸다 (2026-08-22 실측) ─────────────────────\n * 예전 주석은 이랬다: 「트윈마다 `findOne(order revision DESC)` 을 돌고 있었다 — 13개면 질의\n * 13번이고, 트윈이 늘면 그대로 자란다. 한 번의 그룹 질의로 바꾼다.」\n *\n * **질의 개수를 줄였지만 일의 양을 늘렸다.**\n *\n * findOne × 13 `(domain, instance, revision)` 인덱스 **끝에서 한 행** — 각각 O(1)\n * GROUP BY 한 번 그 도메인의 저널을 **전수 집계** — O(전체)\n *\n * 저널이 작을 때는 이득이었고, 커지면서 손해가 됐다. 실측(저널 1,134만 행): 이 그룹 질의가\n * **44.7초**였다. 그리고 sqlite 드라이버는 연결이 하나이므로 그동안 앱의 모든 질의가 그 뒤에 섰다 —\n * 같은 순간 29행짜리 `twin_instances` 조회도 44.7초로 찍혔다. 이 목록은 「트윈 관리·현장 구성·\n * 엔티티 패널이 모두 읽는 자리」여서, 화면을 열 때마다 서버 전체가 그만큼 멈췄다.\n *\n * 트윈 수는 수십이고 저널은 천만이다. **작은 것을 여러 번 읽는 편이 큰 것을 한 번 훑는 것보다 싸다.**\n * 질의 개수가 트윈 수에 비례해 자라는 것은 사실이지만, 각 질의가 인덱스 끝 한 행이므로 그 성장은\n * 감당된다 — 그리고 병렬로 묻는다.\n *\n * **다시 그룹 질의로 바꾸지 말 것.** 바꾸려면 이 숫자를 먼저 다시 재라.\n */\n const tipOfInstance = new Map<string, number>()\n await Promise.all(\n rows.map(async r => {\n try {\n /*\n * **집계 하나로 묻는다 — 행을 실어 오지 않는다.**\n *\n * `findOne(order revision DESC)` 로 두었더니 두 가지가 틀렸다. ① 관계를 가진 엔티티의 정렬\n * 조회는 TypeORM 이 `DISTINCT` 로 감싸므로 `select` 로 컬럼을 좁히면 `distinctAlias.\n * TwinEvent_id` 가 없다고 터진다(실측: 모든 트윈에서 SQLITE_ERROR). ② `select` 를 떼면\n * **`payload` 까지 실어 온다** — 이 값 하나를 알려고 큰 TEXT 를 읽는다.\n *\n * 그래서 단일 집계를 쓴다. `(domain, instance, revision)` 인덱스에서 instance 가 정해지면\n * `MAX` 는 그 구간의 끝이므로 sqlite 가 끝을 집는다(실측 0.007초 · 도메인 전체 GROUP BY 는\n * 14.5초). 이 파일의 다른 자리도 같은 규율이다(§`timeRange` · 기동 시 최종 리비전).\n */\n const row = await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select('MAX(e.revision)', 'revision')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId: r.instanceId })\n .getRawOne<{ revision: unknown }>()\n /* 행이 없으면 `null` 이다 — 그때는 비워 둔다(0 은 \"아무 일도 없었다\" 는 주장이다). */\n if (row?.revision != null) tipOfInstance.set(String(r.instanceId), Number(row.revision) || 0)\n } catch (err: any) {\n /* 한 트윈의 조회가 실패해도 **0 으로 메우지 않는다** — 리비전 0 은 \"아직 아무 일도 없었다\" 는\n 사실 주장이다. 비워 두면 아래에서 undefined 로 남고, 화면은 그것을 \"모름\" 으로 그린다.\n 그리고 그 트윈만 모름이 된다 — 예전에는 집계 하나가 실패하면 전부 모름이었다. */\n twinError(`[twin-engine] latest revision lookup failed \"${r.instanceId}\"`, err?.message ?? err)\n }\n })\n )\n\n const out: any[] = []\n for (const r of rows) {\n const model = (r.model as TwinModelDef) ?? { locations: [], equipment: [] }\n out.push({\n instanceId: r.instanceId,\n /*\n * **이름을 함께 낸다.** 업무키(`instanceId`)만 내보내고 있어서 목록이 `crew-two` 만 보였다 —\n * 업무키를 나눠 둔 설계에서는 이름을 같이 실어야 그 나눔이 값을 한다.\n * 없으면 `undefined` 다(id 를 베끼지 않는다 — 화면이 이름 없음을 알아볼 수 있어야 한다).\n */\n name: r.name ?? undefined,\n description: r.description ?? undefined,\n kind: r.kind,\n status: r.status,\n spaceId: r.spaceId, // co-location: 같은 spaceId 인스턴스들이 한 현장 공유 — 현장뷰 집약 키(G7)\n /* 사람이 읽는 현장 이름 — 없으면 `undefined`(화면이 \"이름 없음\" 을 알아볼 수 있어야 한다). */\n spaceName: (r.spaceId ? spaceNameOf.get(r.spaceId) : undefined) || undefined,\n restartPolicy: r.restartPolicy, // 재기동 정책(ADR-0029 §2) — resync/resume/reset. 선언이므로 비어 있을 수 없다.\n purpose: r.purpose, // 운영 vs 벤치 사본(1급 구별 — 이름 접두사 아님). 저장 시 각인되므로 비지 않는다.\n copyOf: r.copyOf ?? undefined,\n running: !!this.instances[runtimeKey(domainId, r.instanceId)],\n /*\n * **계측이 들어오고 있나** — 「도는 중」과 다른 사실이다.\n *\n * 미러 트윈은 피드가 떨어져도 커널이 돌기만 하면 「도는 중」이었다. 그래서 아무것도 받지 않는\n * 트윈과 흐르는 트윈이 화면에서 똑같이 보였다(재기동 뒤 실제로 그랬다). 시뮬·정지 트윈에는\n * 「해당 없음」이다 — 없어야 하는 것을 끊겼다고 부르지 않는다.\n */\n /* 스스로 멈춘 이유 — 있으면 낸다. 재기동 뒤에는 없다(그때는 「모른다」가 사실이다). */\n stopNote: this.stopNotes.get(runtimeKey(domainId, r.instanceId)) || undefined,\n liveFeed: liveFeedStateOf({\n restartPolicy: r.restartPolicy,\n running: !!this.instances[runtimeKey(domainId, r.instanceId)],\n instanceId: r.instanceId\n }),\n revision: tipOfInstance.get(r.instanceId) ?? 0,\n /*\n * **리더를 거쳐 센다** — 보드 키를 직접 읽으면 옛 세대 모델이 0 으로 보인다.\n *\n * 커널은 자리·설비 배열의 **옛 세대 키까지 흡수해** 읽어 주는데, 이 목록은 새 이름만 직접\n * 세고 있었다. 그래서 옛 모델 12개가 화면에 **자리 0 · 설비 0**\n * 으로 떴다 — 오류 없이, 그냥 빈 공장처럼. 세는 규칙이 두 벌이면 이런 식으로 어긋난다.\n */\n locationCount: readBoardLocations(model).length,\n equipmentCount: readBoardEquipment(model).length\n })\n }\n return out\n }\n\n /** 운영 공간 목록(벤치 소스 선택기) — 이름·규모 포함, 벤치 사본 제외. */\n static async listSpaces(domainId: string): Promise<{ spaceId: string; name: string; instances: number; locations: number; equipment: number }[]> {\n const nameOf = new Map((await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })).map(s => [s.spaceId, s.name]))\n const insts = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n const agg = new Map<string, { spaceId: string; name: string; instances: number; locations: number; equipment: number }>()\n for (const r of insts) {\n /* 벤치 제외는 **선언으로만** 판단한다. 예전에는 spaceId 이름(`bench-`·`loadtest*`)으로도 추측했는데,\n 그러면 그렇게 이름 지은 진짜 운영 공간이 목록에서 조용히 사라진다. purpose 가 정본이다. */\n if (!r.spaceId || r.purpose === 'bench') continue\n const model: any = r.model ?? {}\n const a = agg.get(r.spaceId) ?? { spaceId: r.spaceId, name: nameOf.get(r.spaceId) ?? r.spaceId, instances: 0, locations: 0, equipment: 0 }\n a.instances++\n /* 목록과 **같은 규칙**으로 센다 — 여기만 직접 세면 공간 요약과 인스턴스 목록이 다른 수를 말한다. */\n a.locations += readBoardLocations(model).length\n a.equipment += readBoardEquipment(model).length\n agg.set(r.spaceId, a)\n }\n return [...agg.values()]\n }\n\n /** 인스턴스 목적 표식(운영/벤치) 설정 — 벤치 사본을 1급 속성으로 구별(이름 접두사 아님). */\n static async setPurpose(domainId: string, instanceId: string, purpose: 'operational' | 'bench', copyOf?: string): Promise<void> {\n await getRepository(TwinInstance).update({ domain: { id: domainId } as any, instanceId }, { purpose, copyOf: copyOf ?? null } as any)\n }\n\n /**\n * 공간 구조 판독 — 완전복제(벤치 사본)의 소스. 저장물이 model(위상)·TwinSpace.content(치수·geo·표현)·TwinArea(영역)로\n * 분산돼 있으므로 셋을 모아 돌려준다. 호출측이 ReferenceMaster 로 재구성 → 재식별 → ingestMaster.\n */\n static async spaceStructure(domainId: string, spaceId: string): Promise<{\n name?: string\n /** 설계 좌표계 범위(미터)와 지오레퍼런스 — 사본이 원본과 같은 자리에 서려면 함께 가야 한다. */\n frame: { extentX?: number; extentY?: number; geo?: any; primaryRepresentationId?: string }\n areas: any[]\n instances: { instanceId: string; kind?: string; model: any }[]\n } | null> {\n const sp = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n const areas = sp\n ? (await getRepository(TwinArea).find({ where: { domain: { id: domainId } as any, space: { id: sp.id } as any } })).map(a => ({ id: a.areaId, type: a.type, name: a.name, parentId: a.parentId, layout: a.layout }))\n : []\n const insts = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n if (!insts.length) return null\n return {\n name: sp?.name,\n frame: { extentX: sp?.extentX, extentY: sp?.extentY, geo: sp?.geo, primaryRepresentationId: sp?.primaryRepresentationId },\n areas,\n instances: insts.map(i => ({ instanceId: i.instanceId, kind: i.kind, model: i.model }))\n }\n }\n\n /** 공간(+표현·영역) 삭제 — 벤치 정리 등. 호출측이 바인딩 인스턴스를 먼저 제거하는 전제(가드 없음). deleteTwinSpace 리졸버와 동형. */\n static async deleteSpace(domainId: string, spaceId: string): Promise<void> {\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (space) {\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n for (const rep of reps) await getRepository(TwinSpaceArea).delete({ domain: { id: domainId } as any, representation: { id: rep.id } as any })\n await getRepository(TwinSpaceRepresentation).delete({ domain: { id: domainId } as any, space: { id: space.id } as any })\n await getRepository(TwinArea).delete({ domain: { id: domainId } as any, space: { id: space.id } as any })\n }\n await getRepository(TwinSpace).delete({ domain: { id: domainId } as any, spaceId })\n }\n\n /**\n * Face2 마스터 인제스트(ADR-0018) — 레퍼런스 시스템(실 또는 가상)의 마스터를 읽어 트윈을 생성.\n * 엔티티를 손배선/발명하지 않고 마스터에서 반영: 공간(Space) upsert + 인스턴스 provision(미기동).\n * 노드타입은 커널 카탈로그로 검증(warning). start 는 호출측(bootstrap/mutation)이 결정.\n *\n * `into.spaceId` — **이 현장에 더한다.** 한 현실을 여러 렌즈(WMS·MES·YMS)가 비추므로 새 트윈이\n * 기존 공간으로 들어갈 수 있다. 아래 병합은 원래 그 경우를 위해 있었는데(N:1) 만드는 흐름에서\n * 공간을 고를 방법이 없었다 — 마스터가 파생한 id 만 쓰였다. 판정은 `resolveIngestSpace`(순수).\n */\n static async ingestMaster(\n domainId: string,\n master: ReferenceMaster,\n /** 만들어지는 트윈의 재기동 정책 — 원본이 정하는 것이 아니라 **만드는 쪽의 선언**이다(ADR-0029 §2). */\n restartPolicy: RestartPolicy,\n into?: { spaceId?: string },\n /** 누가 인제스트했나 — 사람이 없는 경로(부팅)는 주지 않는다(감사 기록을 지어내지 않는다). */\n actor?: { id: string }\n ): Promise<{ instanceId: string; spaceId: string; warnings: IngestWarning[] }> {\n /*\n * **거절할 것이면 아무것도 쓰기 전에 거절한다.**\n *\n * 가동 중 재프로비저닝은 `provision` 이 막는다. 그런데 그 호출은 이 함수의 **맨 끝**이라,\n * 그때까지 공간·표현·구역(TwinArea)은 이미 저장된 뒤였다. 사용자에게는 \"인제스트 실패\" 로\n * 보이는데 실제로는 절반이 적용된 상태 — 실패라고 말하면서 데이터를 바꾸는 것이 가장 나쁘다.\n *\n * 그래서 판정을 앞으로 옮긴다. 아래 `provision` 의 같은 판정은 그대로 둔다 — 이건 편의를 위한\n * 앞선 거절이고, 저기가 진짜 방벽이다(다른 경로가 생겨도 지켜져야 한다).\n *\n * **미러는 여기서 거절하지 않는다.** 미러가 비추는 현실은 안 멈추므로 동작 중에 전환한다\n * (아래 `adoptStructure`). 거절은 시뮬레이션에만 남는다 — 조건이 바뀐 실험은 다른 실험이다.\n */\n const running = this.instances[runtimeKey(domainId, master.source)]\n if (running && running.mode !== 'live') this.assertNotRunning(domainId, master.source)\n\n const { model, spaceContent, warnings } = masterToTwin(master, DOMAIN_CATALOG)\n /*\n * ── 현장 선언을 다시 얹는다 (2026-08-18) ──────────────────────────────────\n *\n * 여기가 「원천에서 다시 그리는」 자리다. 요금 단가·계약 정보처럼 **현장이 정한 수**는 원천이 모르므로\n * 다시 그리면 그대로 사라진다 — 금액이 사라지고, 사용자는 자기가 넣은 값이 어디로 갔는지 알 수 없다.\n * 그래서 겹으로 보관한 선언을 매번 다시 얹는다(`engine/local-declarations`).\n *\n * 대상이 사라졌으면(구조가 바뀌었다) 그 사실을 경고로 낸다 — 갈 곳 없는 선언을 조용히 버리지 않는다.\n */\n const prior = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: master.source } })\n /*\n * 겹이 **둘**이다 — 현장(공간)의 것과 이 트윈의 것. 순서가 규율이다: 현장 먼저, 트윈이 나중.\n * 요금처럼 현장이 정한 수는 그 현장의 트윈 전부가 같이 읽어야 하고, 한 트윈만 다르게 두는 실험은\n * 좁은 겹이 이겨야 한다(넓은 값을 고치면 나머지 트윈이 함께 흔들린다).\n */\n const priorSpaceId = prior?.spaceId ?? (model as any)?.spaceId\n const spaceRow = priorSpaceId\n ? await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId: priorSpaceId } })\n : null\n if (prior?.localDeclarations || spaceRow?.localDeclarations) {\n const layered = applyDeclarationLayers(model as any, spaceRow?.localDeclarations as any, prior?.localDeclarations as any)\n Object.assign(model as any, layered.model)\n /*\n * 겹을 **다시 저장한다** — 여기서 얹은 것은 원천에서 새로 그린 모델이므로, 그때 우리가 덮은 값이\n * 곧 지금의 원천 값이다(`replaced`). 저장하지 않으면 그 기억이 낡아, 철회가 옛 원천 값으로\n * 되돌린다 — 원천이 그동안 값을 고쳤어도 알 수 없다.\n */\n if (prior) {\n prior.localDeclarations = layered.instanceLayerApplied as any\n await getRepository(TwinInstance).save(prior)\n }\n if (spaceRow) {\n spaceRow.localDeclarations = layered.spaceLayerApplied as any\n await getRepository(TwinSpace).save(spaceRow)\n }\n /*\n * 갈 곳 없는 선언은 경고로 낸다 — 다만 **현장 겹의 것은 뺀다**: 한 현장에는 여러 종류의 트윈이\n * 살고(창고·야드·에너지), 요금 자리가 없는 트윈에 요금이 얹히지 않는 것은 정상이다.\n */\n for (const t of layered.missingTargets.filter(x => x.scope === 'instance')) {\n warnings.push(unresolvedReference('localDeclaration.target', `${t.target}:${t.id}`))\n }\n }\n const repo = getRepository(TwinSpace)\n /* 합칠 공간을 골랐으면 **있는지 먼저 확인한다** — 없는 곳에 조용히 새 공간을 만들면 사용자는\n 합쳤다고 믿고 화면은 따로 논다. 판정 함수가 그 경우 거절한다. */\n const wanted = (into?.spaceId ?? '').trim()\n const wantedExists = wanted\n ? (await repo.count({ where: { domain: { id: domainId }, spaceId: wanted } })) > 0\n : false\n const choice = resolveIngestSpace(model.spaceId, wanted, wantedExists)\n const spaceId: string = choice.spaceId\n model.spaceId = spaceId // 보드(커널 소비)도 같은 공간을 가리켜야 한다\n const existing = await repo.findOne({ where: { domain: { id: domainId }, spaceId } })\n if (choice.joined) {\n /* 같은 id 의 구역·랜드마크는 합집합으로 접힌다 — 구분할 수 없는 것을 고르지 않고 무엇이\n 합쳐졌는지 말한다(정당한 경우가 많으므로 막지 않는다). */\n }\n /*\n * 공유 공간(여러 트윈이 한 spaceId, N:1) — **먼저 쓴 값이 이긴다.**\n *\n * 마지막 인제스트가 통째로 덮어써 표현·구역이 유실되던 문제 보정. 설계 좌표계 범위와\n * 지오레퍼런스는 공간의 성질이라 트윈마다 다를 수 없다 — 두 번째 트윈이 들어오면서 바꾸면\n * 먼저 놓인 구역들이 통째로 어긋난다. 그래서 이미 있으면 그대로 둔다.\n */\n const cur: any = spaceContent\n const timezone = existing?.timezone || master.space.timezone\n const savedSpace = await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n spaceId,\n name: existing?.name || master.siteName,\n ...(timezone ? { timezone } : {}),\n extentX: existing?.extentX ?? cur.width,\n extentY: existing?.extentY ?? cur.depth,\n geo: existing?.geo ?? cur.geo,\n /*\n * 대표 표현 포인터는 **표현을 저장한 뒤** 실제 행 id 로 채운다(아래). 여기서 마스터의 논리\n * id(`r-map` 따위)를 넣으면 표현 행은 생성 uuid 를 받으므로 포인터가 **처음부터 허공을\n * 가리킨다** — 실제로 13개 현장이 그 상태였고 정합성 점검이 잡았다(2026-08-13). 화면은\n * 행의 `isPrimary` 로 ★를 그려서 증상이 보이지 않았다(사실이 두 벌이면 이렇게 조용하다).\n */\n primaryRepresentationId: existing?.primaryRepresentationId ?? null\n })\n )\n /*\n * 표현을 twin_space_representations 테이블에 저장한다 — 뷰(twin-map-page 등)는 content 가 아니라 테이블 표현을 소싱하므로,\n * 저장하지 않으면 인제스트 사이트에 \"대표 표현\" 이 없어 지도로 시작하지 못한다. rep.areas 가 있으면 TwinSpaceArea 도 함께 저장.\n * 최초 인제스트만(기존 표현 있으면 사용자 편집 보존).\n */\n const repRepo = getRepository(TwinSpaceRepresentation)\n const areaRepo = getRepository(TwinSpaceArea)\n if ((await repRepo.count({ where: { space: { id: savedSpace.id } } })) === 0) {\n const reps: any[] = (spaceContent as any).representations ?? []\n for (let i = 0; i < reps.length; i++) {\n const rep = reps[i]\n const config =\n rep.type === 'map' ? { center: rep.center, zoom: rep.zoom }\n : rep.type === 'board' ? { boardId: rep.boardId }\n : rep.type === 'image' ? { imageUrl: rep.imageUrl, width: rep.width, height: rep.height }\n : {}\n const savedRep = await repRepo.save(repRepo.create({ domain: { id: domainId } as any, space: { id: savedSpace.id } as any, type: rep.type, name: rep.name, seq: i, isPrimary: !!rep.primary || rep.id === (spaceContent as any).primaryId, config }))\n for (const area of (rep.areas ?? []) as any[]) {\n await areaRepo.save(areaRepo.create({ domain: { id: domainId } as any, representation: { id: savedRep.id } as any, name: area.name, type: area.type, geometry: area.geometry, drillTo: area.drillTo ?? null, binding: area.binding ?? null, style: area.style ?? null }))\n }\n }\n /*\n * 대표를 **저장된 행 id** 로 가리킨다 — 마스터의 논리 id 는 저장 키가 아니다. 고른 순서:\n * ① 마스터가 primary 로 표시한 표현 ② 없으면 첫 표현 ③ 표현이 없으면 비운다(지어내지 않는다).\n */\n const saved = await repRepo.find({ where: { domain: { id: domainId } as any, space: { id: savedSpace.id } as any }, order: { seq: 'ASC' } })\n const primary = saved.find(r => r.isPrimary) ?? saved[0]\n if (primary && savedSpace.primaryRepresentationId !== primary.id) {\n await repo.save(repo.create({ ...savedSpace, primaryRepresentationId: primary.id }))\n /* 하나만 대표다 — 행 플래그도 그 하나로 맞춘다(둘이 켜져 있으면 화면이 ★를 두 번 그린다). */\n for (const r of saved) if (!!r.isPrimary !== (r.id === primary.id)) await repRepo.save(repRepo.create({ ...r, isPrimary: r.id === primary.id }))\n }\n }\n /*\n * area 단일화(space #2, P1) — 논리 구역을 TwinArea(정규·표현무관·공유)에 dual-write(upsert by areaId).\n * P3: content.areas 저장 폐기 → TwinArea 가 유일 권위. 소스 = masterToTwin 산출 spaceContent.areas(cur).\n * (원천 diff 제거[master 에서 빠진 area 삭제]는 사용자저작 area 보호 위해 per-area provenance 필요 → 후속.)\n */\n const twinAreaRepo = getRepository(TwinArea)\n for (const a of ((spaceContent as any).areas ?? []) as any[]) {\n if (!a?.id) continue\n const existingArea = await twinAreaRepo.findOne({ where: { domain: { id: domainId }, space: { id: savedSpace.id }, areaId: a.id } })\n await twinAreaRepo.save(\n twinAreaRepo.create({\n ...(existingArea ?? {}),\n domain: { id: domainId } as any,\n space: { id: savedSpace.id } as any,\n areaId: a.id,\n name: a.name ?? a.id,\n type: a.type,\n parentId: a.parentId ?? null,\n layout: a.x != null || a.w != null ? { x: a.x, y: a.y, w: a.w, h: a.h } : null\n })\n )\n }\n\n if (running) {\n /* 실행 중인 미러 — 멈추지 않고 전환한다. 무엇이 사라졌는지는 **경고로 말한다**\n (멈췄다 세우는 마디가 없으므로, 말하지 않으면 자리 하나가 조용히 없어진다). */\n const shift = await this.adoptStructure(domainId, master.source, model, undefined, master.origin)\n warnings.push(structureAdopted(shift.rev, shift))\n } else {\n /* 사이트 이름이 곧 트윈의 이름이다 — 마스터가 이미 말했으므로 지어내지 않고 그대로 싣는다. */\n await this.provision(domainId, master.source, master.system, model, restartPolicy, undefined, master.origin, {\n name: master.siteName,\n description: (master as any).description,\n actor\n })\n }\n\n /*\n * 구조 투영 — model(커널 입력 문서)를 **표준 엔티티 행**으로 푼다(ADR-0032).\n *\n * 인제스트가 유일한 쓰기 경로다. 여기서 실패해도 인제스트 자체는 성공으로 둔다 —\n * 행은 **원본에서 언제든 다시 그릴 수 있는 캐시**이고, 트윈 자체는 model 로 이미 동작한다.\n * 다만 **조용히 넘기지 않는다**: 못 이은 참조는 인제스트 경고로 올라간다.\n */\n try {\n const projected = await projectStructure(domainId, master.source, model, master.source)\n for (const ref of projected.unresolvedHome) warnings.push(unresolvedReference('equipment.homeLocation', ref))\n for (const ref of projected.unresolvedArea) warnings.push(unresolvedReference('location.area', ref))\n /*\n * 발전 형상은 **시각**을 읽는다 — 시간대를 모르면 UTC 로 읽히고, 현장 정오가 아닌 시각에 피크가 선다.\n * 시간대를 지어내지 않고 그 조합을 말한다(공간에 선언하면 사라진다).\n */\n if ((model as any)?.utcOffsetMinutes === undefined) {\n for (const e of ((model as any)?.equipment ?? []) as any[]) {\n const hasProfile = ((e?.properties ?? []) as any[]).some(p => String(p?.id) === EMS_PROPERTY.genDailyProfile && String(p?.value ?? '').trim())\n if (hasProfile) warnings.push(generationWithoutTimeZone(String((model as any)?.spaceId ?? ''), String(e.id)))\n }\n }\n } catch (err: any) {\n twinError(`[twin-engine] structure projection failed for \"${master.source}\":`, err?.message)\n warnings.push(projectionFailed(err?.message ?? 'unknown'))\n }\n\n if (warnings.length) twinWarn(`[twin-engine] ingest \"${master.source}\" warnings: ${describeWarnings(warnings)}`)\n return { instanceId: master.source, spaceId, warnings }\n }\n\n /** 단건 상세 — 프로비저닝 에디터가 편집할 model(구조+layout) 포함. */\n static async detail(domainId: string, instanceId: string): Promise<any | null> {\n const r = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!r) return null\n return {\n instanceId: r.instanceId,\n kind: r.kind,\n status: r.status,\n running: !!this.instances[runtimeKey(domainId, r.instanceId)],\n restartPolicy: r.restartPolicy, // 현실 선언 — what-if 적용 가드용(mirror=예측 전용, 자극 주입 불가)\n model: r.model\n }\n }\n\n /**\n * 라이브 바인딩 브리지(P3, ADR-0018) — 트윈 엔티티 상태를 `data(tag=엔티티id)` 채널로 publish.\n * 보드 컴포넌트가 tag 로 구독(board-ui provider)해 `component.data` 로 라이브 갱신. delta 시에만(희소).\n * tag=엔티티 id(데모=단일 인스턴스). 멀티 인스턴스/보드 재사용 시 tag 네임스페이스는 후속.\n */\n /** 브로드캐스팅 실패 로그 조절 — 창마다 한 줄(막힌 구독자는 초당 수십 번 실패한다). */\n private static publishDrops = new Map<string, { count: number; lastLogMs: number }>()\n private static readonly PUBLISH_DROP_LOG_MS = 10_000\n\n /**\n * 한 번의 브로드캐스팅 — **구독자 하나가 호스트를 죽이지 못하게.**\n *\n * ── 무엇이 죽였나 (2026-08-14) ─────────────────────────────────────────────\n * 밀린 push 가 1024를 넘으면 pubsub 이 오류를 낸다(`RepeaterOverflowError`). 그 브로드캐스팅은 타이머 콜백\n * 안에서 일어나므로 예외가 잡히는 곳 없이 올라가 **프로세스가 끝났다** — 트윈 14개가 도는 호스트가\n * 소비를 멈춘 구독자 하나 때문에 통째로.\n *\n * 못 보낸 것은 **사실로 남긴다**(횟수를 세고 창마다 한 줄 남긴다). 삼키면 「보냈는데 화면이 낡았다」가\n * 되고, 그건 가장 찾기 어려운 부류다.\n */\n private static publishGuarded(channel: 'data' | 'twin-state', payload: any, what: string): boolean {\n try {\n pubsub.publish(channel as any, payload)\n return true\n } catch (err: any) {\n const d = this.publishDrops.get(what) ?? { count: 0, lastLogMs: 0 }\n d.count++\n const now = Date.now()\n if (now - d.lastLogMs >= this.PUBLISH_DROP_LOG_MS) {\n d.lastLogMs = now\n twinWarn(`[twin-engine] broadcast dropped on \"${what}\" (${d.count} so far) — ${err?.message ?? err}`)\n }\n this.publishDrops.set(what, d)\n return false\n }\n }\n\n static publishEntityData(inst: InstanceRuntime): void {\n const domain = inst.domain\n if (!domain) return\n /* 상태 출처 스왑 — sim: 커널 runtime, live: projector 미러(+OEE 계산 층 보강). 계약·payload 동일, 드라이버만 다름. */\n const load = inst.load ?? (inst.load = newLoadMeter())\n\n /* ① 상태 투영 — 상태 크기에 비례한다(대규모에서 가장 무거운 축). */\n const tSnap = performance.now()\n const st: any =\n inst.mode === 'live'\n ? inst.oee\n ? withLiveOee(inst.projector?.snapshot?.(), inst.oee) // 관측 커널 + 계산(OEE) → equipment payload 에 oee 포함(sim 동형)\n : inst.projector?.snapshot?.()\n : inst.runtime?.resync?.()?.state\n recordPhase(load, 'snapshot', performance.now() - tSnap)\n if (!st) return\n /*\n * 변화한 엔티티만 발행 — 이전엔 delta 마다 전 엔티티(노드+무버+오더)를 값 변화와 무관하게 전량 재발행해\n * 같은 데이터를 매초 반복 push 하고 있었다(오용). 최신-상태 채널이므로 무변화 재브로드캐스팅은 무의미하다.\n * 엔티티별 시그니처를 비교해 바뀐 것만 push.\n */\n const sigs = inst.entitySigs ?? (inst.entitySigs = new Map())\n const seen = new Set<string>()\n /* payload 매핑은 순수 함수(buildEntityDeltas)로 분리 — 여기선 시그니처 dedup + 발행만.\n * 변화한 엔티티만 발행(최신-상태 채널이라 무변화 재브로드캐스팅 무의미). */\n /* ② payload 만들기 — 엔티티 수에 비례. ③ 시그니처 비교 + 발행 — 바뀐 것 수에 비례. */\n const tDelta = performance.now()\n /*\n * ── 물품은 **건드린 것만** 만든다 (2026-08-21 실측) ──────────────────────\n * 만드는 payload 의 대부분이 물품이다(엔티티 3,611 중 2,400). 바뀐 것이 하나여도 전부 만들어\n * 문자열로 바꾼 뒤 「같다」를 확인하고 버렸다.\n *\n * 범위는 이 창에 들어온 사건에서 모았다(`touchedItemKeys`). **말할 수 없는 사건이 하나라도 있으면\n * 범위는 없고 전부 만든다** — 낯선 어휘가 오면 조용히 빠뜨리는 대신 비싸게 안전한 쪽으로 떨어진다.\n *\n * 그리고 주기마다 한 번은 **무조건 전부** 만든다(`FULL_BROADCAST_EVERY`). 커널이 사건 없이 물품을\n * 바꾸는 자리가 생기면 그 값이 화면에 남을 수 있는데, 그 창을 몇 초로 묶는 그물이다. **보장이 아니라\n * 그물이다** — 사건 없이 바뀌는 자리를 찾으면 그것을 고치는 것이 답이고 이 그물은 시간을 벌 뿐이다.\n */\n const full = inst.fullBroadcastDue === true || !inst.dirtyItems\n const deltas = buildEntityDeltas(st, inst.id, full ? undefined : { items: inst.dirtyItems! })\n this.broadcastPasses++\n if (full) this.broadcastFullPasses++\n /* 이번 창의 범위는 여기서 닫는다 — 다음 창은 다시 모은다. */\n inst.dirtyItems = new Set()\n inst.fullBroadcastDue = false\n recordPhase(load, 'deltas', performance.now() - tDelta)\n\n const tPub = performance.now()\n for (const { tag, data } of deltas) {\n seen.add(tag)\n const sig = JSON.stringify(data)\n if (sigs.get(tag) === sig) continue // 무변화 → 발행 생략\n sigs.set(tag, sig)\n /*\n * **못 보냈으면 보낸 것으로 적지 않는다.** 시그니처를 남겨 두면 다음 주기에 「무변화」로 건너뛰고,\n * 그 태그는 영원히 낡은 값을 보여 준다(오류 없이). 되돌려 두면 다음 주기가 다시 시도한다.\n */\n if (!this.publishGuarded('data', { data: { domain, tag, data } }, `data:${inst.id}`)) sigs.delete(tag)\n }\n recordPhase(load, 'publish', performance.now() - tPub)\n /*\n * 사라진 엔티티의 시그니처 정리(맵 무한 성장 방지) — **전부 만든 창에서만.**\n * 범위를 좁힌 창의 `seen` 에는 만들지 않은 엔티티가 없으므로, 그때 정리하면 살아 있는 태그의\n * 시그니처를 지운다. 낡은 값이 나가는 것은 아니지만(다음 창에 다시 만들어 보낸다) 같은 값을\n * 되풀어 보내게 되어, 줄이려던 것을 되돌린다.\n */\n if (full && sigs.size > seen.size) for (const tag of sigs.keys()) if (!seen.has(tag)) sigs.delete(tag)\n }\n\n /*\n * 단건 저장(`persist`)은 **없앴다** (2026-08-20, §7.1).\n *\n * 시뮬이 델타마다 이것을 불러 행 하나씩 썼고, 그것이 규모에서 호스트를 먹었다. 남겨 두면 다음 사람이\n * 다시 부를 자리가 되므로 지운다 — 쓰는 문은 `flushJournal` 하나다(`persistBatch`·`persistCarried`).\n */\n\n /**\n * 재부팅 복구 / 시간여행 — DB 저널을 replay 해 상태 재구성.\n * model 는 레지스트리(TwinInstance)에서, 이벤트는 TwinEvent(revision ASC)에서.\n * 커서 두 축(runtime-state-model §4): **시각(untilTime, 사용자 모국어·공간 공통축)** 우선, 없으면 리비전(untilRevision, 렌즈 내부).\n * - untilTime 주면 `eventTime ≤ T` 인 이벤트만(그 시점 watermark) — 공동배치 여러 트윈을 하나의 시각 T로 통일 해소.\n * - 둘 다 없으면 최신(라이브 인메모리 진실).\n * 이벤트는 항상 revision ASC(인과 순서)로 적용 — 시각 필터는 컷오프 집합만 정한다.\n */\n static async recover(domainId: string, instanceId: string, untilRevision?: number, untilTime?: string): Promise<any> {\n // 라이브 최신(시간여행 아님) + 인메모리 인스턴스 → 라이브 커널 스냅샷을 직접 사용.\n // replay(StateProjector)는 attentions·ack 등 라이브 전용 파생 상태를 담지 못하므로, 최신은 커널 진실을 쓴다.\n if (untilRevision == null && untilTime == null) {\n const live = this.instances[runtimeKey(domainId, instanceId)]\n if (live?.kernel?.getSnapshot) return live.kernel.getSnapshot()\n // live 모드는 kernel 이 없고 projector 미러 → 인메모리 최신 스냅샷(projector+OEE+attentions) 직접 사용.\n // (저널이 있어도 최신은 인메모리가 진실 — replay 는 시간여행/복구 전용.)\n if (live?.mode === 'live' && live.projector) return this.snapshot(domainId, instanceId)\n }\n /*\n * **끝에 있는 스냅샷이면 접지 않는다.**\n *\n * 멈춘 트윈을 조회할 때마다 저널을 전량 접고 있었다 — 트윈을 하나도 안 돌려도 모델 조회가\n * 4.6~7.7초였던 이유다(crew-probe 23,731건). 스냅샷은 같은 폴드의 결과이므로, 그 뒤로 이벤트도\n * 구조 변경도 없다면 **다시 접어 봐야 같은 값**이다.\n *\n * 쓰지 않는 조건을 좁게 잡는다: 지금을 물었을 때만(시간여행은 그 시점까지 접어야 한다), 리비전이\n * 끝과 같을 때만, 구조 리비전까지 같을 때만. 하나라도 어긋나면 접는다 — 캐시가 사실을 이기지 않는다.\n */\n const asOfNowRead = untilRevision == null && untilTime == null\n const tip = asOfNowRead ? await this.tipOf(domainId, instanceId).catch(() => null) : null\n /* 한 번만 읽는다 — 끝에 있으면 그대로 쓰고, 아니면 아래에서 **이어 접는 씨앗**으로 쓴다. */\n const cachedForResume = asOfNowRead && tip ? await this.loadSnapshot(domainId, instanceId).catch(() => null) : null\n if (cachedForResume) {\n const state = unwrapState(cachedForResume.state)\n if (state && (cachedForResume.revision ?? 0) === tip!.revision && (cachedForResume.structureRev ?? null) === tip!.structureRev)\n return state\n }\n\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) throw new Error(`twin instance \"${instanceId}\" not registered (no model to replay)`)\n\n /*\n * ── 재개점에서 **이어 접는다** (2026-08-18) ────────────────────────────\n *\n * 우리는 이미 접은 결과를 남기고 있다(`saveFoldedSnapshot`). 그 지점의 **재개점**(리듀서 내부 상태\n * 전부 + 가동 누적기)이 함께 있으면, 그 뒤에 일어난 것만 접어도 같은 답이 나온다 — 그 동치는\n * 커널 시험이 증명한다(0부터 접기 == 재개점 + 꼬리).\n *\n * 쓰는 조건을 좁게 잡는다: **지금을 물었을 때만**(시간여행은 목표 이전 재개점이 필요한데 지금은\n * 최신 하나만 남긴다 — 사슬은 다음 단계다), 구조가 그대로일 때만(구조가 바뀌면 그 경계에서 갈라\n * 접어야 한다), 재개점이 저널 끝보다 앞설 때만. 하나라도 어긋나면 0부터 접는다 — **캐시가 사실을\n * 이기지 않는다.**\n */\n /*\n * 씨앗은 둘 중 하나다: **지금**을 물으면 최신 재개점, **과거**를 물으면 사슬에서 목표 직전 지점.\n *\n * 과거 씨앗은 구조가 한 번도 바뀌지 않은 트윈에서만 쓴다 — 구조가 갈린 저널은 마디마다 갈아 접어야\n * 하고, 마디를 건너뛴 씨앗은 그 경계의 판정을 잃는다(그때는 0부터 접는 것이 옳다).\n */\n const structureCount = asOfNowRead\n ? 0\n : await getRepository(TwinStructure).count({ where: { domain: { id: domainId }, instanceId } }).catch(() => 99)\n const pastSeed =\n !asOfNowRead && structureCount <= 1\n ? await this.chainSeedFor(domainId, instanceId, {\n ...(untilRevision != null ? { revision: untilRevision } : {}),\n ...(untilTime != null && !Number.isNaN(Date.parse(untilTime)) ? { timeMs: Date.parse(untilTime) } : {})\n }).catch(() => null)\n : null\n const resume =\n asOfNowRead && tip && cachedForResume && cachedForResume.fold && (cachedForResume.structureRev ?? null) === tip.structureRev\n ? cachedForResume\n : pastSeed\n\n /*\n * **자를 것을 알면서 다 읽어 오지 않는다** (2026-08-18 실측).\n *\n * 저널을 전량 읽어 온 뒤 JS 에서 걸렀다. 27만 건짜리 트윈(order-check)에서 한 시간 전 상태를 물으면\n * **7.4초**가 걸렸고, 그 대부분이 「필요 없는 행을 읽어 오는 시간」이었다. 시각·리비전 상한은 SQL 이\n * 아는 조건이므로 거기서 자른다(TypeORM 관용구만 — 원시 SQL 은 5개 드라이버에서 갈라진다).\n *\n * 시각 상한에는 **경계를 그대로** 쓴다(`<=`): 그 시각에 일어난 사실은 그 시각의 화면에 있어야 한다.\n * 시각이 없는 레거시 행은 보수적으로 포함해 왔는데, SQL 로 자르면 그 행들이 빠진다 — 그래서 시각\n * 조건일 때는 **시각이 비어 있는 행도 함께** 가져와 예전과 같은 결과를 낸다.\n */\n const cutoffMs = untilTime != null ? Date.parse(untilTime) : NaN\n const useTime = untilTime != null && !Number.isNaN(cutoffMs)\n const baseWhere = { domain: { id: domainId }, instanceId }\n /* 이어 접을 때는 **그 뒤만** 읽는다 — 재개점까지의 사실은 이미 씨앗 안에 있다. */\n const from = resume ? (resume.revision ?? 0) : undefined\n /*\n * journal-fold: 재생은 사실을 하나씩 접는 것이므로 그 구간의 행이 필요하다. 커서(`from`)와 시각\n * 상한이 구간을 자르고, 체크포인트가 앞쪽을 씨앗으로 대신한다 — 표 전체를 읽지 않는다.\n */\n const rows = await getRepository(TwinEvent).find({\n where: useTime\n ? from\n ? /* 씨앗 뒤 · 목표 이내 — 시각이 빈 옛 행은 씨앗 뒤에 있는 것만 포함한다(보수적 포함을 유지). */\n [\n { ...baseWhere, revision: MoreThan(from), eventTime: LessThanOrEqual(new Date(cutoffMs)) },\n { ...baseWhere, revision: MoreThan(from), eventTime: IsNull() }\n ]\n : [\n { ...baseWhere, eventTime: LessThanOrEqual(new Date(cutoffMs)) },\n { ...baseWhere, eventTime: IsNull() }\n ]\n : untilRevision != null\n ? from\n ? { ...baseWhere, revision: And(MoreThan(from), LessThanOrEqual(untilRevision)) }\n : { ...baseWhere, revision: LessThanOrEqual(untilRevision) }\n : from\n ? { ...baseWhere, revision: MoreThan(from) }\n : baseWhere,\n order: { revision: 'ASC' }\n })\n const wanted = rows\n\n /*\n * **그때의 공장으로 접는다.**\n *\n * 예전에는 모든 이벤트를 지금 등록된 보드 하나로 접었다. 구조가 바뀐 적 없으면 맞지만, 바뀐\n * 뒤에는 옛 사실을 새 공장에 대고 접게 되어 — 그때 없던 설비에서 일이 있었던 것처럼 보인다.\n * (그래서 예전 프로비저닝은 구조가 바뀌면 저널을 아예 지웠다. 역사를 잃거나 거짓말을 하거나.)\n *\n * 이제 이벤트가 자기 구조를 달고 오므로, 리비전이 바뀌는 지점에서 구조를 갈아타며 이어 접는다.\n * 리비전이 하나뿐이거나(대다수) 아예 없으면(구조 이력 이전) 예전과 똑같이 한 번에 접는다.\n */\n const structures = await getRepository(TwinStructure).find({\n where: { domain: { id: domainId }, instanceId },\n order: { rev: 'ASC' }\n })\n const boardOf = new Map<number, TwinModelDef>(structures.map(x => [x.rev, x.model as TwinModelDef]))\n /* 컬럼이 생기기 전 행은 리비전이 비어 있다 — **가장 오래된 구조**에 속한다(0 으로 채우지 않는다). */\n const oldest = structures[0]?.rev\n const revOf = (r: { structureRev?: number }): number | undefined => r.structureRev ?? oldest\n\n const segments: { model: TwinModelDef; events: any[] }[] = []\n for (const r of wanted) {\n if (!r.payload) continue\n const rev = revOf(r)\n const model = (rev !== undefined && boardOf.get(rev)) || (reg.model as TwinModelDef)\n const last = segments[segments.length - 1]\n if (last && last.model === model) last.events.push(r.payload)\n else segments.push({ model, events: [r.payload] })\n }\n /*\n * **가장 새 구조가 지금의 공장이다** — 그 아래에서 아직 아무 일도 없었더라도.\n *\n * 재프로비저닝 직후가 정확히 그 상태다: 부스를 넷 늘렸는데 새 이벤트는 아직 하나도 없다. 이때\n * 마지막 이벤트의 구조로만 접으면 화면은 **옛 공장**을 보여준다 — 방금 늘린 것이 안 보인다.\n * 그래서 마디의 끝에 지금 구조를 한 번 더 얹는다(이벤트 없는 마디).\n *\n * **다만 \"지금\" 을 물었을 때만이다.** 과거 시점을 물었는데 최신 구조를 얹으면, 그 시점에 없던\n * 설비가 화면에 서고 — 이 작업이 막으려던 바로 그 거짓말이 된다.\n */\n const asOfNow = untilRevision == null && untilTime == null\n const newest = structures[structures.length - 1]?.model as TwinModelDef | undefined\n if (asOfNow && newest && segments[segments.length - 1]?.model !== newest) segments.push({ model: newest, events: [] })\n\n /*\n * 접은 상태에 **주의 신호와 시각을 채운다.**\n *\n * 라이브·시뮬은 커널이 신호를 스스로 내지만, 저널을 접는 이 경로는 프로젝터 상태만 낸다 — 신호도\n * `nowTime` 도 없다. 그래서 **과거를 다시 계산하면 주의 레일이 텅 비었고**(지도는 `snap.attentions` 를\n * 읽는다), 기동돼 있지 않은 트윈을 보는 화면도 같았다. 신호는 상태에서 계산되는 것이므로\n * 여기서 같은 공식(`deriveAttentions`)으로 채우면 된다 — 두 벌을 두지 않는다.\n *\n * `nowTime` 이 먼저다: \"늦었나\" 판정이 그 값을 본다. 다시 계산한 시점의 정직한 \"지금\" 은 물어본 시각\n * (`untilTime`)이고, 없으면 마지막으로 적용한 이벤트의 시각이다. 둘 다 없으면 채우지 않는다 —\n * 벽시계를 끼워 넣으면 과거 화면이 \"지금 기준으로 늦었다\" 고 말하게 된다.\n */\n const lastEventTime = rows.length ? (rows[rows.length - 1]?.eventTime?.toISOString() ?? '') : ''\n\n /*\n * **가동 이력도 되살린다** — 다시 계산한 화면에 설비 계측이 비어 있던 것.\n *\n * OEE 는 원 시스템이 누적을 보내 주지 않아 호스트가 상태 전이를 적분해 만든다(그래서 커널이 아니라\n * 여기 있다). 그런데 그 누적기는 **라이브에서만** 돌았고, 저널을 접는 경로는 그 계산을 하지 않았다 —\n * 과거를 다시 계산하면 모든 설비가 \"가동 이력이 전혀 없음\" 으로 보였다.\n *\n * 없는 것은 데이터가 아니라 계산이다: 입력(`equipment.status` 전이·`quality.output`)은 저널에 다\n * 있다. 그래서 **같은 누적기에 같은 이벤트를 태운다** — 규칙을 두 벌 만들지 않는다.\n *\n * 시간여행에서도 맞다: 여기 태우는 것은 이미 잘라 낸(`wanted`) 이벤트뿐이므로, 그 시점까지의\n * 가동 이력이 나온다(그 뒤에 일어난 고장이 과거 화면에 섞이지 않는다).\n */\n const oee = new OeeAccumulator()\n /* 재개점이 있으면 그 위에 꼬리만 얹는다 — 없으면 꼬리분만 세어 가용률이 조용히 작아진다. */\n if (resume?.fold?.oee) oee.restore(resume.fold.oee)\n for (const r of wanted) {\n try {\n oee.apply(r.payload as any)\n } catch {\n /* 한 건이 이상해도 나머지 계측을 버리지 않는다 — 누적기는 모르는 이벤트를 무시하는 계약이다. */\n }\n }\n\n const withNow = (st: any): any => {\n if (!st || typeof st !== 'object') return st\n const nowTime = st.nowTime || untilTime || lastEventTime || undefined\n const based = nowTime ? { ...st, nowTime } : st\n /* 계측 시점은 그 화면의 \"지금\" 이다 — 벽시계로 재면 과거 화면의 가용률이 시간이 갈수록 떨어진다. */\n const nowMs = nowTime ? Date.parse(String(nowTime)) : Number.NaN\n const withMetrics = withLiveOee(based, oee, Number.isFinite(nowMs) ? nowMs : undefined)\n return withLiveAttentions(withMetrics)\n }\n\n /* 접은 결과를 남긴다 — **지금을 물었을 때만**(시간여행 결과를 \"지금\" 으로 저장하면 거짓이 된다). */\n /*\n * 접은 지점의 리비전 — 사슬에 적을 이름이다. 꼬리를 접었으면 그 꼬리의 끝, 아무것도 안 읽었으면\n * 씨앗의 자리 그대로다(모르면 0).\n */\n const foldedTo = rows.length ? (rows[rows.length - 1]?.revision ?? 0) : (from ?? 0)\n\n const keep = (st: any, fold?: { reducer: ReducerCheckpoint; oee: OeeCheckpoint }): any => {\n /* 재개점을 함께 남긴다 — 상태만 남기면 다음 번에 또 0부터 접어야 한다(그것이 이 작업의 요점이다).\n **구조가 갈린 폴드에는 재개점을 붙이지 않는다**: 마디를 건너뛴 씨앗은 그 경계의 판정을 잃는다. */\n if (asOfNowRead && tip && st) {\n void this.saveFoldedSnapshot(domainId, instanceId, { revision: tip.revision, state: st, structureRev: tip.structureRev, fold })\n }\n /*\n * 사슬에는 **과거를 접었을 때도** 한 지점을 남긴다 (2026-08-18 실측으로 고침).\n *\n * 처음에는 「지금 읽기」에서만 남겼다. 그런데 도는 트윈의 지금 읽기는 커널 스냅샷으로 즉시 답하고\n * 폴드에 닿지 않는다 — 그래서 사슬이 **영원히 비어 있었다**(실측: 지점 0개, 시간여행 3.7s 그대로).\n *\n * 지점은 「지금」을 주장하지 않는다: 자기 리비전과 시각을 달고 있으므로 과거 폴드의 결과를 남겨도\n * 거짓이 아니다(그것이 스냅샷과 다른 점이다). 그래서 첫 과거 조회가 다음 과거 조회를 빠르게 한다.\n */\n if (fold && st) {\n const at = asOfNowRead && tip ? tip.revision : foldedTo\n if (at > 0)\n void this.keepChainPoint(domainId, instanceId, {\n revision: at,\n ...(lastEventTime ? { eventTime: lastEventTime } : {}),\n structureRev: (asOfNowRead && tip ? tip.structureRev : null) ?? null,\n fold\n }).catch(() => {})\n }\n return st\n }\n\n /*\n * 씨앗이 있으면 **이어 접는다** — 한 구조 안에서만(구조가 갈리면 아래 마디 경로가 맡는다).\n * 새 재개점도 함께 남긴다: 다음 번에 또 꼬리만 접을 수 있어야 이 지름길이 계속 산다.\n */\n if (resume?.fold?.reducer && segments.length <= 1) {\n const model = (segments[0]?.model ?? (asOfNow && newest) ?? reg.model) as TwinModelDef\n const out = replayFrom(model, resume.fold.reducer, segments[0]?.events ?? [])\n return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() })\n }\n\n if (!segments.length) {\n const model = ((asOfNow && newest) || reg.model) as TwinModelDef\n const out = replayWithCheckpoint(model, [])\n return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() })\n }\n if (segments.length === 1) {\n const out = replayWithCheckpoint(segments[0].model, segments[0].events)\n return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() })\n }\n\n /* 커널 계약도 `model` 이다(0.6.14) — 경계에서 어휘를 되돌려 담던 브릿지가 사라졌다. */\n const { state, shifts } = replaySegments(segments)\n /* 경계에서 사라진 것을 조용히 넘기지 않는다 — 수가 줄어든 이유를 어딘가에는 남겨야 한다. */\n for (const sh of shifts)\n if (sh.equipmentDropped || sh.locationsDropped || sh.personsDropped || sh.assetsDropped)\n console.info(`[twin-engine] \"${instanceId}\" replay crossed a structure change — dropped ${sh.equipmentDropped} equipment, ${sh.locationsDropped} locations, ${sh.personsDropped} persons, ${sh.assetsDropped} assets that no longer exist.`)\n return keep(withNow(state))\n }\n\n /**\n * 공간(공동배치) 시각 범위 — 스크러버 앵커(runtime-state-model §4·§6). 그 공간 전 인스턴스 저널의 min/max eventTime.\n * 반환 {minTime, maxTime}(ISO) — 이벤트/시각 없으면 null. 클라 히스토리 스크러버가 이 범위를 시각축으로 그린다.\n *\n * ── 두 수를 구하려고 저널을 다 읽지 않는다 (2026-08-20 실측으로 잡음) ────────\n * 여기서 인스턴스마다 `find()` 로 **행을 전부 엔티티로 하이드레이션**한 다음 JS 에서 min/max 를\n * 골랐다. 그런데 이 함수는 화면 상단의 컨텍스트 띠가 **4초마다** 부른다. 실측한 개발 서버에서\n * `order-check` 한 트윈이 275,882행 · `payload` 131MB 였다 — 4초마다 그 JSON 을 전부 파싱한 것이다.\n *\n * 그 결과가 이랬다: 프로세스 CPU 81~152%, 아무 일도 하지 않는 질의가 8~14초. JS 프로파일의 상위가\n * TypeORM 의 `RelationIdLoader`·`RawSqlResultsToEntityTransformer`·`stringToSimpleJson`(= `payload`\n * 파싱)이고 GC 가 16.7% 였다. **트윈 틱도 저널 쓰기도 아니라 이 읽기였다.**\n *\n * 집계는 DB 가 한다. `(domain, instanceId, eventTime)` 인덱스가 이미 있어(`ix_twin_event_1`)\n * 인덱스의 **양 끝을 집는다** — 행을 하나도 실어 오지 않는다.\n *\n * ── 왜 MIN 과 MAX 를 한 문장에 넣지 않나 (실측) ─────────────────────────────\n * 처음에 `SELECT MIN(...), MAX(...) ... WHERE instanceId IN (...)` 한 방으로 두었더니 **21ms** 였다.\n * 집계가 **둘이면** 옵티마이저의 「인덱스 끝을 집는」 최적화가 걸리지 않아 인덱스 구간을 훑는다 —\n * 즉 비용이 여전히 **행 수에 비례**한다. 트윈마다 단일 집계로 나눠 물으면 **0.32ms**(트윈 3개 · 6왕복)\n * 이고, 비용이 **트윈 수에 비례**한다. 규모 기준(엔티티 10만)에서는 이 차이가 본질이다.\n *\n * 왕복은 트윈당 둘이지만 **함께 띄운다** — 원격 DB 에서 직렬로 돌면 왕복 지연이 그대로 쌓인다.\n *\n * 드라이버 다섯을 다 지나가야 하므로 raw SQL 을 쓰지 않는다(쿼리빌더의 MIN/MAX 는 이식된다).\n * 돌려주는 값의 **모양은 드라이버마다 다르다**(문자열·Date) — 받은 뒤에 한 번 정규화한다(`parseTime`).\n */\n static async timeRange(domainId: string, spaceId: string): Promise<{ minTime: string | null; maxTime: string | null }> {\n const regs = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n const ids = regs.map(r => r.instanceId)\n if (!ids.length) return { minTime: null, maxTime: null }\n\n /**\n * 한 트윈 저널의 시각 양 끝 하나 — 단일 집계라 인덱스 끝을 집는다.\n *\n * 집계식을 **조립하지 않고 표에 리터럴로 적는다.** `` `${agg}(e.eventTime)` `` 로 만들면 이 자리가\n * 집계를 쓰는지 훑는 검사(`journal-read-discipline`)가 찾지 못한다 — 실제로 그렇게 빨개졌다.\n * 번역 키에서 겪은 것과 같은 규율이다: 검사가 일하게 두는 편이 낫다.\n */\n const AGG_SELECT = { MIN: 'MIN(e.eventTime)', MAX: 'MAX(e.eventTime)' } as const\n const edge = async (instanceId: string, agg: 'MIN' | 'MAX'): Promise<number | null> => {\n const row = await getRepository(TwinEvent)\n .createQueryBuilder('e')\n .select(AGG_SELECT[agg], 't')\n .where('e.domain = :domainId', { domainId })\n .andWhere('e.instanceId = :instanceId', { instanceId })\n .getRawOne<{ t: unknown }>()\n return parseTime(row?.t)\n }\n\n let min = Infinity\n let max = -Infinity\n\n /*\n * 한 번에 띄우는 수를 묶는다 — 공간에 트윈이 수백이면 왕복 수백 개를 동시에 보내 커넥션 풀을\n * 말려 버린다(이 함수 하나 때문에 다른 질의가 기다리게 된다).\n */\n for (let i = 0; i < ids.length; i += TIME_RANGE_FANOUT) {\n const batch = ids.slice(i, i + TIME_RANGE_FANOUT)\n const edges = await Promise.all(batch.flatMap(id => [edge(id, 'MIN'), edge(id, 'MAX')]))\n for (let k = 0; k < edges.length; k += 2) {\n const lo = edges[k]\n const hi = edges[k + 1]\n if (lo !== null && lo < min) min = lo\n if (hi !== null && hi > max) max = hi\n }\n }\n\n if (min === Infinity) return { minTime: null, maxTime: null }\n return { minTime: new Date(min).toISOString(), maxTime: new Date(max).toISOString() }\n }\n\n /** 정지 훅 — 인스턴스 정지 시 부수자원 정리(예: reference-live 피드 unsubscribe). 순환 임포트 없이 결선. */\n static stopHooks: ((id: string) => void)[] = []\n static onStop(fn: (id: string) => void): void {\n this.stopHooks.push(fn)\n }\n\n static async stop(domainId: string, id: string): Promise<void> {\n const i = this.instances[runtimeKey(domainId, id)]\n if (i) {\n /*\n * **끄기 전에 남긴다** — 지금이 메모리가 진실인 마지막 순간이다.\n *\n * 남기지 않으면 다음 조회가 저널을 전량 다시 접는다(그 값은 어차피 방금 메모리에 있던 것이다).\n * 체크포인트 루프가 20초마다 뜨지만 그 사이에 멈추면 그 구간이 통째로 다시 접힌다.\n */\n await this.persistSnapshot(domainId, id).catch(err =>\n twinError(`[twin-engine] snapshot on stop fail \"${id}\"`, err?.message ?? err)\n )\n /*\n * **모아 둔 저널도 지금 흘린다** — 주기 flush 사이(최대 `BROADCAST_COALESCE_MS`)에 멈추면 그 구간의\n * 사실이 사라진다. 스냅샷만 남기면 상태는 살아도 **왜 그렇게 됐는지**가 빈다(저널이 답하는 것이다).\n * 쓰기는 이 함수를 기다리지 않지만(비차단) 버퍼는 여기서 비워지므로 다음 기동이 두 번 적지 않는다.\n */\n await this.flushJournal(i)\n clearInterval(i.timer)\n i.unsub()\n delete this.instances[runtimeKey(domainId, id)]\n await getRepository(TwinInstance)\n .update({ domain: { id: i.domainId }, instanceId: id }, { status: 'stopped' })\n .catch(err => twinError('twin deregister fail', err))\n }\n for (const hook of this.stopHooks) { try { hook(id) } catch { /* 훅 격리 */ } }\n }\n\n /*\n * tick 한 번 — **한 트윈의 예외가 서버를 내리지 못하게** 감싼다.\n *\n * 잘못된 시나리오가 실렸을 때 다음 tick 에서 `rate.meanPerHour` 를 읽다 터졌고, 타이머 콜백의\n * 예외는 아무도 받지 않아 **uncaught exception 으로 프로세스가 내려갔다.** 한 테넌트의 잘못된\n * 선언이 모든 테넌트를 멈춘 셈이다. 문 앞에서 막는 것이 1차 방벽이고(`validateScenario`),\n * 이것이 2차 방벽이다.\n *\n * **조용히 삼키지 않는다.** 실행을 멈추고 그 사실을 남긴다 — 예외를 무시하고 계속 tick 하면\n * 같은 오류가 매 주기 쏟아지고, 그 트윈은 \"도는 것처럼 보이면서\" 아무것도 진행하지 않는다.\n */\n /**\n * 같은 현장 트윈들의 **설비 상태**를 커널에 넘긴다 — 커널이 요청할 때만.\n *\n * ── 경계 (2026-08-14) ──────────────────────────────────────────────────────\n * 호스트가 아는 것은 **누가 같은 현장에 있는가** 하나다. 무엇을 읽고 그것을 어떻게 부하로 바꿀지는\n * 커널이 정한다(계수는 트윈의 모델이 선언한다). 호스트가 kW 를 계산해 주면 트윈마다 다른 규칙이\n * 생기고, 그 규칙은 어디에도 적혀 있지 않게 된다.\n *\n * 상태만 넘긴다. 스냅샷을 통째로 넘기면 상태 크기에 비례한 비용을 매 tick 치르게 된다 —\n * 설비 목록은 그 트윈의 커널이 이미 들고 있는 것이라 훑는 값이 싸다.\n */\n private static feedPeerEquipment(inst: InstanceRuntime): void {\n const kernel: any = inst.kernel\n if (typeof kernel?.observePeerEquipment !== 'function') return // 이웃을 읽지 않는 커널\n if (!inst.spaceId) {\n kernel.observePeerEquipment([]) // 현장이 없으면 이웃도 없다(옛 상태가 남지 않게 비운다)\n return\n }\n const peers: { id: string; status?: string }[] = []\n for (const other of Object.values(this.instances)) {\n if (other === inst || other.domainId !== inst.domainId || other.spaceId !== inst.spaceId) continue\n const eq: Map<string, any> | undefined = (other.kernel as any)?.equipment\n if (!eq || typeof eq.forEach !== 'function') continue\n eq.forEach(e => peers.push({ id: String(e?.id ?? ''), status: String(e?.status ?? '') }))\n }\n kernel.observePeerEquipment(peers)\n }\n\n private static tickGuarded(domainId: string, id: string, runtime: TwinRuntimeType): void {\n const inst = this.instances[runtimeKey(domainId, id)]\n const load = inst && (inst.load ?? (inst.load = newLoadMeter()))\n const t0 = performance.now()\n try {\n /* 이웃의 설비 상태를 먼저 싣는다 — 커널이 이번 tick 에서 부하를 만들 때 읽는다. */\n if (inst) this.feedPeerEquipment(inst)\n runtime.tick(this.TICK_MS)\n\n /* 재고 말한다 — 시뮬 틱은 메인 이벤트 루프에서 수행된다. 예산(간격의 절반)을 넘기면 HTTP·구독이\n 함께 느려지는데, 예전에는 그것을 볼 계기판이 없어 \"터지면 알고 느려지면 몰랐다\". */\n if (load) {\n const took = performance.now() - t0\n recordPhase(load, 'tick', took)\n const j = judgeCycle(load, took, this.TICK_MS, Date.now())\n if (j.warn) twinWarn(slowTickMessage(id, took, j.budgetMs, load))\n this.guardStarvation(domainId, id, took)\n }\n } catch (err: any) {\n /*\n * 멈추는 길은 **하나**다(`stop`) — 예전에는 타이머만 껐다. 그러면 등록부는 계속 `running` 이라\n * 말하고(아무 틱도 없는 채로), 부팅 재개는 그 거짓을 근거로 다시 세운다. 스냅샷 보존·피드 정리·\n * 등록부 갱신이 모두 `stop` 안에 있다.\n */\n this.stopWithNote(\n domainId,\n id,\n { code: 'tick-failed', params: { reason: String(err?.message ?? err) } },\n `[twin-engine] \"${id}\" tick failed — this twin is stopped (other twins keep running). ` +\n `Fix the declaration and start it again. Reason: ${err?.message ?? err}`\n )\n }\n }\n\n /**\n * 호스트를 굶기는 트윈을 멈춘다 — **도는 척하는 것보다 멈춘 것이 낫다.**\n *\n * 굶김 문턱을 넘는 틱이 연속 `STARVE_STREAK` 번이면 그 트윈은 구조적으로 무겁다(우연이 아니다).\n * 문턱 아래로 한 번만 내려와도 연속을 끊는다 — 무거운 순간 하나로 트윈을 내리지 않는다.\n */\n private static guardStarvation(domainId: string, id: string, tookMs: number): void {\n const key = runtimeKey(domainId, id)\n const starveMs = this.TICK_MS * this.STARVE_FACTOR\n if (!(tookMs >= starveMs)) {\n this.starveStreak.delete(key)\n return\n }\n const streak = (this.starveStreak.get(key) ?? 0) + 1\n this.starveStreak.set(key, streak)\n if (streak < this.STARVE_STREAK) return\n\n this.starveStreak.delete(key)\n const secs = Math.round(tookMs) / 1000\n this.stopWithNote(\n domainId,\n id,\n { code: 'starved', params: { streak, thresholdSec: starveMs / 1000, lastSec: secs } },\n `[twin-engine] \"${id}\" stopped — ${streak} consecutive ticks over ${starveMs / 1000}s (last ${secs}s). ` +\n `A simulation tick runs on the main loop, so this twin was stalling HTTP, subscriptions and every other twin. ` +\n `Its state is checkpointed; start it again after making it lighter (fewer orders/resources) or wait for off-loop ticking.`\n )\n }\n\n /** 멈추고 **이유를 남긴다** — 이유 없는 「정지」는 사람이 자기가 멈춘 것으로 읽는다. */\n private static stopWithNote(domainId: string, id: string, note: StopNote, log: string): void {\n twinError(log)\n this.stopNotes.set(runtimeKey(domainId, id), note)\n this.stop(domainId, id).catch(err => twinError(`[twin-engine] stop after guard failed \"${id}\"`, err?.message ?? err))\n }\n\n /** 이 트윈이 스스로 멈춘 이유(있으면) — 화면이 옮겨 말한다. */\n static stopNoteOf(domainId: string, id: string): StopNote | undefined {\n return this.stopNotes.get(runtimeKey(domainId, id))\n }\n\n /**\n * 이 트윈이 **지금 실행 중인가** — 판정의 집 하나.\n *\n * \"스냅샷이 있나\" 로는 답이 되지 않는다: 웜스타트가 되살린 상태가 캐시에 남아 있으면 멈춘 트윈도\n * 스냅샷을 낸다. 그것을 관측 중으로 읽으면 화면이 **멈춘 트윈의 작업을 0 건이라고 단언**한다\n * (실제로 그렇게 나왔다 — 관측이 없는 것과 0 건은 다르다는 이 프로젝트의 규율을 화면이 어겼다).\n *\n * 목록이 쓰는 것과 **같은 술어**다(`list()` 의 `running`) — 두 벌이면 어긋난다.\n */\n static isRunning(domainId: string, id: string): boolean {\n return !!this.instances[runtimeKey(domainId, id)]\n }\n\n static runtime(domainId: string, id: string): TwinRuntimeType | undefined {\n return this.instances[runtimeKey(domainId, id)]?.runtime\n }\n\n /*\n * 커맨드 실행 — **판정은 `routeCommand`(순수)가 하고 여기서는 실행만** 한다.\n * 판정을 코드 한가운데 두면 이 부류를 테스트로 못 잡는다(엔진은 DB 를 물고 있어 단위 테스트가\n * 불러올 수 없다). 예전에는 리졸버가 `inst.runtime.dispatch` 를 곧바로 불러 미러에서 터졌다.\n */\n static async dispatchCommand(domainId: string, instanceId: string, command: any): Promise<{ accepted: boolean; error?: string; errorCode?: string; errorParams?: Record<string, string | number> }> {\n const inst = this.instances[runtimeKey(domainId, instanceId)]\n const type = String(command?.type ?? '')\n const route = routeCommand(\n inst && { mode: inst.mode, hasRuntime: !!inst.runtime, hasKernelDispatch: typeof (inst.kernel as any)?.dispatch === 'function' },\n !!inst && inst.domainId === domainId,\n type\n )\n if (route.target === 'reject') {\n return { accepted: false, errorCode: route.errorCode, errorParams: route.errorParams, error: route.errorCode }\n }\n\n const cmd = { ...command, tenantId: domainId } // tenantId 는 호출자 도메인으로 각인(감사·무결성)\n if (route.target === 'runtime') return inst!.runtime!.dispatch(cmd)\n\n /*\n * 미러 — 관측 커널로 보내고, **커맨드가 낸 사실을 저널 큐에 실어** 코얼레서가 번호를 부여하게 한다.\n * 미러에는 State 구독 배관이 없어(시뮬은 그 경로로 저널링) 커널 방출이 아무 데도 닿지 않는다.\n * 여기서 DB 를 따로 읽어 번호를 매기면 인메모리 카운터와 어긋나 리비전이 겹친다(겹침은 오류를\n * 내지 않고 재생 순서만 조용히 뒤섞는다).\n */\n const kernel: any = inst!.kernel\n const emitted: any[] = []\n const off = kernel.onEvent?.((e: any) => emitted.push(e))\n let ack: any\n try {\n ack = kernel.dispatch(cmd)\n } finally {\n off?.()\n }\n if (ack?.accepted && emitted.length) {\n inst!.pendingJournal = [...(inst!.pendingJournal ?? []), ...emitted]\n inst!.dirty = true // 코얼레서가 이번 주기에 비우고 브로드캐스팅까지 하게 한다\n }\n return ack ?? { accepted: false, errorCode: 'unknown-command', error: 'unknown-command' }\n }\n\n /**\n * 도메인 소유 게이트 — 인스턴스가 이 도메인 소유일 때만 true(테넌트 격리).\n * 없거나 다른 도메인이면 false. 노출 리졸버(per-id metrics/attentions/state/stop/forecast)가\n * this.instances[id] 를 만지기 전에 반드시 이걸로 확인해야 한다. 인스턴스 id 는 추측 가능하므로\n * 검증 없이 접근하면 크로스테넌트 읽기/정지가 가능해진다.\n */\n /**\n * 이 런타임의 **관측 모드** — `'live'`(외부 실물을 미러) 또는 `'sim'`(커널이 실행한다). 기동 중이 아니면 없다.\n *\n * 소비처가 `instances[id].mode` 를 직접 읽던 자리를 대신한다. 레지스트리를 밖에 열면 도메인 확인이\n * 자리마다 제각각이 되고, 실제로 그렇게 됐다(테넌트 격리 전수 확인, 2026-08-06).\n */\n static modeOf(domainId: string, id: string): 'live' | 'sim' | undefined {\n return this.instances[runtimeKey(domainId, id)]?.mode\n }\n\n static owns(domainId: string, id: string): boolean {\n return !!this.instances[runtimeKey(domainId, id)]\n }\n\n /**\n * 이 트윈이 이 테넌트 것인가 — **떠 있든 아니든.**\n *\n * `owns()` 는 **기동 중인** 런타임만 안다. 그것을 이력 조회의 관문으로 쓰면, 꺼진 트윈의 저널을\n * 읽으려 할 때 \"이 테넌트에 없다\" 는 답이 돌아온다 — 두 가지가 틀렸다. 첫째, 저널은 트윈이 꺼져\n * 있을 때 **가장 필요한 것**이다(그게 이력의 존재 이유다). 둘째, 그 문장은 남의 것이라는 뜻이라\n * 사용자가 권한 문제로 오해한다. 실제로는 그냥 실행 중이 아닐 뿐이다.\n *\n * 소유는 **등록부**가 안다. 이력·집계처럼 런타임과 무관한 질문은 이쪽에 묻는다.\n */\n static async ownsRegistered(domainId: string, instanceId: string): Promise<boolean> {\n if (this.owns(domainId, instanceId)) return true\n return !!(await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } }))\n }\n\n /**\n * **이 공간의 인스턴스들** — 한 현실을 여러 렌즈가 비추므로, 공간을 물으면 그 렌즈 전부를 답한다.\n *\n * 화면이 이 규칙을 손으로 짜지 않게 서버가 답한다. 예측 화면은 같은 확장을 **한 파일에서 두 번**\n * 복제하고 있었다(전체 목록을 받아 클라이언트에서 걸렀다) — 규칙이 흩어지면 한쪽만 고쳐진다.\n *\n * 떠 있지 않은 것도 포함한다: 공간에 무엇이 있는지는 기동 여부와 다른 사실이다.\n */\n static async instanceIdsOfSpace(domainId: string, spaceId: string): Promise<string[]> {\n if (!spaceId) return []\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n return rows.map(r => r.instanceId).filter((x): x is string => !!x)\n }\n\n /**\n * **이 공간에서 봐야 할 것** — 공간의 모든 렌즈에서 신호를 모은다.\n *\n * 합집합이 그대로 뜻이 있는 유일한 렌즈다(예측은 합칠 수 없다 — P50 두 개를 더할 수 없다).\n * 정렬·잘라내기는 화면과 **같은 규칙**을 쓴다(`digestAttentions`) — 서버가 고른 상위 N 이 화면이\n * 고를 N 과 달라지면 그 어긋남은 아무 데서도 오류로 드러나지 않는다.\n *\n * 신호마다 어느 트윈에서 왔는지(`instanceId`)를 붙인다. 공간에서 보면 같은 자리 id 가 렌즈마다\n * 다른 것을 가리킬 수 있고, 조치는 결국 그 트윈에 보내야 한다.\n */\n static async attentionsOfSpace(domainId: string, spaceId: string, limit?: number): Promise<{ attentions: any[]; attentionTotal: number; severityByLocation: Record<string, string> }> {\n const ids = await this.instanceIdsOfSpace(domainId, spaceId)\n const lenses = ids\n /* 떠 있지 않은 트윈은 **지금** 신호가 없다(그 시절 신호는 시간여행이 답한다). */\n .filter(id => this.owns(domainId, id))\n .map(id => {\n const kernel: any = this.kernel(domainId, id)\n const snap = kernel?.getSnapshot?.() ?? this.snapshot(domainId, id)\n return { instanceId: id, attentions: snap?.attentions ?? [] }\n })\n /* 모으는 규칙(태깅·급한 순서·자리 색)은 순수 함수가 들고 있다 — 여기서 손으로 접지 않는다. */\n return mergeLensAttentions(lenses, limit)\n }\n\n /** 라이브 커널(ForecastTwin) — forecast/divergence 예측 연산용. */\n static kernel(domainId: string, id: string): any {\n return this.instances[runtimeKey(domainId, id)]?.kernel\n }\n\n /** 라이브 처리량 계측 스냅샷(모니터, ④-1) — 내부 누적(_acc*) 제외한 공개 지표. live 아니면 null. */\n static metrics(domainId: string, id: string): any {\n const m = this.instances[runtimeKey(domainId, id)]?.metrics\n if (!m) return null\n return {\n instanceId: id,\n ingestedTotal: m.ingestedTotal, broadcastTotal: m.broadcastTotal, journaledTotal: m.journaledTotal,\n ingestRate: m.ingestRate, broadcastRate: m.broadcastRate, journalRate: m.journalRate,\n backlog: m.backlog, broadcastCoalesceMs: this.broadcastPeriodMs,\n /* 작업별 부하 — 무거운 것부터. 잰 적이 없으면 null(0 으로 채우면 \"빠르다\" 로 읽힌다). */\n load: loadSummary(this.instances[runtimeKey(domainId, id)]?.load, this.TICK_MS)\n }\n }\n\n /**\n * 부하 계기판만 따로 — **시뮬 트윈도 포함한다.**\n *\n * `metrics()` 는 라이브 지표(`inst.metrics`)가 있어야 무언가를 돌려준다. 그런데 이벤트 루프를 점유하는\n * 것은 주로 **시뮬 틱**이고, 시뮬 인스턴스에는 그 지표가 없어 통째로 안 보였다.\n */\n static load(domainId: string, id: string): any {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (!inst) return null\n\n return {\n instanceId: id,\n mode: inst.mode ?? 'sim',\n domainId: inst.domainId,\n domainLabel: inst.domain?.subdomain,\n restartPolicy: inst.restartPolicy,\n tickMs: this.TICK_MS,\n running: !!inst.timer || inst.mode === 'live',\n ...(loadSummary(inst.load, this.TICK_MS) ?? { recent: null, total: null, forksCreated: 0, overBudget: 0, budgetMs: this.TICK_MS * 0.5, loadRatio: null })\n }\n }\n\n /**\n * **한 곳에서 보는 전체 부하** — 몇 개가 실행 중이고, 누가 루프를 점유하고 있나.\n *\n * 시뮬 트윈도 포함한다(`metrics()` 는 라이브 지표가 있어야 답해서 시뮬이 통째로 안 보였다).\n */\n static fleet(domainId?: string): any {\n const keys = Object.keys(this.instances).filter(key => !domainId || isOfDomain(key, domainId))\n const rows = keys.map(key => {\n const at = parseRuntimeKey(key)\n const inst = this.instances[key]\n /* 도메인을 함께 넘긴다 — 운영자가 먼저 묻는 것은 \"어느 테넌트가 루프를 먹나\" 다.\n 읽을 수 있는 이름(subdomain)은 라이브 인스턴스에만 붙어 있으므로, 없으면 리졸버가 채운다. */\n return {\n instanceId: at.instanceId,\n mode: inst.mode ?? 'sim',\n domainId: at.domainId,\n domainLabel: inst.domain?.subdomain,\n meter: inst.load\n }\n })\n\n return {\n tickMs: this.TICK_MS,\n broadcastCoalesceMs: this.broadcastPeriodMs,\n /* 브로드캐스팅 주기를 늘린 횟수 — 늘어난 주기만 보면 「원래 그런 값」으로 읽힌다. */\n broadcastBackoffs: this.broadcastBackoffs,\n /* 물품 범위를 좁히지 못해 전부 만든 횟수 — 좁히기가 실제로 듣고 있는지를 이 값으로 본다. */\n broadcastPasses: this.broadcastPasses,\n broadcastFullPasses: this.broadcastFullPasses,\n broadcastFullEvery: this.FULL_BROADCAST_EVERY,\n /* **루프가 실제로 얼마나 막혔나** — 트윈 부하와 나란히 놓고 원인을 가린다(loop-lag.ts 주석). */\n loopLag: loopLag.view(),\n ...fleetLoad(rows, this.TICK_MS),\n /* 줄마다 상세 — 화면이 펼쳐 볼 수 있게. 최근 부하 순서는 fleetLoad 가 정한다. */\n details: keys.map(key => { const at = parseRuntimeKey(key); return this.load(at.domainId, at.instanceId) }).filter(Boolean)\n }\n }\n\n /** 이 트윈에서 fork 가 만들어졌다 — 예측 한 번이 수십 개를 만든다. */\n static countForks(domainId: string, id: string, count: number): void {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst) recordFork(inst.load ?? (inst.load = newLoadMeter()), count)\n }\n\n /** 엔진 밖(예측 질의 등)에서 무거운 작업을 잰다 — 같은 계기판에 모인다. */\n static recordLoad(domainId: string, id: string, phase: LoadPhase, tookMs: number): void {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst) recordPhase(inst.load ?? (inst.load = newLoadMeter()), phase, tookMs)\n }\n\n /*\n * ── 동기화 건강 장부 ───────────────────────────────────────────────────────\n *\n * **런타임이 아니라 엔진이 든다.** 인스턴스에 붙이면 트윈을 재기동할 때 사라지는데, 사람이 알고 싶은\n * 것은 바로 그 순간이다 — 「고쳐서 다시 띄웠는데 이제 통과하나」. 프로세스가 사는 동안 이어진다.\n *\n * 지금은 메모리만이다. 창이 닫힐 때 한 행씩 영속하는 것은 `onWindowClosed` 한 자리에 붙는다.\n */\n private static ingestLedgers: Record<string, IngestLedger> = {}\n\n /** 창이 닫힐 때 부를 곳 — 영속 계층이 부팅에서 한 번 등록한다(커널 층은 그 계층을 모른다). */\n private static onWindowClosed?: (at: { domainId: string; instanceId: string }, closed: IngestWindow) => void\n\n /**\n * 닫힌 창을 받을 곳을 등록한다 — **영속(B)이 붙는 유일한 문.**\n *\n * 이 패키지는 저장 계층을 모른다. 등록하는 쪽이 자기 방식으로 쓴다. 훅이 오류를 내도 장부는 계속 굴러간다\n * (`rollIngestWindow` 가 감싼다) — 영속을 지키려고 관측을 멈추지 않는다.\n */\n static onIngestWindowClosed(\n fn: (at: { domainId: string; instanceId: string }, closed: IngestWindow) => void\n ): void {\n this.onWindowClosed = fn\n }\n\n /**\n * 한 번의 인제스트 결과를 장부에 적는다.\n *\n * `offered` 는 **제시된 레코드 수**다(거부 여부 무관). 통과율을 서로 다른 두 계수기에서 나눠 계산하면\n * 분모와 분자가 다른 것을 세게 되므로, 한자리에서 본 수를 그대로 넘긴다.\n */\n static recordIngestResult(\n domainId: string,\n instanceId: string,\n offered: number,\n rejected: { record?: unknown; errors?: string[] }[] | undefined,\n nowMs = Date.now(),\n /**\n * 매핑은 통과했는데 **커널이 받지 않은** 수(`ingestLive` 의 반환과 견주어 얻는다).\n *\n * 「통과」로 세지 않는다 — 트윈이 멈춘 사이 사실이 사라지는데 화면이 100% 라고 말하게 된다.\n */\n undelivered = 0\n ): void {\n const key = runtimeKey(domainId, instanceId)\n const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = newIngestLedger())\n recordIngest(\n ledger,\n offered,\n rejected,\n nowMs,\n closed => this.onWindowClosed?.({ domainId, instanceId }, closed),\n undelivered\n )\n }\n\n /**\n * **원본에 닿지 못했다**를 적는다 — 「받은 것이 없다」와 가른다(§`recordReadFailure`).\n *\n * 이 문이 없던 동안 실 원본이 끊겨도 트윈의 조회 가능한 상태에 그 사실이 없었다. 화면이 볼 수 있는\n * 것은 「새 사실이 없다」뿐이었고 그것은 「원본이 조용하다」와 구별되지 않는다 — 실증 중에 원본이\n * 끊기면 사용자가 원인을 찾을 수 없다.\n *\n * 로그로는 말하고 있었다(어댑터가 재시도를 경고한다). 그러나 **로그는 사람이 볼 때만 값이 있다** —\n * 화면이 말하려면 상태에 있어야 한다.\n */\n static recordIngestReadFailure(domainId: string, instanceId: string, reason: string, nowMs = Date.now(), stream?: string): void {\n const key = runtimeKey(domainId, instanceId)\n const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = newIngestLedger())\n recordReadFailure(ledger, reason, nowMs, stream)\n }\n\n /**\n * 읽기가 성공했다 — 단절 기록을 지운다.\n *\n * **빈 읽기도 성공이다.** 원본이 「새 것이 없다」고 답한 것은 닿았다는 뜻이므로, 그때도 부른다.\n * 그 둘을 같게 두면 조용한 원본이 끊긴 원본으로 보인다.\n */\n static clearIngestReadFailure(domainId: string, instanceId: string): void {\n const ledger = this.ingestLedgers[runtimeKey(domainId, instanceId)]\n if (ledger) clearReadFailure(ledger)\n }\n\n /**\n * **읽었는데 창을 넘길 수 없다**를 적는다 — 위와 **조치가 반대인** 사실이다(§`recordCursorStall`).\n *\n * 이 문이 없던 동안 이 사실이 `recordIngestReadFailure` 로 나갔다. 그래서 화면이 「원본에 닿지\n * 못한다」고 말했는데 원본은 **답한** 상태였고, 그 답의 모양이 커서를 이긴 것이었다(한 시각에 한\n * 페이지보다 많은 행). 사람은 원본을 의심하고 기다리는데 **기다림으로는 영원히 풀리지 않는다.**\n *\n * 조치가 반대인 두 사실을 한 이름으로 부르면 그 이름은 정보가 아니라 오해다.\n */\n static recordIngestCursorStall(domainId: string, instanceId: string, reason: string, nowMs = Date.now(), stream?: string): void {\n const key = runtimeKey(domainId, instanceId)\n const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = newIngestLedger())\n recordCursorStall(ledger, reason, nowMs, stream)\n }\n\n /** 창을 넘겼다 — 정체 기록을 지운다(풀린 정체가 화면에 남아 있으면 그것도 거짓이다). */\n static clearIngestCursorStall(domainId: string, instanceId: string): void {\n const ledger = this.ingestLedgers[runtimeKey(domainId, instanceId)]\n if (ledger) clearCursorStall(ledger)\n }\n\n /**\n * 저널에 **적은 것**을 같은 장부에 남긴다 — 유입과 같은 10분 창에.\n *\n * ── 왜 유입 장부에 넣나 ────────────────────────────────────────────────────\n * 새 장부를 만들면 「닫힌 창만 최근」·「0 과 없음을 가른다」·영속을 두 벌 지켜야 하고, 그중 한 벌만\n * 고쳐지는 것이 보통이다. 유입 창은 그 규율이 이미 들어 있고 닫힐 때 행으로 남는다.\n *\n * ── 이 값이 없으면 무엇을 못 보나 ──────────────────────────────────────────\n * 계기(`journalRate`)는 **지금**만 답한다. 프로세스를 다시 띄우면 0 에서 시작하므로 「어제 이 시각에도\n * 이랬나」·「고친 뒤로 줄었나」를 물을 자리가 없다. 2026-08-20 에 고친 것이 바로 쓰기 경로이므로,\n * 되돌아가는 것을 볼 수 있어야 한다.\n */\n static recordJournalWrite(domainId: string, instanceId: string, rows: number, nowMs = Date.now()): void {\n const key = runtimeKey(domainId, instanceId)\n const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = newIngestLedger())\n recordLedgerWrite(ledger, rows, nowMs, closed => this.onWindowClosed?.({ domainId, instanceId }, closed))\n }\n\n /**\n * 「이 트윈이 현장과 맞춰지고 있나」 — 한눈 판정 + 추이 + 사유 + 표본.\n *\n * 조회할 때 창을 한 번 굴린다: 유입이 멈추면 다음 인제스트가 없어 창이 영원히 닫히지 않는데, 그러면\n * 「최근」이 옛것으로 남는다. 타이머를 두지 않는 이유는 트윈마다 타이머를 걸면 그 타이머들이 다시\n * 메인 루프에 얹히기 때문이다(오늘 확인한 그 부하를 이 기능이 다시 만들 이유가 없다).\n */\n /**\n * 도메인의 트윈마다 **한 줄 요약** — 목록 화면과 미니 추이용.\n *\n * ── 왜 상세와 따로인가 ─────────────────────────────────────────────────────\n * `ingestHealthOf` 는 사유 문구와 **레코드 원문 표본**까지 낸다. 목록에 트윈이 스무 개면 그 원문이\n * 스무 벌 실려 조회가 무거워지고, 화면은 어차피 그것을 그리지 않는다. 그래서 여기서는 **숫자만** 낸다.\n *\n * 추이는 창당 숫자 넷이라 스파크라인 하나에 충분하고 가볍다.\n *\n * ── 등록된 트윈을 기준으로 훑는다 ──────────────────────────────────────────\n * 도는 트윈만 훑으면 「고치려고 멈춰 둔 트윈」이 목록에서 사라진다 — 사람이 방금 멈춘 그것을 보려고\n * 목록을 여는데 없으면 결함으로 읽는다. 그래서 호출부(목록 화면)가 아는 instanceId 들을 받는다.\n */\n static ingestHealthBrief(\n domainId: string,\n instanceIds: string[]\n ): { instanceId: string; verdict: string; acceptedRatio: number | null; trend: { offered: number; rejected: number; undelivered: number; rows: number }[]; lastAt: string | null }[] {\n return instanceIds.map(instanceId => {\n const full = this.ingestHealthOf(domainId, instanceId)\n return {\n instanceId,\n verdict: full.verdict,\n /* 최근 **닫힌** 창의 통과율. 창이 안 닫혔으면 비운다 — 0 이나 1 로 채우지 않는다. */\n acceptedRatio: full.recent?.acceptedRatio ?? null,\n /*\n * 스파크라인용 — 창마다 셋. **미전달을 빼놓으면 스파크라인이 거짓을 그린다**: 버려진 것을\n * 통과로 세면 트윈이 멈춘 구간에서도 선이 100% 에 붙는다.\n */\n /* 적힌 행도 함께 — 시뮬 트윈은 유입이 0 이라 이 값 없이는 추이가 빈 선으로 보인다. */\n trend: full.trend.map(w => ({ offered: w.offered, rejected: w.rejected, undelivered: w.undelivered, rows: w.rows })),\n lastAt: full.lastAt\n }\n })\n }\n\n /**\n * 한 트윈의 동기화 건강.\n *\n * ── 조회가 장부를 전진시킨다(의도) ─────────────────────────────────────────\n * 창은 **다음 유입이 있을 때** 닫힌다. 그래서 피드가 죽으면 마지막 창이 열린 채로 남아 영원히 영속되지\n * 않고, 추이에도 들어가지 않는다. 조회 시점에 한 번 굴려 주면 그 마지막 창이 닫히면서 영속 훅도 불린다\n * — 즉 **죽은 피드의 마지막 구간을 잃지 않기 위해** 읽기가 굴린다. 부수효과지만 필요한 부수효과다.\n *\n * 시각은 **한 번만 읽어** 굴리기와 판정에 같은 값을 쓴다. 두 번 읽으면 그 사이에 창이 닫혀 판정이\n * 굴리기 전 상태를 보는 일이 생긴다.\n */\n static ingestHealthOf(domainId: string, instanceId: string): IngestHealthView {\n const key = runtimeKey(domainId, instanceId)\n const nowMs = Date.now()\n const ledger = this.ingestLedgers[key]\n if (ledger) {\n rollIngestWindow(ledger, nowMs, undefined, closed => this.onWindowClosed?.({ domainId, instanceId }, closed))\n }\n\n const inst = this.instances[key]\n const feedState = liveFeedStateOf({\n restartPolicy: inst?.restartPolicy,\n running: !!inst,\n instanceId\n })\n return ingestHealth(ledger, feedState, undefined, nowMs)\n }\n\n /**\n * 도는 인스턴스 전체의 계측(모니터 대시보드용) — **시뮬과 미러를 함께**.\n *\n * 예전에는 시뮬에 계기가 없어 이 목록에서 조용히 빠졌다(계기가 `null` 이라 걸러졌다). 도는 트윈\n * 대부분이 시뮬인 서버에서 그 목록은 「부하가 거의 없다」로 보였다.\n */\n static async allMetrics(domainId?: string): Promise<any[]> {\n /* 도메인 없이 부르면 전 테넌트를 훑는다(내부 모니터용) — 키에서 도메인을 되돌려 각자에게 묻는다. */\n const rows = Object.keys(this.instances)\n .filter(key => !domainId || isOfDomain(key, domainId))\n .map(key => {\n const at = parseRuntimeKey(key)\n return this.metrics(at.domainId, at.instanceId)\n })\n .filter(Boolean)\n if (!rows.length || !domainId) return rows\n // 표시 이름 부여 — 실행중 카드가 id 만 보이지 않도록 공간명을 실어준다(공간 카드와 동일). name=공간명 폴백 spaceId 폴백 instanceId.\n const insts = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n const spaceOf = new Map(insts.map(i => [i.instanceId, i.spaceId]))\n /* 용도 선언도 함께 실어 보낸다 — 화면이 공간 이름으로 벤치를 **추측하지 않게** 한다.\n 추측하면 `loadtest-` 로 이름 지은 운영 트윈에 벤치 딱지가 붙는다. */\n const purposeOf = new Map(insts.map(i => [i.instanceId, i.purpose]))\n const nameOf = new Map((await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })).map(s => [s.spaceId, s.name]))\n for (const r of rows) {\n const sp = spaceOf.get(r.instanceId)\n r.spaceId = sp\n r.purpose = purposeOf.get(r.instanceId)\n r.name = (sp && nameOf.get(sp)) || sp || r.instanceId\n }\n return rows\n }\n\n /*\n * `buildForecastKernel` 은 **사라졌다**(통합 P3, 2026-08-01).\n *\n * 라이브가 `StateProjector` 였을 때는 커널이 없어서, 예측하려면 관측 스냅샷 + 저널의 오더 원값으로\n * **일회용 커널을 세워야** 했다. 이제 라이브 인스턴스가 곧 커널이므로(`startLive`) 그 자리에서\n * `fork` 하면 된다 — `TwinEngine.kernel(id)` 가 sim·live 둘 다 돌려준다.\n *\n * (오더 원값을 저널에서 되찾던 이유도 사라졌다 — 상태가 requested·fulfilled·lines 를 지킨다.)\n */\n\n /**\n * 예측용 커널을 **임의 시각 T 기준**으로 재구성 — 과거-vantage 예측(백테스트)·\"그때 서서 본 미래\".\n * recover(untilTime)로 T 시점 상태를, T 이하 오더 관측을 모아 hydrate → monteCarloForecast 가 T 에서 앞으로 실행한다.\n * sim/live 무관(저널 기반 재구성). untilTime 생략 시 최신. 도메인 스코프(reg·journal 조회가 domainId).\n */\n static async buildForecastKernelAt(domainId: string, instanceId: string, untilTime?: string): Promise<any | null> {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!reg?.model) return null\n const Kernel = kernelFor(reg.kind)\n const k = new Kernel(domainId, undefined, this.productionSpecOf(reg.model as TwinModelDef))\n k.loadTwinModel(reg.model as TwinModelDef)\n this.applyOperations(k, reg.model, instanceId) // 예측도 같은 명세로 굴러야 한다(화면과 다른 숫자 금지)\n await this.installEstimators(k, domainId, instanceId, reg.model) // 예측은 기다린다 — 실측을 놓치면 예측이 상수로 계산된다\n const state = await this.recover(domainId, instanceId, undefined, untilTime).catch(() => null)\n if (!state) return null\n const cutoff = untilTime != null ? Date.parse(untilTime) : Infinity\n /*\n * journal-fold: 오더의 마지막 상태는 그 오더에 일어난 사실들을 접어야 나온다.\n *\n * **없어질 조건** — 지금 이 읽기에는 상한이 없고 `eventType` 에 인덱스도 없다. 그래서 저널이 큰\n * 트윈에서는 이 한 번이 그 트윈의 저널 전체 주사다. 오더 상태를 따로 접어 둔 표(투영)를 두거나,\n * `(domain, instanceId, eventType, revision)` 인덱스를 붙이고 커서를 넣으면 이 예외는 사라진다.\n * 시각 상한(`cutoff`)을 SQL 로 내려도 절반은 준다.\n */\n const rows = await getRepository(TwinEvent).find({ where: { domain: { id: domainId }, instanceId, eventType: OP_EVENT.order }, order: { revision: 'ASC' } })\n const latest = new Map<string, any>()\n for (const r of rows) {\n if (Number.isFinite(cutoff) && (r.eventTime?.getTime() ?? NaN) > cutoff) continue\n const d = (r.payload as any)?.data\n if (d?.orderId) latest.set(d.orderId, d)\n }\n k.hydrateObserved(state, [...latest.values()])\n return k\n }\n\n /** 현재 전체 스냅샷 — 라이브 우선, 없으면 저널 복구 캐시. */\n static snapshot(domainId: string, id: string): any {\n const inst = this.instances[runtimeKey(domainId, id)]\n if (inst?.mode === 'live' && inst.projector) {\n /* live: **커널이 주목 신호를 스스로 낸다**(관측 모드) — 호스트가 덧붙이던 withLiveAttentions 는\n * 필요 없다. OEE 만 호스트가 채운다: 원 시스템이 시간 누적을 보내 주지 않아 상태 전이를 적분해\n * 만드는 값이라 커널이 대신할 수 없다(적합성 하네스의 유일한 예외). */\n const st = inst.projector.snapshot()\n return inst.oee ? withLiveOee(st, inst.oee) : st\n }\n return inst?.runtime?.resync() ?? this.recovered[runtimeKey(domainId, id)]\n }\n}\n"]}