@things-factory/headless-twin 10.1.142 → 10.1.144
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/engine/model-refusal.d.ts +3 -0
- package/dist-server/engine/model-refusal.js +37 -0
- package/dist-server/engine/model-refusal.js.map +1 -0
- package/dist-server/engine/twin-engine.js +8 -7
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/service/reference/reference-resolver.js +4 -1
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js +2 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
- package/dist-server/service/twin-journal/twin-journal-query.js +2 -1
- package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +2 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-item-query.js +2 -1
- package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-query.js +2 -1
- package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
- package/package.json +2 -2
- package/server/engine/model-refusal.ts +31 -0
- package/server/engine/twin-engine.ts +12 -7
- package/server/service/reference/reference-resolver.ts +5 -2
- package/server/service/twin-forecast/twin-forecast-query.ts +3 -2
- package/server/service/twin-journal/twin-journal-query.ts +3 -2
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +3 -2
- package/server/service/twin-model/twin-model-item-query.ts +3 -2
- package/server/service/twin-model/twin-model-query.ts +3 -2
- package/test/model-refusal.test.ts +75 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twin-lifecycle-mutation.js","sourceRoot":"","sources":["../../../server/service/twin-lifecycle/twin-lifecycle-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Mutation, Query, Resolver, Directive} from 'type-graphql'\n\nimport { ScalarObject, getRepository } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\n/* 정책 읽기는 그 모듈에서 직접 가져온다 — 다른 소비처(`reference-resolver`)와 같은 길이다. */\nimport { readRestartPolicy } from '../../engine/restart-policy.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinEvent } from '../twin-event/twin-event.js'\n\nimport type { TwinModelDef } from '@operato/ops-contract'\n\n/* 도메인 어휘 카탈로그(시스템별 노드 타입) — 커널이 SSOT. 앱/UI 는 이걸 소싱하고 재선언하지 않는다(방언 금지).\n * 조합은 domain-catalog.ts 가 소유 — 리졸버와 서버측 소비자(board-ai 도구 등)가 같은 형태를 본다. */\nimport { domainCatalog } from './domain-catalog.js'\n\n/*\n * 트윈 인스턴스 생명주기 채널 — 프로비저닝(상향, ADR-0015).\n * State/Command/Scenario 는 이미 running 인 인스턴스를 다루지만, 이 채널은 인스턴스 자체를 만들고/설정하고/없앤다.\n * 생명주기: provision(save, 미기동) → start → stop → delete. 모두 domain 스코프(context.state.domain.id).\n * model(TwinModelDef+layout)=구조, scenario=자극 은 분리 — 여기선 구조만 세운다. 자극은 **원본이 선언하고**\n * (`TwinReference.connectionConfig.scenario`) 기동이 싣거나, 원본의 구동 능력으로 태운다(ADR-0029 §4·§8).\n */\n@Resolver()\nexport class TwinLifecycleMutation {\n /*\n * `saveTwinInstance` 는 **없앴다**(2026-08-08, ADR-0028).\n *\n * 트윈의 구조를 임의의 model 로 덮어쓰는 문이었고, 유일한 소비자는 손저작 편집기였다.\n * 구조는 원본에서 온다 — 템플릿(`createFromTemplate`)이나 커넥터(`ingestMaster`)가 그 길이다.\n * 문을 열어 두면 화면만 지워도 다음 소비자가 다시 생긴다.\n *\n * 시뮬 트윈을 세우는 것은 여전히 가능하다. 다만 그 입구는 **원본을 만드는 쪽**이지\n * 트윈을 고치는 쪽이 아니다(ADR-0029 — 시뮬레이터는 원본의 한 종류).\n */\n\n /** 기동 — model 를 주면 provision+start, 없으면 레지스트리에 저장된 구조로 start. */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, {\n description: 'Start a twin runtime instance and begin the worker tick. If model is given it provisions first; otherwise it starts from the saved registry model.'\n })\n async startTwinInstance(\n @Arg('instanceId') instanceId: string,\n @Ctx() context: ResolverContext,\n @Arg('kind', { nullable: true }) kind?: string,\n @Arg('model', type => ScalarObject, { nullable: true }) model?: any,\n /** 새 시뮬레이션은 재기동 때 저널을 이어야 한다. 엔진에는 이미 필수지만 이 API가 누락해\n * zero-to-twin 경로가 기동 단계에서 막혔다. */\n @Arg('restartPolicy', { nullable: true }) restartPolicy?: 'resync' | 'resume' | 'reset'\n ): Promise<boolean> {\n const domainId = context.state.domain.id\n // 시각 기준은 **공간**이 갖는다(테넌트 아님) — 교대의 HH:MM 을 어느 기준으로 읽나.\n if (model) {\n /* model 를 함께 주는 것은 프로비저닝이다 — 그러면 종류도 말해야 한다.\n 예전에는 `kind ?? 'wms'` 로 메웠는데, 종류를 빠뜨린 야드/생산 트윈이 **창고로 알리지 않고 기동**했다. */\n if (!kind) throw new Error('kind is required when model is given — it decides which domain kernel runs this twin')\n TwinEngine.start(instanceId, domainId, kind, await TwinEngine.withSpaceTimeBase(model as TwinModelDef, domainId), restartPolicy)\n }\n else await TwinEngine.startFromRegistry(domainId, instanceId)\n return true\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Stop a running twin runtime instance by its id (only if it belongs to the current domain).' })\n async stopTwinInstance(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n if (!TwinEngine.owns(context.state.domain.id, instanceId)) return false // 테넌트 격리 — 남의 도메인 트윈 정지 차단\n await TwinEngine.stop(context.state.domain.id, instanceId)\n return true\n }\n\n /**\n * 이 트윈이 **자기 과거를 어떻게 대할 것인가**를 다시 선언한다 (2026-08-20).\n *\n * ── 왜 이 문이 필요한가 ────────────────────────────────────────────────────\n * `restartPolicy` 는 사람이 하는 선언인데, 만들 때 한 번 정하면 **고칠 길이 없었다.** 그래서 「씨앗\n * 재현용」으로 세운 트윈이 나중에 사람들이 이력을 보는 트윈이 되어도 선언은 `reset` 으로 남았다.\n * 선언과 쓰임이 어긋난 채로 두면, 선언대로 구현하는 순간(저널 초기화) 이력을 잃는다.\n *\n * ── 지금 도는 것에는 손대지 않는다 ─────────────────────────────────────────\n * 이 값은 **다음 기동**의 규칙이다. 돌고 있는 런타임의 구동 방식을 바꾸려면 정지·기동이 필요하고,\n * 그 판단은 사람의 것이다(도는 트윈을 알리지 않고 갈아 끼우면 그 사이의 사실이 어디로 갔는지 알 수 없다).\n * 그래서 결과에 「지금 도는 것과 다르다」는 사실을 함께 낸다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n \"Re-declare how a twin treats its own past on the next boot: 'resync' (re-read from the source), 'resume' (carry its own journal forward) or 'reset' (reproduce from the seed, journal cleared). The value is read strictly — an unknown or legacy word is refused with the accepted words named, because a silent default would decide whether a twin's history survives. This changes the declaration only: a running runtime keeps the mode it was started with, and the result says so (appliesAtNextStart) rather than swapping it underneath.\"\n })\n async setTwinRestartPolicy(\n @Arg('instanceId') instanceId: string,\n @Arg('restartPolicy') restartPolicy: string,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n /* 값은 **엄격히** 읽는다 — 모르는 말을 기본값으로 메우면 그 트윈의 이력이 남을지가 알리지 않고 결정된다. */\n const policy = readRestartPolicy(restartPolicy, `twin \"${instanceId}\"`)\n const repo = getRepository(TwinInstance)\n const row = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!row) throw new Error(`unknown twin \"${instanceId}\" in this domain — nothing was changed`)\n\n const before = row.restartPolicy\n if (before === policy) return { instanceId, restartPolicy: policy, changed: false, appliesAtNextStart: false }\n\n await repo.update({ id: row.id }, { restartPolicy: policy })\n /* 도는 런타임의 구동 방식은 그대로다 — 그 사실을 숨기지 않는다. */\n const running = !!TwinEngine.metrics(domainId, instanceId)\n return { instanceId, restartPolicy: policy, previous: before, changed: true, appliesAtNextStart: running }\n }\n\n /**\n * 트윈의 **이름을 다시 붙인다** (2026-08-26).\n *\n * ── 왜 이 문이 필요한가 ────────────────────────────────────────────────────\n * 이름은 트윈을 처음 세울 때 한 번 정해지고(`provision`), 다시 읽기는 그것을 건드리지 않는다. 그\n * 자체는 안전하다 — 사람이 붙인 이름을 연결이 덮어쓰면 안 된다. 그런데 그래서 **첫날의 이름에\n * 갇힌다.**\n *\n * 실제로 그런 일이 났다: 태양광 발전소를 붙일 때 커넥터가 아는 이름이 연결된 시스템의 코드\n * (`ES202307202202`)뿐이었다. 뒤에 사람이 부르는 이름(`호현에너지`)이 어디 있는지 알아내 커넥터를\n * 고쳤는데, 트윈 이름은 그대로였다. **연결된 시스템을 따라가는 트윈에서는 이름이 나중에 좋아진다** —\n * 커넥터가 나아질 때마다 이 일이 난다.\n *\n * 그때 남은 유일한 길이 트윈을 지우고 다시 세우는 것이었다. 그러면 지난 기록이 사라진다 — **이름\n * 하나 때문에 사실을 버리는 선택**이 된다. 그래서 이름만 바꾸는 문을 낸다.\n *\n * ── 연결이 따라오게 하지 않는다 ────────────────────────────────────────────\n * 다시 읽기가 이름을 따라가게 하면 사람이 붙인 이름을 덮어쓴다. 「사람이 손대지 않았으면 따라간다」가\n * 옳아 보이지만, 그러려면 「손댔다」는 표시를 새로 만들어야 하고 그것은 이름 하나 때문에 지기에 무거운\n * 빚이다. 사람이 바꾸는 길만 낸다.\n *\n * ── 빈 이름은 받지 않는다 ──────────────────────────────────────────────────\n * 이름을 지우는 것과 바꾸는 것은 다른 일이다. 빈 값을 받으면 그 트윈은 목록에서 식별자만 남는데,\n * 그것을 「이름을 바꿨다」로 보고하면 거짓이다. 지우고 싶으면 그 뜻의 문이 따로 있어야 한다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Rename a twin instance. The name is set when the twin is first provisioned and a re-read never touches it, ' +\n 'so a twin stays with the name its connector knew on day one — often a code from the connected system. ' +\n 'This changes the name only; nothing about the twin data, its journal or its runtime is affected. ' +\n 'An empty name is refused: clearing a name and changing it are different acts.'\n })\n async renameTwinInstance(\n @Arg('instanceId') instanceId: string,\n @Arg('name') name: string,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const next = String(name ?? '').trim()\n if (!next) throw new Error(`a twin name cannot be empty — \"${instanceId}\" was left as it was`)\n\n const repo = getRepository(TwinInstance)\n const row = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!row) throw new Error(`unknown twin \"${instanceId}\" in this domain — nothing was changed`)\n\n const before = row.name ?? ''\n if (before === next) return { instanceId, name: next, changed: false }\n\n await repo.update({ id: row.id }, { name: next, updater: context.state.user })\n /* 도는 런타임은 이름을 쓰지 않는다(식별자로 돈다) — 그래서 정지·기동이 필요하지 않다. */\n return { instanceId, name: next, previous: before || null, changed: true }\n }\n\n /**\n * 폐기 전에 사라질 것을 읽는다.\n *\n * 삭제는 레지스트리 행 하나만 없애는 일이 아니다. `TwinEngine.remove` 는 같은 트윈의 저널도\n * purge 한다. 그래서 확인 창이 추측한 숫자를 쓰지 않고, **삭제와 같은 domain·instance 범위**를\n * 직접 센다. 저널이 비어 있는 트윈도 `0` 과 null 기간을 돌려준다 — 없는 기록을 기간으로\n * 꾸며내면 \"아무것도 안 지워진다\"와 \"언제부터인지 모른다\"가 섞인다.\n */\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'Describe what deleting one twin would purge before it is deleted: its registry identity and the count plus first/last event time of its journal. Null means this twin is not in the current domain.'\n })\n async twinDeletionPreview(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const domainId = context.state.domain.id\n const instance = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n\n if (!instance) return null\n\n const journal = await getRepository(TwinEvent)\n .createQueryBuilder('event')\n .select('COUNT(event.id)', 'count')\n .addSelect('MIN(event.eventTime)', 'firstEventAt')\n .addSelect('MAX(event.eventTime)', 'lastEventAt')\n .where('event.domain = :domainId', { domainId })\n .andWhere('event.instanceId = :instanceId', { instanceId })\n .getRawOne<{ count?: string | number; firstEventAt?: unknown; lastEventAt?: unknown }>()\n\n return {\n instanceId,\n name: instance.name ?? null,\n journalCount: Number(journal?.count ?? 0),\n firstEventAt: journal?.firstEventAt ?? null,\n lastEventAt: journal?.lastEventAt ?? null\n }\n }\n\n /** 삭제 — 정지 + 레지스트리 삭제 + 저널 purge(domain 스코프). */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a twin instance: stop it, remove the registry entry and purge its event journal.' })\n async deleteTwinInstance(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n await TwinEngine.remove(context.state.domain.id, instanceId)\n return true\n }\n\n /** 관리 목록 — 등록된 인스턴스 전체(kind/status/running/revision/노드·무버 수). 데이터 없으면 빈 배열. */\n /**\n * **이 공간의 트윈 id 들** — 한 현실을 여러 렌즈가 비추므로 공간을 물으면 그 렌즈 전부를 답한다.\n *\n * 화면이 전체 목록을 받아 걸러 쓰던 규칙을 서버로 모은다. 예측 화면은 같은 확장을 한 파일에서\n * **두 번** 복제하고 있었고, 규칙이 흩어지면 한쪽만 고쳐진다. 떠 있지 않은 것도 포함한다 —\n * 공간에 무엇이 있는지는 기동 여부와 다른 사실이다.\n */\n @Query(returns => [String], { description: 'Ids of the twins that live in a space (all its lenses), running or not.' })\n async twinSpaceInstanceIds(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<string[]> {\n return TwinEngine.instanceIdsOfSpace(context.state.domain.id, spaceId)\n }\n\n @Query(returns => [ScalarObject], {\n description:\n 'List provisioned twin instances in the current domain with management metadata. Each row also carries `sync`: a one-line answer to \"is this twin keeping in step with the floor?\" — a verdict (syncing | mapping-blocked | no-traffic | not-connected | not-applicable | unknown), the accepted share of the last closed 10-minute window, and up to 36 closed windows of offered/rejected counts for a sparkline. Reasons and rejected-record samples are deliberately absent here; ask twinIngestHealth for one twin when you need them, because carrying raw records for every row would make this list heavy for no gain. acceptedRatio is null while the first window is still filling — a partially filled window under-counts, and drawing it as zero would read as \"nothing passed\".'\n })\n async twinInstanceList(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const list = await TwinEngine.list(domainId)\n /*\n * 동기화 요약을 **같은 응답에 얹는다.** 따로 질의하면 트윈 수만큼 왕복이 생기고(N+1), 그 사이 화면은\n * 판정 없는 목록을 먼저 그린다 — 사람이 그 순간을 「정상」으로 읽는다.\n */\n const brief = new Map(\n TwinEngine.ingestHealthBrief(\n domainId,\n list.map((x: any) => x.instanceId)\n ).map(b => [b.instanceId, b])\n )\n /*\n * **쓰기 사실도 같은 응답에 얹는다** (2026-08-20).\n *\n * 「이 트윈이 사실을 적고 있나」는 운영자가 트윈 화면에서 묻는 질문인데, 그 답은 벤치(슈퍼유저)의\n * 부하 계기판에만 있었다. 유입(`sync`)과 나란히 두는 이유는 둘이 한 사슬이기 때문이다 — 받은 것이\n * 있어도 적히지 않으면 저널이 비고, 그러면 성과·시간여행이 함께 빈다.\n *\n * 계기는 메모리라 왕복이 없다. **도는 트윈만** 답이 있고, 멈춘 트윈은 `null` 이다(0 이 아니다 —\n * 「쓰지 않았다」와 「돌지 않는다」는 다른 사실이다).\n */\n return list.map((x: any) => {\n const m = TwinEngine.metrics(domainId, x.instanceId)\n return {\n ...x,\n sync: brief.get(x.instanceId) ?? null,\n write: m ? { rate: m.journalRate, journaled: m.journaledTotal, backlog: m.backlog } : null\n }\n })\n }\n\n /** 단건 상세 — 프로비저닝 에디터용 model(구조+layout) 포함. */\n @Query(returns => ScalarObject, { nullable: true, description: 'Get one provisioned twin instance with its TwinModelDef (structure + layout) for editing.' })\n async twinInstanceDetail(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any | null> {\n return TwinEngine.detail(context.state.domain.id, instanceId)\n }\n\n /**\n * 라이브(메모리) 인스턴스 id 목록 — 콘솔 셀렉터·포트폴리오용. **현재 도메인만**(테넌트 격리).\n * 과거엔 Object.keys(TwinEngine.instances) 로 전역 반환 → 다른 도메인 트윈이 종합현황/셀렉터에 새던 버그.\n * 도메인 스코프 목록(twinInstanceList 와 동일 소스)에서 running 만 추린다.\n */\n @Query(returns => [String], { description: 'List ids of running (in-memory) twin runtime instances in the current domain (tenant-isolated).' })\n async twinInstances(@Ctx() context: ResolverContext): Promise<string[]> {\n const list = await TwinEngine.list(context.state.domain.id)\n return list.filter((x: any) => x.running).map((x: any) => x.instanceId)\n }\n\n /**\n * 도메인 어휘 카탈로그 — 커널(레퍼런스) SSOT 를 그대로 노출. { wms:{label,locationTypes[]}, yms:…, mes:… }.\n * 프로비저닝 UI 는 이걸 소싱해 노드 타입/시스템을 채운다(앱 내 하드코딩 금지).\n */\n @Query(returns => ScalarObject, { description: 'Domain vocabulary catalog (per-system location location types) sourced from the twin kernel — SSOT for provisioning UI.' })\n twinDomainCatalog(): any {\n return domainCatalog()\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"twin-lifecycle-mutation.js","sourceRoot":"","sources":["../../../server/service/twin-lifecycle/twin-lifecycle-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Mutation, Query, Resolver, Directive, UseMiddleware } from 'type-graphql'\n\nimport { ScalarObject, SpeakRefusals, getRepository } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\n/* 정책 읽기는 그 모듈에서 직접 가져온다 — 다른 소비처(`reference-resolver`)와 같은 길이다. */\nimport { readRestartPolicy } from '../../engine/restart-policy.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinEvent } from '../twin-event/twin-event.js'\n\nimport type { TwinModelDef } from '@operato/ops-contract'\n\n/* 도메인 어휘 카탈로그(시스템별 노드 타입) — 커널이 SSOT. 앱/UI 는 이걸 소싱하고 재선언하지 않는다(방언 금지).\n * 조합은 domain-catalog.ts 가 소유 — 리졸버와 서버측 소비자(board-ai 도구 등)가 같은 형태를 본다. */\nimport { domainCatalog } from './domain-catalog.js'\n\n/*\n * 트윈 인스턴스 생명주기 채널 — 프로비저닝(상향, ADR-0015).\n * State/Command/Scenario 는 이미 running 인 인스턴스를 다루지만, 이 채널은 인스턴스 자체를 만들고/설정하고/없앤다.\n * 생명주기: provision(save, 미기동) → start → stop → delete. 모두 domain 스코프(context.state.domain.id).\n * model(TwinModelDef+layout)=구조, scenario=자극 은 분리 — 여기선 구조만 세운다. 자극은 **원본이 선언하고**\n * (`TwinReference.connectionConfig.scenario`) 기동이 싣거나, 원본의 구동 능력으로 태운다(ADR-0029 §4·§8).\n */\n@Resolver()\n@UseMiddleware(SpeakRefusals)\nexport class TwinLifecycleMutation {\n /*\n * `saveTwinInstance` 는 **없앴다**(2026-08-08, ADR-0028).\n *\n * 트윈의 구조를 임의의 model 로 덮어쓰는 문이었고, 유일한 소비자는 손저작 편집기였다.\n * 구조는 원본에서 온다 — 템플릿(`createFromTemplate`)이나 커넥터(`ingestMaster`)가 그 길이다.\n * 문을 열어 두면 화면만 지워도 다음 소비자가 다시 생긴다.\n *\n * 시뮬 트윈을 세우는 것은 여전히 가능하다. 다만 그 입구는 **원본을 만드는 쪽**이지\n * 트윈을 고치는 쪽이 아니다(ADR-0029 — 시뮬레이터는 원본의 한 종류).\n */\n\n /** 기동 — model 를 주면 provision+start, 없으면 레지스트리에 저장된 구조로 start. */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, {\n description: 'Start a twin runtime instance and begin the worker tick. If model is given it provisions first; otherwise it starts from the saved registry model.'\n })\n async startTwinInstance(\n @Arg('instanceId') instanceId: string,\n @Ctx() context: ResolverContext,\n @Arg('kind', { nullable: true }) kind?: string,\n @Arg('model', type => ScalarObject, { nullable: true }) model?: any,\n /** 새 시뮬레이션은 재기동 때 저널을 이어야 한다. 엔진에는 이미 필수지만 이 API가 누락해\n * zero-to-twin 경로가 기동 단계에서 막혔다. */\n @Arg('restartPolicy', { nullable: true }) restartPolicy?: 'resync' | 'resume' | 'reset'\n ): Promise<boolean> {\n const domainId = context.state.domain.id\n // 시각 기준은 **공간**이 갖는다(테넌트 아님) — 교대의 HH:MM 을 어느 기준으로 읽나.\n if (model) {\n /* model 를 함께 주는 것은 프로비저닝이다 — 그러면 종류도 말해야 한다.\n 예전에는 `kind ?? 'wms'` 로 메웠는데, 종류를 빠뜨린 야드/생산 트윈이 **창고로 알리지 않고 기동**했다. */\n if (!kind) throw new Error('kind is required when model is given — it decides which domain kernel runs this twin')\n TwinEngine.start(instanceId, domainId, kind, await TwinEngine.withSpaceTimeBase(model as TwinModelDef, domainId), restartPolicy)\n }\n else await TwinEngine.startFromRegistry(domainId, instanceId)\n return true\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Stop a running twin runtime instance by its id (only if it belongs to the current domain).' })\n async stopTwinInstance(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n if (!TwinEngine.owns(context.state.domain.id, instanceId)) return false // 테넌트 격리 — 남의 도메인 트윈 정지 차단\n await TwinEngine.stop(context.state.domain.id, instanceId)\n return true\n }\n\n /**\n * 이 트윈이 **자기 과거를 어떻게 대할 것인가**를 다시 선언한다 (2026-08-20).\n *\n * ── 왜 이 문이 필요한가 ────────────────────────────────────────────────────\n * `restartPolicy` 는 사람이 하는 선언인데, 만들 때 한 번 정하면 **고칠 길이 없었다.** 그래서 「씨앗\n * 재현용」으로 세운 트윈이 나중에 사람들이 이력을 보는 트윈이 되어도 선언은 `reset` 으로 남았다.\n * 선언과 쓰임이 어긋난 채로 두면, 선언대로 구현하는 순간(저널 초기화) 이력을 잃는다.\n *\n * ── 지금 도는 것에는 손대지 않는다 ─────────────────────────────────────────\n * 이 값은 **다음 기동**의 규칙이다. 돌고 있는 런타임의 구동 방식을 바꾸려면 정지·기동이 필요하고,\n * 그 판단은 사람의 것이다(도는 트윈을 알리지 않고 갈아 끼우면 그 사이의 사실이 어디로 갔는지 알 수 없다).\n * 그래서 결과에 「지금 도는 것과 다르다」는 사실을 함께 낸다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n \"Re-declare how a twin treats its own past on the next boot: 'resync' (re-read from the source), 'resume' (carry its own journal forward) or 'reset' (reproduce from the seed, journal cleared). The value is read strictly — an unknown or legacy word is refused with the accepted words named, because a silent default would decide whether a twin's history survives. This changes the declaration only: a running runtime keeps the mode it was started with, and the result says so (appliesAtNextStart) rather than swapping it underneath.\"\n })\n async setTwinRestartPolicy(\n @Arg('instanceId') instanceId: string,\n @Arg('restartPolicy') restartPolicy: string,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n /* 값은 **엄격히** 읽는다 — 모르는 말을 기본값으로 메우면 그 트윈의 이력이 남을지가 알리지 않고 결정된다. */\n const policy = readRestartPolicy(restartPolicy, `twin \"${instanceId}\"`)\n const repo = getRepository(TwinInstance)\n const row = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!row) throw new Error(`unknown twin \"${instanceId}\" in this domain — nothing was changed`)\n\n const before = row.restartPolicy\n if (before === policy) return { instanceId, restartPolicy: policy, changed: false, appliesAtNextStart: false }\n\n await repo.update({ id: row.id }, { restartPolicy: policy })\n /* 도는 런타임의 구동 방식은 그대로다 — 그 사실을 숨기지 않는다. */\n const running = !!TwinEngine.metrics(domainId, instanceId)\n return { instanceId, restartPolicy: policy, previous: before, changed: true, appliesAtNextStart: running }\n }\n\n /**\n * 트윈의 **이름을 다시 붙인다** (2026-08-26).\n *\n * ── 왜 이 문이 필요한가 ────────────────────────────────────────────────────\n * 이름은 트윈을 처음 세울 때 한 번 정해지고(`provision`), 다시 읽기는 그것을 건드리지 않는다. 그\n * 자체는 안전하다 — 사람이 붙인 이름을 연결이 덮어쓰면 안 된다. 그런데 그래서 **첫날의 이름에\n * 갇힌다.**\n *\n * 실제로 그런 일이 났다: 태양광 발전소를 붙일 때 커넥터가 아는 이름이 연결된 시스템의 코드\n * (`ES202307202202`)뿐이었다. 뒤에 사람이 부르는 이름(`호현에너지`)이 어디 있는지 알아내 커넥터를\n * 고쳤는데, 트윈 이름은 그대로였다. **연결된 시스템을 따라가는 트윈에서는 이름이 나중에 좋아진다** —\n * 커넥터가 나아질 때마다 이 일이 난다.\n *\n * 그때 남은 유일한 길이 트윈을 지우고 다시 세우는 것이었다. 그러면 지난 기록이 사라진다 — **이름\n * 하나 때문에 사실을 버리는 선택**이 된다. 그래서 이름만 바꾸는 문을 낸다.\n *\n * ── 연결이 따라오게 하지 않는다 ────────────────────────────────────────────\n * 다시 읽기가 이름을 따라가게 하면 사람이 붙인 이름을 덮어쓴다. 「사람이 손대지 않았으면 따라간다」가\n * 옳아 보이지만, 그러려면 「손댔다」는 표시를 새로 만들어야 하고 그것은 이름 하나 때문에 지기에 무거운\n * 빚이다. 사람이 바꾸는 길만 낸다.\n *\n * ── 빈 이름은 받지 않는다 ──────────────────────────────────────────────────\n * 이름을 지우는 것과 바꾸는 것은 다른 일이다. 빈 값을 받으면 그 트윈은 목록에서 식별자만 남는데,\n * 그것을 「이름을 바꿨다」로 보고하면 거짓이다. 지우고 싶으면 그 뜻의 문이 따로 있어야 한다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Rename a twin instance. The name is set when the twin is first provisioned and a re-read never touches it, ' +\n 'so a twin stays with the name its connector knew on day one — often a code from the connected system. ' +\n 'This changes the name only; nothing about the twin data, its journal or its runtime is affected. ' +\n 'An empty name is refused: clearing a name and changing it are different acts.'\n })\n async renameTwinInstance(\n @Arg('instanceId') instanceId: string,\n @Arg('name') name: string,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const next = String(name ?? '').trim()\n if (!next) throw new Error(`a twin name cannot be empty — \"${instanceId}\" was left as it was`)\n\n const repo = getRepository(TwinInstance)\n const row = await repo.findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!row) throw new Error(`unknown twin \"${instanceId}\" in this domain — nothing was changed`)\n\n const before = row.name ?? ''\n if (before === next) return { instanceId, name: next, changed: false }\n\n await repo.update({ id: row.id }, { name: next, updater: context.state.user })\n /* 도는 런타임은 이름을 쓰지 않는다(식별자로 돈다) — 그래서 정지·기동이 필요하지 않다. */\n return { instanceId, name: next, previous: before || null, changed: true }\n }\n\n /**\n * 폐기 전에 사라질 것을 읽는다.\n *\n * 삭제는 레지스트리 행 하나만 없애는 일이 아니다. `TwinEngine.remove` 는 같은 트윈의 저널도\n * purge 한다. 그래서 확인 창이 추측한 숫자를 쓰지 않고, **삭제와 같은 domain·instance 범위**를\n * 직접 센다. 저널이 비어 있는 트윈도 `0` 과 null 기간을 돌려준다 — 없는 기록을 기간으로\n * 꾸며내면 \"아무것도 안 지워진다\"와 \"언제부터인지 모른다\"가 섞인다.\n */\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'Describe what deleting one twin would purge before it is deleted: its registry identity and the count plus first/last event time of its journal. Null means this twin is not in the current domain.'\n })\n async twinDeletionPreview(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const domainId = context.state.domain.id\n const instance = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n\n if (!instance) return null\n\n const journal = await getRepository(TwinEvent)\n .createQueryBuilder('event')\n .select('COUNT(event.id)', 'count')\n .addSelect('MIN(event.eventTime)', 'firstEventAt')\n .addSelect('MAX(event.eventTime)', 'lastEventAt')\n .where('event.domain = :domainId', { domainId })\n .andWhere('event.instanceId = :instanceId', { instanceId })\n .getRawOne<{ count?: string | number; firstEventAt?: unknown; lastEventAt?: unknown }>()\n\n return {\n instanceId,\n name: instance.name ?? null,\n journalCount: Number(journal?.count ?? 0),\n firstEventAt: journal?.firstEventAt ?? null,\n lastEventAt: journal?.lastEventAt ?? null\n }\n }\n\n /** 삭제 — 정지 + 레지스트리 삭제 + 저널 purge(domain 스코프). */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a twin instance: stop it, remove the registry entry and purge its event journal.' })\n async deleteTwinInstance(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n await TwinEngine.remove(context.state.domain.id, instanceId)\n return true\n }\n\n /** 관리 목록 — 등록된 인스턴스 전체(kind/status/running/revision/노드·무버 수). 데이터 없으면 빈 배열. */\n /**\n * **이 공간의 트윈 id 들** — 한 현실을 여러 렌즈가 비추므로 공간을 물으면 그 렌즈 전부를 답한다.\n *\n * 화면이 전체 목록을 받아 걸러 쓰던 규칙을 서버로 모은다. 예측 화면은 같은 확장을 한 파일에서\n * **두 번** 복제하고 있었고, 규칙이 흩어지면 한쪽만 고쳐진다. 떠 있지 않은 것도 포함한다 —\n * 공간에 무엇이 있는지는 기동 여부와 다른 사실이다.\n */\n @Query(returns => [String], { description: 'Ids of the twins that live in a space (all its lenses), running or not.' })\n async twinSpaceInstanceIds(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<string[]> {\n return TwinEngine.instanceIdsOfSpace(context.state.domain.id, spaceId)\n }\n\n @Query(returns => [ScalarObject], {\n description:\n 'List provisioned twin instances in the current domain with management metadata. Each row also carries `sync`: a one-line answer to \"is this twin keeping in step with the floor?\" — a verdict (syncing | mapping-blocked | no-traffic | not-connected | not-applicable | unknown), the accepted share of the last closed 10-minute window, and up to 36 closed windows of offered/rejected counts for a sparkline. Reasons and rejected-record samples are deliberately absent here; ask twinIngestHealth for one twin when you need them, because carrying raw records for every row would make this list heavy for no gain. acceptedRatio is null while the first window is still filling — a partially filled window under-counts, and drawing it as zero would read as \"nothing passed\".'\n })\n async twinInstanceList(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const list = await TwinEngine.list(domainId)\n /*\n * 동기화 요약을 **같은 응답에 얹는다.** 따로 질의하면 트윈 수만큼 왕복이 생기고(N+1), 그 사이 화면은\n * 판정 없는 목록을 먼저 그린다 — 사람이 그 순간을 「정상」으로 읽는다.\n */\n const brief = new Map(\n TwinEngine.ingestHealthBrief(\n domainId,\n list.map((x: any) => x.instanceId)\n ).map(b => [b.instanceId, b])\n )\n /*\n * **쓰기 사실도 같은 응답에 얹는다** (2026-08-20).\n *\n * 「이 트윈이 사실을 적고 있나」는 운영자가 트윈 화면에서 묻는 질문인데, 그 답은 벤치(슈퍼유저)의\n * 부하 계기판에만 있었다. 유입(`sync`)과 나란히 두는 이유는 둘이 한 사슬이기 때문이다 — 받은 것이\n * 있어도 적히지 않으면 저널이 비고, 그러면 성과·시간여행이 함께 빈다.\n *\n * 계기는 메모리라 왕복이 없다. **도는 트윈만** 답이 있고, 멈춘 트윈은 `null` 이다(0 이 아니다 —\n * 「쓰지 않았다」와 「돌지 않는다」는 다른 사실이다).\n */\n return list.map((x: any) => {\n const m = TwinEngine.metrics(domainId, x.instanceId)\n return {\n ...x,\n sync: brief.get(x.instanceId) ?? null,\n write: m ? { rate: m.journalRate, journaled: m.journaledTotal, backlog: m.backlog } : null\n }\n })\n }\n\n /** 단건 상세 — 프로비저닝 에디터용 model(구조+layout) 포함. */\n @Query(returns => ScalarObject, { nullable: true, description: 'Get one provisioned twin instance with its TwinModelDef (structure + layout) for editing.' })\n async twinInstanceDetail(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any | null> {\n return TwinEngine.detail(context.state.domain.id, instanceId)\n }\n\n /**\n * 라이브(메모리) 인스턴스 id 목록 — 콘솔 셀렉터·포트폴리오용. **현재 도메인만**(테넌트 격리).\n * 과거엔 Object.keys(TwinEngine.instances) 로 전역 반환 → 다른 도메인 트윈이 종합현황/셀렉터에 새던 버그.\n * 도메인 스코프 목록(twinInstanceList 와 동일 소스)에서 running 만 추린다.\n */\n @Query(returns => [String], { description: 'List ids of running (in-memory) twin runtime instances in the current domain (tenant-isolated).' })\n async twinInstances(@Ctx() context: ResolverContext): Promise<string[]> {\n const list = await TwinEngine.list(context.state.domain.id)\n return list.filter((x: any) => x.running).map((x: any) => x.instanceId)\n }\n\n /**\n * 도메인 어휘 카탈로그 — 커널(레퍼런스) SSOT 를 그대로 노출. { wms:{label,locationTypes[]}, yms:…, mes:… }.\n * 프로비저닝 UI 는 이걸 소싱해 노드 타입/시스템을 채운다(앱 내 하드코딩 금지).\n */\n @Query(returns => ScalarObject, { description: 'Domain vocabulary catalog (per-system location location types) sourced from the twin kernel — SSOT for provisioning UI.' })\n twinDomainCatalog(): any {\n return domainCatalog()\n }\n}\n"]}
|
|
@@ -1005,6 +1005,7 @@ tslib_1.__decorate([
|
|
|
1005
1005
|
tslib_1.__metadata("design:returntype", Promise)
|
|
1006
1006
|
], TwinModelItemQuery.prototype, "twinModelItem", null);
|
|
1007
1007
|
exports.TwinModelItemQuery = TwinModelItemQuery = tslib_1.__decorate([
|
|
1008
|
-
(0, type_graphql_1.Resolver)()
|
|
1008
|
+
(0, type_graphql_1.Resolver)(),
|
|
1009
|
+
(0, type_graphql_1.UseMiddleware)(shell_1.SpeakRefusals)
|
|
1009
1010
|
], TwinModelItemQuery);
|
|
1010
1011
|
//# sourceMappingURL=twin-model-item-query.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twin-model-item-query.js","sourceRoot":"","sources":["../../../server/service/twin-model/twin-model-item-query.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReadBasis } from '@operato/ops-contract'\n\nimport { twinWarn } from '../../engine/log.js'\nimport { Arg, Ctx, Int, Query, Resolver } from 'type-graphql'\n\nimport { ScalarObject, getRepository } from '@things-factory/shell'\n\nimport { itemRefOf } from './item-ref.js'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { unwrapState } from '../../engine/warm-start.js'\nimport { propertyEffectsOf } from '../../engine/property-effects.js'\n/* 축이 사는 자리를 읽는 **한 곳** — 카드(`twin-model-query`)와 같은 규칙을 쓴다. */\nimport { axisValueOf } from '@things-factory/headless-twin/dist-shared/axis-read.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinLocation } from './twin-location.js'\nimport { TwinEquipment } from './twin-equipment.js'\nimport { TwinOperation } from './twin-operation.js'\nimport { TwinArea } from '../twin-space/twin-area.js'\nimport { at, idOf, nameIndex, namesFor } from './name-index.js'\n\n/* 커널 런타임 로드 — 축·관계·속성 선언의 SSOT. 이 파일은 도메인 모양을 알지 않는다. */\nconst { TWIN_AXES, TWIN_RELATIONS, axisInfo, axisSource, documentPath, isCacheableTense, relationsFrom, relationsTo, propertiesOf, splitRelationIds, tenseOf } =\n require('@operato/ops-contract')\n\n/**\n * 목록의 답 — **근거는 계약이 닫아 둔 다섯 중 하나다**(`READ_BASIS`).\n *\n * 2026-09-18 판정(ADR-0075 결정 3 을 코드에 대어 본 결과): 이 문이 `'rows-scanned'` 를 내고 있었다.\n * 그것은 출처가 아니라 **우리가 어떻게 셌나**이고, 목록 소비자가 근거로 갈래를 나눌 때 계약에 없는\n * 값을 만나게 된다. 출처는 `rows` 이고, 훑어 걸렀다는 사실은 `scanned` · `truncated` 가 말한다.\n * 여기에 칸을 묶어 두면 계약 밖의 값이 다시 생길 때 타입 검사가 잡는다.\n */\ntype AxisListAnswer = {\n axis: string\n label: string\n basis: ReadBasis\n total: number | null\n offset: number\n /** 훑어 센 경우에만 — 몇 줄을 읽었나, 상한에서 잘렸나. */\n scanned?: number\n truncated?: boolean\n [key: string]: unknown\n}\nimport { externalIncoming, resolveExternal } from './external-resolver.js'\n\n/**\n * 축 → 그 축이 이미 **행으로 옮겨졌나**, 그리고 행의 어느 컬럼이 id 인가.\n *\n * 옮겨진 축은 **DB 가 페이징하고 센다.** 아직인 축은 문서 배열을 읽어야 하고, 그 차이를 응답이\n * `basis` 로 밝힌다 — 밝히지 않으면 \"이 축은 검색이 되는데 저 축은 왜 느린가\" 를 아무도 설명할 수 없다.\n */\nconst ROW_BACKED: Record<string, { entity: any; idColumn: string; order: any }> = {\n locations: { entity: TwinLocation, idColumn: 'locationId', order: { locationId: 'ASC' } },\n equipment: { entity: TwinEquipment, idColumn: 'equipmentId', order: { equipmentId: 'ASC' } },\n operations: { entity: TwinOperation, idColumn: 'operationKey', order: { seq: 'ASC' } }\n}\n\n/*\n * `productionSpec.binding` 의 키가 사는 축 — 자재가 둘로 갈려 있다.\n *\n * materials productionSpec.definition.materials 레시피의 투입 자재\n * materialDefinitions materialDefinitions 마스터 품목 목록\n *\n * 예전에는 `materials` 하나만 봤다. 커넥터에 따라 `binding` 키가 어느 축의 id 인지 달라서, MES 연결\n * 둘은 품목이 자기 GS1 참조를 한 건도 답하지 못했다. 오류는 안 나고 칸이 비어서 나온다.\n *\n * 실측(2026-09-06, 인티그레이션 레인이 찾음):\n *\n * 트윈 binding def.materials 맞음 materialDefinitions 맞음\n * mes-miratek 106 0 106\n * mes-line-a 21 0 21\n * operato-chef-v1-pocheon 2789 1789 0\n * rosarito-mes 20 20 0\n *\n * **두 축이 동시에 맞는 트윈은 없다**(양쪽 id 에 다 있으면서 binding 키인 것 0개). 그래서 두 축에\n * 다 걸어도 어느 쪽을 붙일지 모호해지지 않는다. 조회가 판정한다 — `binding[id]` 는 키가 아닌 축에서\n * 그냥 없다.\n *\n * 두 축을 한 이름으로 합치지 않는다. 레시피 투입 자재와 마스터 품목은 서로 다른 것이고, 합치면\n * 둘 다 있는 트윈(chef)에서 어느 쪽 목록인지 알 수 없게 된다.\n */\nconst BINDING_AXES = new Set(['materials', 'materialDefinitions'])\n\n\n/** 검색 — 항목의 값 어디든 걸리면 맞는 것으로 본다. 축마다 검색 컬럼을 정해 두면 축이 늘 때마다 여기를 고쳐야 한다. */\nfunction matches(o: any, q: string): boolean {\n if (!q) return true\n const needle = q.toLowerCase()\n const walk = (v: any, depth: number): boolean => {\n if (v == null || depth > 3) return false\n if (typeof v === 'string' || typeof v === 'number') return String(v).toLowerCase().includes(needle)\n if (Array.isArray(v)) return v.some(x => walk(x, depth + 1))\n if (typeof v === 'object') return Object.values(v).some(x => walk(x, depth + 1))\n return false\n }\n return walk(o, 0)\n}\n\n/**\n * 항목 조회 — **개념 안의 목록**(③)과 **항목 하나의 상세**(④).\n *\n * ── 이 파일이 도메인을 알지 않는다 ─────────────────────────────────────────────\n * 어느 축이 있고 무엇을 가리키는지는 **커널 카탈로그가 선언**한다(`TWIN_AXES`·`TWIN_RELATIONS`).\n * 그래서 야드의 도크도어나 에너지의 계량기가 늘어도 여기 손댈 것이 없다(ADR-0031). 이 파일에\n * 도메인 이름이 한 번도 나오지 않는 것이 그 증거다.\n *\n * ── 알리지 않고 자르지 않는다 ──────────────────────────────────────────────────────\n * 목록은 항상 **총 건수**와 함께 온다. 그리고 어떻게 셌는지(`basis`)를 밝힌다 — 행이면 DB 가\n * 페이징했고, 문서면 서버가 문서를 통째로 읽어 잘라 냈다. 후자는 규모에서 한계가 되므로 그 사실이\n * 화면에 드러나야 이주 압력이 살아 있다.\n */\n@Resolver()\nexport class TwinModelItemQuery {\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'Page through the items of one standard concept in a twin. Always returns the total and how it was counted (rows = the database paged it, document = the server read the whole document and sliced).'\n })\n async twinModelEntities(\n @Arg('instanceId') instanceId: string,\n @Arg('axis') axis: string,\n @Ctx() context: ResolverContext,\n @Arg('search', { nullable: true }) search?: string,\n @Arg('offset', type => Int, { nullable: true }) offset?: number,\n @Arg('limit', type => Int, { nullable: true }) limit?: number,\n /**\n * 어느 시각의 사실인가 — **관측 축에만 뜻이 있다.**\n *\n * 선언 축은 시간축이 없다(그 시점의 선언은 구조 리비전이 답한다). 그래서 문서 축에 이 값을 주면\n * 쓰지 않는다 — 무시했다는 사실은 응답의 `basis` 가 말한다(`document`).\n */\n @Arg('untilTime', { nullable: true }) untilTime?: string\n ): Promise<any | null> {\n const domainId = context.state.domain.id\n const info = axisInfo(axis)\n /* 모르는 축은 **거절한다.** 빈 목록으로 답하면 \"이 개념은 비어 있다\" 로 읽히고, 오타 하나가\n \"우리 트윈에는 그게 없다\" 는 결론으로 굳는다. */\n if (!info) throw new Error(`unknown concept axis: \"${axis}\" — the kernel catalog does not declare it`)\n\n const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!inst) return null\n\n const take = Math.min(Math.max(limit ?? 50, 1), 200)\n const skip = Math.max(offset ?? 0, 0)\n const q = (search ?? '').trim()\n /* 시각 커서는 시간축을 가진 축만 쓴다(`historical`) — 선언 축에서는 뜻이 없다. */\n const at_ = axisInfo(axis)?.historical ? untilTime || null : null\n const row = ROW_BACKED[axis]\n\n if (row && !q) {\n /* 검색어가 없으면 **DB 가 페이징한다** — 이것이 규모에서 유일하게 성립하는 길이다. */\n const repo = getRepository(row.entity)\n const where = { domain: { id: domainId } as any, instance: { id: inst.id } as any }\n const [rows, total] = await repo.findAndCount({ where, order: row.order, skip, take })\n const answer: AxisListAnswer = {\n axis,\n label: info.label,\n basis: 'rows',\n total,\n offset: skip,\n /* 목록도 등급 이름을 쓴다 — 목록 칸에 `assembler-op` 이 그대로 서면 목록이 제 일을 못 한다. */\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n items: rows.map((r: any) => this.rowItem(axis, r))\n }\n return answer\n }\n\n if (row && q) {\n /*\n * 검색은 아직 DB 로 내리지 않았다. **그 사실을 밝힌다** — 흉내로 덮으면 규모가 오는 날까지\n * 아무도 이 한계를 모른다. 훑는 건수를 상한으로 막고, 상한에 닿았으면 잘렸다고 말한다\n * (알리지 않고 자르지 않는다).\n *\n * 말하는 자리는 `scanned` · `truncated` 다. 근거(`basis`)는 그대로 `rows` 이고 — 값이 어디서\n * 왔는지는 훑었든 DB 가 골랐든 같은 행이다 — 계약이 닫아 둔 다섯 밖으로 나가지 않는다.\n */\n const SCAN_MAX = 5000\n const repo = getRepository(row.entity)\n const where = { domain: { id: domainId } as any, instance: { id: inst.id } as any }\n const rows = await repo.find({ where, order: row.order, take: SCAN_MAX })\n const hit = rows.filter((r: any) => matches(this.rowItem(axis, r), q))\n const answer: AxisListAnswer = {\n axis,\n label: info.label,\n basis: 'rows',\n total: hit.length,\n offset: skip,\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n scanned: rows.length,\n truncated: rows.length >= SCAN_MAX,\n ...(() => {\n const items = hit.slice(skip, skip + take).map((r: any) => this.rowItem(axis, r))\n return { items, names: namesFor(items, nameIndex(inst.model ?? {})) }\n })()\n }\n return answer\n }\n\n /*\n * **선언이 아닌 축** — 일정·실적(ISA-95 Part 4). 이 축의 집은 트윈 모델이 아니라 **커널 상태**다\n * (커널이 `source: 'state'` 로 선언한다).\n *\n * ── 멈춘 트윈은 0 이 아니다 ──────────────────────────────────────────────────\n * 커널이 동작하지 않으면 관측이 **없다**. 그때 빈 목록을 내면 \"작업이 0 건\" 으로 읽히고, 그건\n * 거짓이다 — 이 화면이 관측 열에서 내내 지켜 온 구분(관측 없음 ≠ 0)을 목록에서도 지킨다.\n *\n * ── 규모 ────────────────────────────────────────────────────────────────────\n * 상태 배열은 지금의 사실만 담아 유한하다(진행 중 오더·작업). 과거까지 세는 것은 저널의 일이고\n * 커서 페이징이 필요하다 — 그건 `historical` 축의 후속이며, 여기서 흉내내지 않는다.\n */\n if (axisSource(axis) === 'state') {\n /* 봉투를 벗긴다 — `{revision, state}` 안에 축이 있다. 그리고 **실행 중일 때만** 관측이다. */\n /*\n * **라이브는 권위, 히스토리는 파생.**\n *\n * 지금 도는 커널의 상태가 이 축의 진실이다. 그런데 커널이 멈춰 있거나 사용자가 **과거 시각**을\n * 물으면 답할 것이 없어진다 — 그때 저널을 그 시점까지 계산해 답한다(`recover`). 둘은 같은 모양이지만\n * **성질이 다르므로 `basis` 로 구별해 낸다**: 파생을 권위처럼 내면 다시 계산한 값을 보고 \"지금 이렇다\"\n * 로 읽게 된다.\n *\n * 규모: 계산 비용은 이벤트 수에 비례한다. 감추지 않고 **어느 리비전까지 계산했는지 함께 낸다** —\n * 이 화면이 목록마다 `basis` 를 밝혀 온 규율 그대로다.\n */\n const live = TwinEngine.isRunning(domainId, instanceId) && !at_\n let snap = live ? unwrapState(TwinEngine.snapshot(domainId, instanceId)) : null\n let folded: number | undefined\n if (!snap) {\n try {\n const rec = await TwinEngine.recover(domainId, instanceId, undefined, at_ ?? undefined)\n snap = unwrapState(rec)\n folded = Number((rec as any)?.revision) || undefined\n } catch {\n /* 다시 계산할 것이 없다(모델도 저널도 없다) — 없는 것을 0 으로 메우지 않는다. */\n snap = null\n }\n }\n if (!snap) {\n return { axis, label: info.label, basis: 'state', total: null, observed: false, offset: skip, items: [] }\n }\n /* 축이 사는 자리는 **커널 선언이 말한다**(`path`) — 축 이름으로만 읽으면 중첩된 축이 언제나\n 비어 보인다. 카드는 `axisValueOf` 로 읽는데 여기가 그 규칙을 지나지 않아, 「42」를 센 개념의\n 목록이 「0건」으로 나왔다(에너지의 수요 구간). 규칙의 집은 `axisValueOf` 하나다. */\n const bucket = axisValueOf(snap, info)\n const list: any[] = Array.isArray(bucket) ? bucket : []\n const hitState = q ? list.filter(o => matches(o, q)) : list\n const items = hitState\n .slice(skip, skip + take)\n .map(o => ({ id: idOf(o, info), fields: this.withOrderMaterial(axis, inst.model ?? {}, o) }))\n return {\n axis,\n label: info.label,\n /* 권위(라이브)와 파생(저널)을 구별해 낸다 — 화면이 이 낱말을 그대로 보인다. */\n basis: live ? 'state' : 'journal',\n ...(folded != null ? { foldedRevision: folded } : {}),\n ...(at_ ? { at: at_ } : {}),\n observed: true,\n total: hitState.length,\n offset: skip,\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n items,\n names: namesFor(items, nameIndex(inst.model ?? {}))\n }\n }\n\n /* 아직 문서 안에 사는 축 — 문서를 읽어 자른다. 규모 한계를 `basis` 로 드러낸다. */\n const raw = at(inst.model ?? {}, documentPath(axis))\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n const hit = q ? all.filter(o => matches(o, q)) : all\n return {\n axis,\n label: info.label,\n basis: 'document',\n total: hit.length,\n offset: skip,\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n ...(() => {\n /*\n * **한 벌뿐인 선언은 축 이름이 곧 식별자다.**\n *\n * `productionSpec` 처럼 문서에 객체 하나로 있는 축은 `id`/`key` 가 없다. 그것을 그대로\n * 목록에 실으면 \"식별자 없음 — 가리킬 수 없습니다\" 라는 줄 하나가 뜨고, 정작 그 선언을\n * 열어 볼 방법이 없다. 하나뿐인 것은 축 자신으로 가리킨다(상세도 같은 규칙으로 찾는다).\n */\n const singular = !Array.isArray(raw) && !!raw\n const items = hit\n .slice(skip, skip + take)\n .map(o => ({ id: idOf(o) ?? (singular ? axis : null), fields: this.withBinding(axis, inst.model ?? {}, o) }))\n return { items, names: namesFor(items, nameIndex(inst.model ?? {})), singular }\n })()\n }\n }\n\n /**\n * 행에서 **내부 배관을 걷어낸다** — 사용자가 볼 것은 현장의 사실이지 우리 스키마가 아니다.\n *\n * 손으로 목록을 두지 않는다. 관계와 그 조인 컬럼이 무엇인지는 **엔티티 메타데이터**가 알고,\n * 표로 두면 컬럼이 늘 때마다 여기를 고쳐야 하며 잊으면 그대로 새어 나간다 — 실제로\n * `domainId`·`instanceRowId` 같은 내부 UUID 가 화면까지 갔다.\n *\n * 식별자도 뺀다: 항목 자신의 id 는 이미 `id`/`itemId` 로 나가므로 두 번 보일 이유가 없다.\n */\n private strip(entityClass: any, idColumn: string, r: any): any {\n const meta = getRepository(entityClass).metadata\n const hidden = new Set<string>(['id', 'createdAt', 'updatedAt', 'creator', 'updater', 'creatorId', 'updaterId', idColumn])\n for (const rel of meta.relations) {\n hidden.add(rel.propertyName)\n for (const jc of rel.joinColumns) hidden.add(jc.propertyName)\n }\n /* `@RelationId` 로 승격한 내부 UUID(`domainId`·`instanceRowId`·`areaRowId`) — 관계 목록에는 없고\n 여기에만 있다. 이 한 줄이 없어서 실제로 화면까지 샜다. */\n for (const rid of meta.relationIds) hidden.add(rid.propertyName)\n const out: any = {}\n for (const [k, v] of Object.entries(r)) if (!hidden.has(k)) out[k] = v\n return out\n }\n\n\n /**\n * **자재는 자기 GS1 품목 참조를 안다** — 읽기 경계에서 이어 붙인다.\n *\n * 정본은 `productionSpec.binding` 하나다(커널이 EPC↔자재를 그 표로 잇는다). 그런데 그 사실은\n * **자재마다의 속성**이다: 이 자재가 GS1 품목 몇 번인가, 그래서 개체로 추적되는가(= 계보를 비교할\n * 수 있는가). 자재 목록에 그것이 없으면 자재는 자기 정체를 모르고, 사용자는 그 사실을 딴 축에서\n * 찾아야 한다.\n *\n * 그래서 **저장은 한 곳(binding), 표시는 읽는 자리에서 이어 붙임** — 이름표와 같은 방식이다.\n * 값을 복제해 두면 두 곳이 어긋나고, 어긋난 쪽을 아무도 모른다.\n */\n private withBinding(axis: string, model: any, fields: any): any {\n if (!BINDING_AXES.has(axis) || !fields || typeof fields !== 'object') return fields\n const binding: Record<string, string> = model?.productionSpec?.binding ?? {}\n const ref = binding[fields.key ?? fields.id]\n /* 없으면 키를 만들지 않는다 — 빈 값이 있는 것과 선언되지 않은 것은 다르다. */\n return ref ? { ...fields, gs1Ref: ref } : fields\n }\n\n /**\n * **오더가 무엇을 만드나** — GS1 품목 참조를 자재로 다시 계산해 붙인다.\n *\n * 커널의 오더는 품목을 GS1 으로 말한다(`urn:epc:idpat:sgtin:0614141.078101.*`). 사람에게 그 문자열은\n * 아무 뜻이 없고, 그 품목의 이름은 **자재 선언**이 갖고 있다. 둘을 잇는 것은 `productionSpec.binding`\n * (자재 키 → 품목 참조)이므로 **역방향으로 다시 계산한다.**\n *\n * 정본은 그대로 둔다: `gtin` 은 커널이 말한 값이고, 여기서 더하는 것은 **자재 키 하나**다(그 이름은\n * 이름표가 붙인다 — 값을 복제하지 않는다). 다시 계산하지 못하면 아무것도 더하지 않는다: 짐작으로 이으면\n * \"이 오더는 저것을 만든다\" 는 거짓이 되고, 그건 모르는 것보다 나쁘다.\n */\n private withOrderMaterial(axis: string, model: any, fields: any): any {\n if (axis !== 'orders' || !fields || typeof fields !== 'object') return fields\n const binding: Record<string, string> = model?.productionSpec?.binding ?? {}\n const refToMaterial = new Map(Object.entries(binding).map(([mat, r]) => [String(r), mat]))\n /* 단일 품목 작업지시는 `gtin`, 여러 품목이면 라인마다 말한다 — 첫 라인으로 대표하지 않는다. */\n /* 정체성 모양은 하나가 아니다 — 규칙의 집은 `item-ref` 하나다(웹 URI 원본에서 이 자리가 언제나\n 빈칸이었다). */\n const refOf = itemRefOf\n const mat = refToMaterial.get(String(refOf(fields.gtin) ?? ''))\n if (mat) return { ...fields, material: mat }\n const lineMats = (fields.lines ?? [])\n .map((l: any) => refToMaterial.get(String(refOf(l?.gtin) ?? '')))\n .filter(Boolean)\n return lineMats.length ? { ...fields, materials: [...new Set(lineMats)] } : fields\n }\n\n /** 행 하나 → 목록 항목. 컬럼 이름을 화면이 알지 않아도 되게 `id` + 나머지로 낸다. */\n private rowItem(axis: string, r: any): any {\n const { entity, idColumn } = ROW_BACKED[axis]\n return { id: r[idColumn], fields: this.strip(entity, idColumn, r) }\n }\n\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'One item of a standard concept: what the source declared, what the twin observed, what it links to and is linked from (declared relations, both directions), and where it came from. Never invents a value for a field the source did not provide.'\n })\n async twinModelItem(\n @Arg('instanceId') instanceId: string,\n @Arg('axis') axis: string,\n @Arg('itemId') itemId: string,\n @Ctx() context: ResolverContext\n ): Promise<any | null> {\n const domainId = context.state.domain.id\n const info = axisInfo(axis)\n if (!info) throw new Error(`unknown concept axis: \"${axis}\" — the kernel catalog does not declare it`)\n\n const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!inst) return null\n\n const model = inst.model ?? {}\n const row = ROW_BACKED[axis]\n let declared: any = null\n let provenance: any = null\n\n /*\n * **관측 축의 상세** — 일정·실적은 상태에서 찾는다. 커널이 멈춰 있으면 항목이 아니라 **모른다**를\n * 낸다(그 트윈에 그 오더가 없다는 뜻이 아니다 — 지금 관측이 없다는 뜻이다).\n */\n if (axisSource(axis) === 'state') {\n /*\n * 동작하지 않으면 **목록과 같은 길로 저널을 계산한다.**\n *\n * 목록만 계산하고 상세는 안 계산했더니, 목록에는 472건이 보이는데 그 줄을 열면 \"자기 속성이 없습니다\"\n * 가 나왔다 — 한 화면에서 두 답이 갈리면 어느 쪽이 맞는지 사용자가 알 수 없다.\n */\n const liveItem = TwinEngine.isRunning(domainId, instanceId)\n let snap = liveItem ? unwrapState(TwinEngine.snapshot(domainId, instanceId)) : null\n if (!snap) {\n try {\n snap = unwrapState(await TwinEngine.recover(domainId, instanceId))\n } catch {\n /* 다시 계산할 것이 없다 — 아래에서 \"모른다\" 를 낸다(0 으로 메우지 않는다). */\n }\n }\n /* 같은 규칙 — 축 이름이 아니라 선언된 자리에서 읽는다(§axisValueOf). */\n const bucket = snap ? axisValueOf(snap, info) : null\n const found = Array.isArray(bucket) ? bucket.find((o: any) => idOf(o, info) === itemId) : undefined\n /*\n * **상태를 읽었는데 그 개체가 없으면, 그런 개체가 없는 것이다** (2026-09-18).\n *\n * 이 갈래가 `!snap || !found` 하나였다. 그래서 없는 식별자로 물어도 「트윈이 실제로 본 것입니다」\n * 라고 적힌 패널이 돌아왔다 — 화면은 그것을 그려서, 있지도 않은 개체가 값이 비어 있는 개체처럼\n * 보였다. 문서 축은 같은 물음에 `null` 을 답한다(없는 것은 없다고 답한다). 상태 축도 같다.\n *\n * 못 읽은 것은 다른 사실이라 아래에서 따로 답한다 — 「없다」로 접지 않는다.\n */\n if (snap && !found) return null\n if (!snap) {\n return {\n instanceId, axis, label: info.label, itemId,\n identity: { standardClass: info.standardClass ?? null, typeRole: info.typeRole ?? null, kind: info.kind, gs1Scheme: info.gs1Scheme ?? null, journalAxis: info.journalAxis ?? null, describedBy: info.describedBy ?? null },\n declared: null,\n observed: null,\n observedOnly: true,\n /*\n * **왜 관측 열이 비었나** — 커널이 멈춰 있고 저널로도 되세우지 못했다. 코드는 목록·비교 열이\n * 쓰는 것과 같은 것을 쓴다(`not-running`) — 같은 사실에 두 낱말을 만들지 않는다.\n */\n observedAbsence: 'not-running' as const,\n basis: liveItem ? 'state' : 'journal', observedBasis: liveItem ? 'state' : 'journal', observing: liveItem,\n links: { out: [], incoming: [] }, properties: propertiesOf(axis).map((pr: any) => ({ key: pr.key, label: pr.label, kind: pr.kind, uom: pr.uom ?? null, observedBy: pr.observedBy ?? null })),\n /* 어떤 속성이 **효과가 있나** — 등록부가 말한다(§property-effects). 없는 것은 표시만 된다. */\n propertyEffects: propertyEffectsOf(axis),\n /*\n * 출처는 이 답의 `basis` 와 같은 규칙이다(아래 읽은 갈래도 같다). 여기를 `state` 로 박아 두어서, 커널이 멈춰\n * 저널로 되세우려던 답이 「지금 상태에서 읽었다」고 말했다(ADR-0075 결정 3 · 결함 넘김 2026-09-24).\n * 아무것도 못 읽었다는 사실은 `observedAbsence` 가 말한다 — 출처를 비우지 않는다(`READ_BASIS` 주석).\n */\n names: {}, provenance: { basis: liveItem ? 'state' : 'journal' }\n }\n }\n const names = namesFor([{ id: itemId, fields: found }], nameIndex(inst.model ?? {}))\n return {\n instanceId, axis, label: info.label, itemId,\n identity: { standardClass: info.standardClass ?? null, typeRole: info.typeRole ?? null, kind: info.kind, gs1Scheme: info.gs1Scheme ?? null, journalAxis: info.journalAxis ?? null, describedBy: info.describedBy ?? null },\n /*\n * **선언이 없는 축이다.** 두 열 중 왼쪽이 비는 것이 정상이고, 그 사실을 값으로 말한다\n * (`observedOnly`) — 빈 열을 \"원본이 침묵했다\" 로 읽으면 안 된다. 원본은 애초에 이 축을\n * 선언하지 않는다.\n */\n declared: null,\n observed: this.withOrderMaterial(axis, inst.model ?? {}, found),\n observedOnly: true,\n basis: liveItem ? 'state' : 'journal',\n /* 관측 열의 근거는 **한 이름으로** 낸다 — 두 이름을 두면 화면이 한쪽을 잊는다. */\n observedBasis: liveItem ? 'state' : 'journal',\n observing: liveItem,\n properties: propertiesOf(axis).map((pr: any) => ({ key: pr.key, label: pr.label, kind: pr.kind, uom: pr.uom ?? null, observedBy: pr.observedBy ?? null })),\n /* 어떤 속성이 **효과가 있나** — 등록부가 말한다(§property-effects). 없는 것은 표시만 된다. */\n propertyEffects: propertyEffectsOf(axis),\n links: await this.linksOf(domainId, inst, axis, itemId, found),\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n names,\n provenance: { basis: liveItem ? 'state' : 'journal' }\n }\n }\n\n if (row) {\n const found: any = await getRepository(row.entity).findOne({\n where: { domain: { id: domainId } as any, instance: { id: inst.id } as any, [row.idColumn]: itemId } as any\n })\n if (found) {\n const { sourceRef, ingestedAt, ...rest } = this.strip(row.entity, row.idColumn, found)\n declared = rest\n /* 출처는 속성이 아니라 **근거**다 — 두 열이 아니라 아래 근거 묶음으로 간다. */\n provenance = { sourceRef, ingestedAt, basis: 'rows' }\n }\n }\n\n /*\n * 행에 없으면 문서를 본다 — **투영이 낡은 트윈에서도 항목을 볼 수 있어야 한다.** 행만 보고\n * \"없다\" 고 답하면, 문서에는 있는 자리가 화면에서 사라진다(이 프로젝트가 내내 잡아 온 부류).\n */\n if (!declared) {\n const raw = at(model, info.path)\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n /* 한 벌뿐인 선언은 축 이름으로 찾는다 — 목록이 그 이름으로 가리켰기 때문이다. */\n const found = all.find(o => idOf(o) === itemId) ?? (!Array.isArray(raw) && raw && itemId === axis ? raw : undefined)\n if (found) {\n declared = typeof found === 'string' ? { id: found } : this.withBinding(axis, model, found)\n provenance = { basis: 'document' }\n }\n }\n\n /* 선언에도 문서에도 없다 — 그런데 **관측에는 있을 수 있다**(원본이 모르는 자원). 그 경우도\n 항목으로 열려야 한다. 둘 다 없으면 진짜로 없는 것이므로 `null`. */\n const seen = await this.observedOf(domainId, instanceId, axis, itemId)\n const observed = 'value' in seen ? seen.value : null\n if (!declared && !observed) return null\n\n /* 이웃을 먼저 구한다 — 이름표가 이웃의 id 까지 덮으려면 반환 전에 손에 있어야 한다. */\n const links = await this.linksOf(domainId, inst, axis, itemId)\n\n /*\n * **구역 이름은 모델에 없다** — 구역은 호스트 개념이고(`TwinArea`), 인제스트가 모델에서 갈라\n * 공간 쪽으로 보낸다. 그래서 모델만 조회하는 이름표에는 `a-floor` 의 이름이 없고, 관계 그림에 그 id 가\n * 그대로 섰다. 그 행에서 가져와 이름표에 합친다(이 트윈의 공간 것만).\n */\n const areaNames: Record<string, string> = {}\n if (inst.spaceId) {\n const areas = await getRepository(TwinArea)\n .find({ where: { domain: { id: domainId } as any, space: { spaceId: inst.spaceId } as any } as any })\n .catch(() => [] as any[])\n for (const a of areas as any[]) if (a?.areaId && a?.name) areaNames[a.areaId] = a.name\n }\n\n return {\n instanceId,\n axis,\n label: info.label,\n itemId,\n /* 정체 — 표준 클래스·식별 스킴은 전부 카탈로그 선언에서 온다. */\n identity: {\n standardClass: info.standardClass ?? null,\n typeRole: info.typeRole ?? null,\n kind: info.kind,\n gs1Scheme: info.gs1Scheme ?? null,\n /*\n * 선언 둘을 그대로 나른다 (ADR-0074) — 이 개체의 이력을 저널의 어느 축으로 묻나,\n * 그리고 식별자 말고 무엇이 이 개체를 말하나. 화면이 그 목록을 갖지 않게 한다.\n */\n journalAxis: info.journalAxis ?? null,\n describedBy: info.describedBy ?? null\n },\n /*\n * **그릇인가** — 문서에 객체 하나로 있는 축(`productionSpec`)인지.\n *\n * `kind` 로는 갈리지 않는다: 커널은 라우트·레시피·공정도 `spec` 이라 부른다(같은 선언 부류라는\n * 뜻). 화면이 `kind` 로 갈랐더니 **라우트 상세가 그릇 틀로 그려져** 가장 중요한 정보(공정 순서)가\n * 개수 칩 하나로 줄어들었다. 그릇인지 아닌지는 모양이 말한다.\n */\n container:\n axisSource(axis) === 'document' && !Array.isArray(at(model, info.path)) && at(model, info.path) != null,\n /* 두 열 — 원본이 말한 값, 트윈이 관측한 값. 한쪽이 없으면 **없다고 낸다**(0 으로 메우지 않는다). */\n declared,\n observed,\n /*\n * 관측 열이 **자기 근거를 말한다** — 목록의 그 낱말 그대로(`state`=라이브 권위, `journal`=다시 계산한\n * 파생). 없으면 비교하지 못한 것이다. 파생이면 몇 번째 리비전까지 계산했는지 함께 낸다.\n */\n ...('value' in seen\n ? { observedBasis: seen.basis, ...(seen.foldedRevision != null ? { observedRevision: seen.foldedRevision } : {}) }\n : { observedAbsence: seen.absence }),\n /* 선언된 속성 — 어느 관측 축에서 오는지도 함께(카탈로그가 말한 대로). */\n properties: propertiesOf(axis).map((p: any) => ({ key: p.key, label: p.label, kind: p.kind, uom: p.uom ?? null, observedBy: p.observedBy ?? null })),\n /*\n * **효과가 있는 속성과 표시만 되는 속성은 다르다.** 속성은 열려 있어 아무 사실이나 실어 보낼 수\n * 있지만, 값이 계산을 바꾸려면 그 규칙을 코드가 알아야 한다. 지금 무엇이 그런지 화면이 말할 수\n * 있게 등록부를 함께 낸다 — 사용자가 넣고 나서 아무 일도 안 일어나는 이유를 알 수 있게.\n */\n propertyEffects: propertyEffectsOf(axis),\n links,\n /*\n * **등급 이름은 등급이 갖고 있다.** 공정은 자격을 등급 id 로만 요구하므로(표준이 그렇다),\n * 그 id 를 그대로 화면에 내면 `assembler-op` 이 사용자에게 간다. 등급의 표시명은 등급 선언의\n * `description`(i18n 키)에 있고 그것은 **다른 축**이다 — 화면이 축을 하나 더 읽지 않아도 되게\n * 여기서 이어 붙인다(서버는 이미 모델을 손에 들고 있다).\n */\n resourceClassLabels: this.classLabels(model),\n /*\n * **공정이면 그 공정의 능력도 함께 낸다** — ISA-95 Part 4 `OperationsCapability`.\n *\n * 공정 상세에서 사람이 묻는 것은 \"이 공정이 지금 얼마나 더 할 수 있나\" 이고, 그 답은 명세만\n * 봐서는 안 나온다(약정과 지금 못 쓰는 자원을 빼야 한다). 화면이 축을 하나 더 읽지 않게\n * 여기서 이어 붙인다 — 이름표·등급 라벨을 붙이는 것과 같은 이유다.\n */\n ...(await this.capabilityOfOperation(domainId, instanceId, axis, itemId)),\n /*\n * 상세도 같은 표를 쓴다 — 목록과 상세가 같은 이름으로 말해야 사용자가 같은 것으로 읽는다.\n *\n * **이웃의 이름도 함께 싣는다.** 관계 그림의 이웃은 대개 *들어오는* 링크(이 자리를 기준 자리로\n * 삼는 설비·사람)라, 이 항목 자신의 필드에는 그 id 가 없다 — 필드만 훑으면 그림이 id 로 채워진다.\n */\n names: namesFor(\n [{ id: itemId, fields: declared }, { fields: observed }, { fields: links }],\n { ...nameIndex(model), ...areaNames }\n ),\n provenance\n }\n }\n\n /**\n * **id → 이름**, 모든 축을 한 표로.\n *\n * ── 왜 이 표가 필요한가 ──────────────────────────────────────────────────────\n * 행은 다른 것을 **id 로** 가리킨다(사람의 `personnelClassIds`, 설비의 `homeLocationId`, 공정의\n * `locationType`). 그 id 의 이름은 **가리켜진 축의 행**에 있으므로, 화면이 그것을 알려면 축을\n * 하나씩 더 읽어야 한다 — 그래서 지금까지 표면마다 그냥 id 를 찍었다(`cutter-op`, `cut-station`).\n * 표면을 하나씩 고치는 것은 끝이 없다: 새 화면은 처음부터 다시 id 를 찍는다.\n *\n * 그래서 **서버가 붙인다.** 서버는 이미 모델을 손에 들고 있고, 어느 축이 있는지는 커널 카탈로그가\n * 선언한다(`TWIN_AXES`) — 도메인이 늘어도 이 함수는 그대로다.\n *\n * 값은 그 항목이 **자기 이름이라고 말한 것**이다(`name`·`label`·`description`). 그중 어떤 것은\n * i18n 키이므로(등급의 `description`) 번역은 화면의 일로 남긴다. 이름이 없으면 표에 넣지 않는다 —\n * 없는 것을 지어내지 않고, 그 경우 화면은 id 를 그대로 보인다.\n */\n private nameIndex(model: any): Record<string, string> {\n const out: Record<string, string> = {}\n for (const info of TWIN_AXES as any[]) {\n /* 관측 축(상태·저널)은 문서에 없다 — 경로가 없는 축을 읽으면 모델 루트를 훑는다. */\n if (axisSource(info.axis) !== 'document') continue\n const raw = at(model ?? {}, info.path)\n const list = Array.isArray(raw) ? raw : raw ? [raw] : []\n for (const o of list) {\n const id = idOf(o)\n if (!id || typeof o !== 'object') continue\n const label = o.name ?? o.label ?? o.description\n /* 이름이 id 와 같으면 표에 넣지 않는다 — 같은 값을 두 번 보이는 셈이다. */\n if (typeof label === 'string' && label && label !== id && !out[id]) out[id] = label\n }\n }\n return out\n }\n\n /**\n * 이 응답이 **실제로 가리킨 것만** 골라 낸다.\n *\n * 모델 전체 표를 그대로 실으면 자리가 10만인 현장에서 목록 한 페이지에 10만 줄짜리 이름표가\n * 따라온다. 나온 값에 걸리는 것만 싣는다 — 규모에서 성립하는 유일한 방식이다.\n */\n private namesFor(rows: any[], index: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {}\n const take = (v: any, depth: number): void => {\n if (v == null || depth > 4) return\n if (typeof v === 'string') { if (index[v]) out[v] = index[v]; return }\n if (Array.isArray(v)) { for (const x of v) take(x, depth + 1); return }\n if (typeof v === 'object') for (const x of Object.values(v)) take(x, depth + 1)\n }\n for (const r of rows) { take(r?.fields ?? r, 0); if (typeof r?.id === 'string' && index[r.id]) out[r.id] = index[r.id] }\n return out\n }\n\n /** 등급 id → 표시명 키. 인원·설비·자산·품목 등급을 한 표로 — 어느 자원이든 같은 방식으로 요구된다. */\n private classLabels(model: any): Record<string, string> {\n const out: Record<string, string> = {}\n for (const key of ['personnelClasses', 'equipmentClasses', 'assetClasses', 'materialClasses'])\n /* 표시명은 `name` 이 정본이다 — 옛 모델는 `description` 에 담고 있어 둘 다 본다(읽기 경계 하나). */\n for (const c of (model?.[key] ?? []) as any[]) if (c?.id && (c.name || c.description)) out[c.id] = c.name || c.description\n return out\n }\n\n /**\n * 관측이 본 이 항목 — 커널이 실행 중일 때만. **실행 중이 아니면 `null` 이지 빈 객체가 아니다**\n * (관측이 없는 것과 비교하지 못한 것은 다르다).\n */\n /**\n * 이 공정의 **생산 능력** — 공정 축 항목에만 붙는다.\n *\n * 구간은 **앞으로 24시간**이다. 표준의 약정·가용은 *앞으로 쓸* 용량이므로 지난 구간을 두고 말하면\n * 뜻이 없고, 이 화면에는 사용자가 고른 창이 없다. 그래서 하루를 쓰고 **그 사실을 값과 함께 낸다**\n * (화면이 라벨로 말한다) — 어느 구간의 값인지 모르면 능력은 읽을 수 없다.\n *\n * **수요를 지어내지 않는다.** 여기서 내는 값(상한·약정·달성불가·가용·제약하는 축)은 전부 공급 쪽이다 —\n * 자원 수·사이클·가동률에서 나온다. 수요는 `ok`·병목·하루 상한에만 쓰이고 그것들은 내지 않으므로,\n * 계산에 넘기는 수요 `1` 은 결과에 새지 않는다(성과 화면은 사용자가 걸어 둔 목표를 쓴다 — 그 화면은\n * \"목표를 낼 수 있나\" 에 답하고 여기서는 \"얼마나 더 할 수 있나\" 에 답한다).\n *\n * 안 실행 중이면 붙이지 않는다 — 능력은 지금 자원의 사실에서 나오고, 없는 것을 지어내지 않는다.\n */\n private async capabilityOfOperation(\n domainId: string,\n instanceId: string,\n axis: string,\n itemId: string\n ): Promise<{ capability?: any } > {\n if (axis !== 'operations') return {}\n if (!TwinEngine.isRunning(domainId, instanceId)) return {}\n const from = new Date()\n const to = new Date(from.getTime() + 24 * 3_600_000)\n const monday = Date.UTC(from.getUTCFullYear(), from.getUTCMonth(), from.getUTCDate() - ((from.getUTCDay() + 6) % 7))\n try {\n const rows = await TwinEngine.operationsCapability(\n domainId,\n { instanceId },\n 1,\n monday,\n { fromTime: from.toISOString(), toTime: to.toISOString() }\n )\n const report = rows.find((r: any) => r.instanceId === instanceId)?.report\n const entry = report?.perOperation?.find((o: any) => o.operation === itemId)\n if (!entry) return {}\n /* 병목·상한은 **넣지 않는다** — 그 둘만 수요에 달려 있고, 여기서는 수요를 모른다. */\n return { capability: { window: report.window, operationsType: report.operationsType, ...entry } }\n } catch {\n /* 능력을 못 냈다고 상세가 안 열릴 이유는 없다 — 없으면 없는 대로 낸다(화면이 그 줄을 안 그린다). */\n return {}\n }\n }\n\n /**\n * 이 항목을 트윈이 **관측한 값** — 그리고 **무엇을 근거로** 아는지.\n *\n * 봉투를 푸는 것을 빠뜨려서(`unwrapState`) 문서 축의 관측 열이 통째로 비어 있던 자리다(사람을 열면\n * 트윈이 아는 것이 전부 `—` 였다).\n *\n * 근거를 값과 함께 낸다 — 목록이 오래 해 온 그대로다(§twinModelItemList). 라이브(권위)와 저널\n * 폴드(파생)는 **같은 모양의 객체**라서, 근거가 없으면 다시 계산한 값을 \"지금 이렇다\" 로 읽는다. 근거를\n * 실을 자리가 없던 동안에는 멈춘 트윈의 저널을 아예 계산하지 않고 `—` 로 두는 편이 정직했다. 이제\n * 자리가 있으니 계산한다 — 멈춘 트윈에도 마지막으로 알던 사실이 있고, 그것을 감출 이유는 없다.\n *\n * 다시 계산할 것이 없으면(모델도 저널도 없다) `null` 이다 — **없는 것과 비교하지 못한 것은 다르다.**\n */\n private async observedOf(\n domainId: string,\n instanceId: string,\n axis: string,\n itemId: string\n ): Promise<{ value: any; basis: 'state' | 'journal'; foldedRevision?: number } | { absence: 'not-running' | 'not-observed' }> {\n const live = TwinEngine.isRunning(domainId, instanceId)\n let state: any = null\n let folded: number | undefined\n if (live) {\n state = unwrapState(TwinEngine.snapshot(domainId, instanceId))\n } else {\n try {\n const rec = await TwinEngine.recover(domainId, instanceId)\n folded = Number((rec as any)?.revision) || undefined\n /*\n * **이벤트를 하나도 계산하지 않은 폴드는 관측이 아니다.** 저널이 비어도 복원은 선언을 다시 투영한\n * 기준선을 돌려준다 — 그것을 \"트윈이 관측한 값\" 열에 실으면 **선언이 관측으로 위장한다**\n * (원본이 말한 값이 오른쪽에도 똑같이 앉아, 견준 것처럼 보인다). 계산한 것이 없으면 없다고 한다.\n */\n if (folded == null) return { absence: 'not-running' as const }\n state = unwrapState(rec)\n } catch {\n return { absence: 'not-running' as const }\n }\n }\n /* 같은 규칙 — 선언된 자리에서 읽는다. 축 이름으로 읽으면 중첩된 축이 언제나 「관측 없음」이 된다. */\n const bucket = state ? axisValueOf(state, axisInfo(axis) ?? { axis }) : null\n /*\n * **왜 관측이 없는지 말한다.** 예전에는 그냥 `null` 이었고 화면은 그것을 \"트윈이 실행 중이지 않아\"\n * 로 읽었다 — 실행 중인데도 그렇게 말했다(공정 상세에서 관측됨). 공정·레시피처럼 **관측 축이\n * 아닌 것**은 트윈이 돌든 말든 관측이 없다. 이유가 다르면 화면이 다르게 말해야 한다.\n */\n if (!Array.isArray(bucket)) return { absence: 'not-observed' as const }\n /* 같은 규칙 — 선언이 말하는 자리로 찾는다. `id` 로만 찾으면 수요 구간을 열 수 없다. */\n const value = bucket.find((x: any) => idOf(x, axisInfo(axis)) === itemId)\n if (!value) return { absence: 'not-observed' as const }\n return { value, basis: live ? 'state' : 'journal', ...(folded != null ? { foldedRevision: folded } : {}) }\n }\n\n /**\n * 이어진 것 — **양방향.** 선언된 관계(`TWIN_RELATIONS`)만 따라간다.\n *\n * 관계를 코드가 알지 않으므로 도메인이 늘어도 여기 손댈 것이 없다. 대신 **선언에 없는 관계는\n * 그리지 않는다** — 지도에 없는 길을 그리는 것보다 없다고 두는 것이 정직하다.\n *\n * 들어오는 쪽(누가 나를 가리키나)은 그 축의 항목을 살펴야 안다. 규모 규율상 **깊이 1 · 방향별\n * 상한**이고, 넘치면 몇이 더 있는지 말한다(목록으로 보낼 수 있게).\n */\n private async linksOf(\n domainId: string,\n inst: any,\n axis: string,\n itemId: string,\n /*\n * 이 항목 자신 — **상태 축은 문서에서 찾을 수 없다.** 부르는 쪽이 이미 손에 들고 있으므로 넘겨\n * 받는다. 없으면 예전처럼 문서에서 찾는다(문서 축의 거동은 그대로).\n */\n self0?: any\n ): Promise<any> {\n const NEIGHBOR_MAX = 20\n const model = inst.model ?? {}\n\n /*\n * 관측 축의 항목들 — **한 번만** 읽는다(관계마다 다시 계산하면 저널을 여러 번 계산한다).\n * 라이브가 있으면 그것, 없으면 저널 폴드. 없으면 빈 배열(없는 것을 지어내지 않는다).\n */\n let observedState: any\n let observedLoaded = false\n const observedBucket = async (a: string): Promise<any[]> => {\n if (!observedLoaded) {\n observedLoaded = true\n try {\n observedState = TwinEngine.isRunning(domainId, inst.instanceId)\n ? unwrapState(TwinEngine.snapshot(domainId, inst.instanceId))\n : unwrapState(await TwinEngine.recover(domainId, inst.instanceId))\n } catch {\n observedState = null\n }\n }\n const b = observedState ? (observedState as any)[a] : null\n return Array.isArray(b) ? b : []\n }\n\n /*\n * **관계는 선언 어휘로 푼다** — 문서에서 이 항목을 찾아 그것을 본다.\n *\n * 관계 선언의 필드 이름(`locations.parentId`)은 **원본 문서의 어휘**다. 행은 같은 사실을 자기\n * 컬럼 이름으로 담는다(자리의 구역은 `area` FK). 행을 보고 `parentId` 를 찾으면 늘 비어서\n * \"이어진 것이 없다\" 로 알리지 않고 답한다 — 실제로 그랬다.\n *\n * 어느 쪽이 정본인가로 구분하면 답이 분명하다: 관계를 선언한 어휘가 문서 어휘이므로 **문서에서\n * 푼다.** 행에만 있고 문서에 없는 항목(있을 수 있다)은 이어진 것이 비지만, 그것은 사실이다.\n */\n const axisPath = axisSource(axis) === 'document' ? axisInfo(axis)?.path : undefined\n const rawSelf = axisPath ? at(model, axisPath) : undefined\n const selfAll = Array.isArray(rawSelf) ? rawSelf : rawSelf ? [rawSelf] : []\n const self = self0 ?? selfAll.find((o: any) => idOf(o) === itemId)\n\n /*\n * ── 한 필드가 두 곳을 가리킬 때 (계약 0.9.24, 2026-09-17) ──────────────────────\n * `locations.parentId` 는 다른 자리(라인 · 셀 · 존)이거나, 그 id 의 자리가 없으면 공간의 구역이다\n * (`axis-or-external`). 어느 쪽인지는 **조회로** 갈린다 — 규칙은 계약의 `splitRelationIds` 하나다.\n *\n * 화면에는 두 줄로 낸다: 자리 쪽은 그 자리로 걷는 링크(`target.kind: 'axis'`), 나머지는 구역으로\n * 풀린 것(`external`). 한 줄에 섞으면 화면이 그 줄 전체를 외부로 그리거나 전체를 링크로 그려 둘 중\n * 하나가 틀린다. 선언은 `declaredTarget` 으로 함께 남긴다.\n */\n const axisIdSets = new Map<string, Set<string>>()\n for (const r of relationsFrom(axis)) {\n if (r.target?.kind !== 'axis-or-external' || axisIdSets.has(r.target.axis)) continue\n const tInfo = axisInfo(r.target.axis)\n const raw = tInfo && axisSource(r.target.axis) === 'document' ? at(model, tInfo.path) : await observedBucket(r.target.axis)\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n axisIdSets.set(r.target.axis, new Set(all.map((o: any) => idOf(o)).filter(Boolean).map(String)))\n }\n const inAxis = (a: string, id: string) => axisIdSets.get(a)?.has(id) ?? false\n\n /* 나가는 쪽 — 내 필드가 가리키는 것. 선언이 필드 이름을 알려 준다. */\n const out = relationsFrom(axis).map((r: any) => {\n const raw = self ? this.fieldValue(self, r.field) : []\n const ids = raw.filter((v: any) => v != null).map(String)\n return {\n via: r.via,\n field: r.field,\n optional: !!r.optional,\n /* 대상이 축이면 그 축의 항목으로 갈 수 있다. 타입·외부(구역)면 **갈 곳이 다르다** —\n 화면이 링크를 만들지 말지 알아야 하므로 대상 종류를 그대로 낸다(막다른 링크 금지). */\n target: r.target,\n /*\n * ── 언제의 일인가, 그리고 담아 둬도 되나 (2026-09-06) ────────────────\n * 판정을 계약이 낸다. 화면이 `standing` 을 보고 스스로 정하면 값이 하나 늘 때 한 화면만\n * 따라간다. UX 레인이 이 칸을 요청했고, 그쪽에 있던 규칙은 걷었다.\n *\n * `tense` 가 없는 관계도 `cacheable: false` 다. 모를 때는 다시 조회하는 쪽이 낫다 —\n * 낡은 값을 자신 있게 보여 주는 것이 비어 있는 것보다 나쁘다. 그래서 `tense` 는 없을 수\n * 있고 `cacheable` 은 언제나 있다.\n */\n tense: tenseOf(r),\n cacheable: isCacheableTense(tenseOf(r)),\n ids: ids.slice(0, NEIGHBOR_MAX),\n total: ids.length\n }\n }).flatMap((l: any) => {\n if (l.target?.kind !== 'axis-or-external') return [l]\n const all = self ? this.fieldValue(self, l.field).filter((v: any) => v != null).map(String) : []\n const split = splitRelationIds(l.target, all, inAxis)\n const part = (target: any, ids: string[]) => ({ ...l, target, declaredTarget: l.target, ids: ids.slice(0, NEIGHBOR_MAX), total: ids.length })\n const parts = [\n ...(split.axis?.ids.length ? [part({ kind: 'axis', axis: split.axis.axis }, split.axis.ids)] : []),\n ...(split.external?.ids.length ? [part({ kind: 'external', entity: split.external.entity }, split.external.ids)] : [])\n ]\n /* 비어 있는 관계도 낸다(아래 주석) — 가리키는 것이 없으면 선언 그대로 한 줄. */\n return parts.length ? parts : [l]\n })\n\n /*\n * ── 밖을 가리키는 관계를 푼다 (2026-09-05) ─────────────────────────────────\n * 계약이 `kind: 'external'` 을 선언하며 「해소는 호스트가 한다」고 적어 두었는데 **부르는 곳이\n * 0이었다.** 그래서 화면은 id 만 받고 그것이 무엇인지, 갈 수 있는지 몰랐다.\n *\n * 못 풀면 **못 푼다고 말한다** — 링크를 지우면 화면이 「그런 관계가 없다」로 읽고, 실제로는\n * 「아무도 답할 수 없다」다. 사람이 할 일이 다르다.\n */\n for (const l of out) {\n if (l.target?.kind !== 'external' || !l.ids.length) continue\n const got = await resolveExternal(l.target.entity, domainId, l.ids, { instanceId: inst.instanceId }, m => twinWarn(m))\n if (got.refs) (l as any).refs = got.refs\n else (l as any).unresolved = got.unresolved\n }\n\n /*\n * **비어 있는 관계도 낸다.** 예전에는 `total > 0` 만 냈다 — 그러면 사람은 없다는 것조차 모른다.\n *\n * 실측으로 그 값이 드러났다(2026-09-05): 설비 64대에 시험 규격이 전부 비어 있는 것을 「빈 묶음」\n * 으로 세워 두니 **「이 설비에 검사 기준이 없다」와 「화면이 그것을 안 본다」가 구별됐다.** 지우면\n * 그 구별이 사라진다.\n *\n * 선택이 아닌 관계(`optional: false`)가 비어 있으면 그것은 **끊어진 참조**이고, 그 사실이 화면에\n * 닿아야 한다.\n */\n\n /* 들어오는 쪽 — 나를 가리키는 항목들. 그 축이 행이면 DB 가 세고, 문서면 문서를 전수 조회한다. */\n const incoming: any[] = []\n /*\n * 밖에서 오는 것을 함께 싣는다 — 제품이 자기 저장소에서 모은다(커널은 그 표를 모른다).\n * 꽂힌 해소기가 없으면 빈 배열이고 그것은 정상이다.\n */\n incoming.push(...(await externalIncoming(domainId, inst.instanceId, axis, itemId, m => twinWarn(m))))\n for (const r of relationsTo(axis)) {\n const fromInfo = axisInfo(r.from)\n if (!fromInfo) continue\n const hits: string[] = []\n /*\n * 행은 `axis` 관계만 담는다. `axis-or-external`(자리 → 부모 자리 또는 구역)은 행에 구역 FK(`area`)만\n * 있고 부모 **자리**를 담는 칸이 없어서, 행에서 세면 「이 존 아래 자리들」이 조용히 0이 된다.\n * 그 관계는 선언 어휘가 사는 문서에서 센다.\n */\n const row = r.target?.kind === 'axis' ? ROW_BACKED[r.from] : undefined\n if (row) {\n const repo = getRepository(row.entity)\n /*\n * **FK 는 부르지 않으면 오지 않는다.** 관계 필드를 로딩하지 않고 조회하면 값이 늘 `undefined`\n * 라서 \"나를 가리키는 것이 하나도 없다\" 로 알리지 않고 답한다 — 실제로 그랬다(설비 둘이 이 자리를\n * 기준으로 삼는데 이웃이 비어 있었다).\n *\n * 어느 필드가 관계인지는 **엔티티 메타데이터**가 안다. 축마다 표를 두면 축이 늘 때마다\n * 여기를 고쳐야 하고, 고치는 것을 잊으면 같은 침묵이 다시 생긴다.\n */\n const relationNames = new Set(repo.metadata.relations.map(rel => rel.propertyName))\n const field = r.field.replace(/\\[\\]$/, '').split('.')[0]\n const rows: any[] = await repo.find({\n where: { domain: { id: domainId } as any, instance: { id: inst.id } as any },\n ...(relationNames.has(field) ? { relations: [field] } : {}),\n take: 5000\n })\n for (const x of rows) {\n /* 행에서는 관계가 FK 객체이거나 컬럼이다 — 이름 후보를 순서대로 본다. */\n const v = this.relationValueOfRow(x, r.field, axis)\n if (v.includes(itemId)) hits.push(x[row.idColumn])\n }\n } else {\n /*\n * 들어오는 쪽을 훑는다 — **어디를 훑을지는 그 축의 `source` 가 정한다.**\n *\n * 문서 축은 모델에서, 관측 축은 **상태에서** 훑는다(작업 → 이 오더, 작업 → 이 자리). 한동안\n * 관측 축을 건너뛰었더니 오더 상세가 \"닿는 관계가 없습니다\" 라고 답했다 — `tasks.orderId` 를\n * 선언해 두고도 그 관계를 그리지 않은 것이다. 선언한 것을 그리지 않으면 선언이 거짓이 된다.\n *\n * 규모: 상태는 지금의 사실만 담아 유한하고, 상한과 총계는 문서 축과 같은 규율을 쓴다\n * (넘치면 몇이 더 있는지 말한다). 저널 전체를 전수 조회하는 일은 여기서 하지 않는다.\n */\n const raw =\n axisSource(r.from) === 'document' ? at(model, fromInfo.path) : (await observedBucket(r.from))\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n for (const x of all) if (this.fieldValue(x, r.field).map(String).includes(itemId)) {\n const id = idOf(x)\n if (id) hits.push(id)\n }\n }\n /*\n * **들어오는 쪽도 빈 것을 낸다** — 나가는 쪽과 같은 이유다(위 주석).\n *\n * 「이 설비를 가리키는 작업이 없다」는 사실이고, 그것을 지우면 화면은 그 물음을 물어보지도\n * 못한다. 축당 들어오는 관계는 0~8개다(실측 2026-09-05: 시험규격 8 · 자리 6 · 나머지 2 이하)\n * — 다 내도 읽을 수 있는 분량이다.\n *\n * 값도 안 든다. 행 축은 0을 알아내려면 이미 `find` 를 돌렸고, 그 0을 말하는 비용은 없다.\n *\n * `externalIncoming` 은 여기서 예외다 — 그쪽의 빈 묶음은 「그 제품이 이 축을 안 본다」는\n * 뜻이고 우리 선언에 없는 관계이므로 할 말이 없다.\n */\n incoming.push({\n via: r.via,\n from: r.from,\n field: r.field,\n tense: tenseOf(r),\n cacheable: isCacheableTense(tenseOf(r)),\n ids: hits.slice(0, NEIGHBOR_MAX),\n total: hits.length\n })\n }\n\n return { out, incoming }\n }\n\n /**\n * 선언 필드 경로 → 값들. `inputs[].material` 처럼 **배열을 지나는 경로**를 다룬다.\n * 배열 표기(`[]`)가 관계 선언의 문법이므로 그것을 따르는 것이 곧 선언을 존중하는 것이다.\n */\n private fieldValue(obj: any, field: string): any[] {\n let cur: any[] = [obj]\n for (const seg of field.split('.')) {\n const isArray = seg.endsWith('[]')\n const key = isArray ? seg.slice(0, -2) : seg\n const next: any[] = []\n for (const c of cur) {\n if (c == null) continue\n const v = c[key]\n if (v == null) continue\n if (Array.isArray(v)) next.push(...v)\n else next.push(v)\n }\n cur = next\n }\n return cur.map(v => (typeof v === 'object' && v !== null ? idOf(v) ?? v : v)).filter(v => v != null)\n }\n\n /**\n * 행에서 관계 값을 꺼낸다 — FK 는 객체(관계 미로딩이면 없음)이고 문서 필드명과 컬럼명이 다를 수 있다.\n *\n * 여기서 컬럼 이름을 **축마다 표로 두지 않는다.** 후보를 순서대로 보는 편이 축이 늘 때 고칠 것이\n * 없다: 관계 필드 이름 그대로 · 그 이름의 FK 객체의 id 컬럼.\n */\n private relationValueOfRow(rowObj: any, field: string, targetAxis: string): string[] {\n const key = field.replace(/\\[\\]$/, '').split('.')[0]\n const v = rowObj[key]\n if (v == null) return []\n if (typeof v === 'string') return [v]\n if (Array.isArray(v)) return v.map(x => (typeof x === 'string' ? x : idOf(x) ?? '')).filter(Boolean)\n /* FK 객체 — 대상 축의 id 컬럼으로 읽는다(관계를 로딩하지 않았으면 값이 없고, 그것도 사실이다). */\n const idCol = ROW_BACKED[targetAxis]?.idColumn\n const got = idCol ? v[idCol] : idOf(v)\n return got ? [String(got)] : []\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"twin-model-item-query.js","sourceRoot":"","sources":["../../../server/service/twin-model/twin-model-item-query.ts"],"names":[],"mappings":";;;;AAEA,gDAA8C;AAC9C,+CAA4E;AAE5E,iDAAkF;AAElF,+CAAyC;AAEzC,oDAAkD;AAClD,8DAAwD;AACxD,0EAAoE;AACpE,+DAA+D;AAC/D,yFAAoF;AACpF,wEAAgE;AAChE,yDAAiD;AACjD,2DAAmD;AACnD,2DAAmD;AACnD,6DAAqD;AACrD,mDAA+D;AAE/D,yDAAyD;AACzD,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAC5J,OAAO,CAAC,uBAAuB,CAAC,CAAA;AAqBlC,iEAA0E;AAE1E;;;;;GAKG;AACH,MAAM,UAAU,GAAkE;IAChF,SAAS,EAAE,EAAE,MAAM,EAAE,+BAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE;IACzF,SAAS,EAAE,EAAE,MAAM,EAAE,iCAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;IAC5F,UAAU,EAAE,EAAE,MAAM,EAAE,iCAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;CACvF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC,CAAA;AAGlE,0EAA0E;AAC1E,SAAS,OAAO,CAAC,CAAM,EAAE,CAAS;IAChC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAA;IACnB,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;IAC9B,MAAM,IAAI,GAAG,CAAC,CAAM,EAAE,KAAa,EAAW,EAAE;QAC9C,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,KAAK,CAAA;QACxC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QACnG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAA;QAC5D,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAA;QAChF,OAAO,KAAK,CAAA;IACd,CAAC,CAAA;IACD,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACnB,CAAC;AAED;;;;;;;;;;;;GAYG;AAGI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAMvB,AAAN,KAAK,CAAC,iBAAiB,CACF,UAAkB,EACxB,IAAY,EAClB,OAAwB,EACI,MAAe,EACF,MAAe,EAChB,KAAc,EAOvB,SAAkB;QAExD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC3B;yCACiC;QACjC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,4CAA4C,CAAC,CAAA;QAEtG,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAA;QAC3G,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QAEtB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QACrC,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QAC/B,yDAAyD;QACzD,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;QACjE,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAE5B,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC;YACd,uDAAuD;YACvD,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACtC,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAS,EAAE,CAAA;YACnF,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;YACtF,MAAM,MAAM,GAAmB;gBAC7B,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,MAAM;gBACb,KAAK;gBACL,MAAM,EAAE,IAAI;gBACZ,kEAAkE;gBAClE,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvD,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;aACnD,CAAA;YACD,OAAO,MAAM,CAAA;QACf,CAAC;QAED,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;YACb;;;;;;;eAOG;YACH,MAAM,QAAQ,GAAG,IAAI,CAAA;YACrB,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACtC,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAS,EAAE,CAAA;YACnF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;YACzE,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YACtE,MAAM,MAAM,GAAmB;gBAC7B,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,MAAM;gBACb,KAAK,EAAE,GAAG,CAAC,MAAM;gBACjB,MAAM,EAAE,IAAI;gBACZ,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvD,OAAO,EAAE,IAAI,CAAC,MAAM;gBACpB,SAAS,EAAE,IAAI,CAAC,MAAM,IAAI,QAAQ;gBAClC,GAAG,CAAC,GAAG,EAAE;oBACP,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;oBACjF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAA,wBAAQ,EAAC,KAAK,EAAE,IAAA,yBAAS,EAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAA;gBACvE,CAAC,CAAC,EAAE;aACL,CAAA;YACD,OAAO,MAAM,CAAA;QACf,CAAC;QAED;;;;;;;;;;;WAWG;QACH,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YACjC,oEAAoE;YACpE;;;;;;;;;;eAUG;YACH,MAAM,IAAI,GAAG,qBAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAA;YAC/D,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAA,2BAAW,EAAC,qBAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAC/E,IAAI,MAA0B,CAAA;YAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,qBAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,SAAS,CAAC,CAAA;oBACvF,IAAI,GAAG,IAAA,2BAAW,EAAC,GAAG,CAAC,CAAA;oBACvB,MAAM,GAAG,MAAM,CAAE,GAAW,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAA;gBACtD,CAAC;gBAAC,MAAM,CAAC;oBACP,oDAAoD;oBACpD,IAAI,GAAG,IAAI,CAAA;gBACb,CAAC;YACH,CAAC;YACD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;YAC3G,CAAC;YACD;;uEAE2D;YAC3D,MAAM,MAAM,GAAG,IAAA,0BAAW,EAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACtC,MAAM,IAAI,GAAU,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;YACvD,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAC3D,MAAM,KAAK,GAAG,QAAQ;iBACnB,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;iBACxB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAA,oBAAI,EAAC,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YAC/F,OAAO;gBACL,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,kDAAkD;gBAClD,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACjC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3B,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,QAAQ,CAAC,MAAM;gBACtB,MAAM,EAAE,IAAI;gBACZ,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvD,KAAK;gBACL,KAAK,EAAE,IAAA,wBAAQ,EAAC,KAAK,EAAE,IAAA,yBAAS,EAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;aACpD,CAAA;QACH,CAAC;QAED,wDAAwD;QACxD,MAAM,GAAG,GAAG,IAAA,kBAAE,EAAC,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;QACpD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACvD,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QACpD,OAAO;YACL,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,UAAU;YACjB,KAAK,EAAE,GAAG,CAAC,MAAM;YACjB,MAAM,EAAE,IAAI;YACZ,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACvD,GAAG,CAAC,GAAG,EAAE;gBACP;;;;;;mBAMG;gBACH,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAA;gBAC7C,MAAM,KAAK,GAAG,GAAG;qBACd,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;qBACxB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAA,oBAAI,EAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC/G,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAA,wBAAQ,EAAC,KAAK,EAAE,IAAA,yBAAS,EAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAA;YACjF,CAAC,CAAC,EAAE;SACL,CAAA;IACH,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,WAAgB,EAAE,QAAgB,EAAE,CAAM;QACtD,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,QAAQ,CAAA;QAChD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAS,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC1H,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;YAC5B,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,WAAW;gBAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,CAAA;QAC/D,CAAC;QACD;8CACsC;QACtC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QAChE,MAAM,GAAG,GAAQ,EAAE,CAAA;QACnB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACtE,OAAO,GAAG,CAAA;IACZ,CAAC;IAGD;;;;;;;;;;OAUG;IACK,WAAW,CAAC,IAAY,EAAE,KAAU,EAAE,MAAW;QACvD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAA;QACnF,MAAM,OAAO,GAA2B,KAAK,EAAE,cAAc,EAAE,OAAO,IAAI,EAAE,CAAA;QAC5E,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC,CAAA;QAC5C,iDAAiD;QACjD,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IAClD,CAAC;IAED;;;;;;;;;;OAUG;IACK,iBAAiB,CAAC,IAAY,EAAE,KAAU,EAAE,MAAW;QAC7D,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAA;QAC7E,MAAM,OAAO,GAA2B,KAAK,EAAE,cAAc,EAAE,OAAO,IAAI,EAAE,CAAA;QAC5E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;QAC1F,6DAA6D;QAC7D;qBACa;QACb,MAAM,KAAK,GAAG,uBAAS,CAAA;QACvB,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QAC/D,IAAI,GAAG;YAAE,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAA;QAC5C,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;aAClC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;aAChE,MAAM,CAAC,OAAO,CAAC,CAAA;QAClB,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IACpF,CAAC;IAED,yDAAyD;IACjD,OAAO,CAAC,IAAY,EAAE,CAAM;QAClC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAC7C,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAA;IACrE,CAAC;IAOK,AAAN,KAAK,CAAC,aAAa,CACE,UAAkB,EACxB,IAAY,EACV,MAAc,EACtB,OAAwB;QAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC3B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,4CAA4C,CAAC,CAAA;QAEtG,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAA;QAC3G,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QAEtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;QAC9B,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,QAAQ,GAAQ,IAAI,CAAA;QACxB,IAAI,UAAU,GAAQ,IAAI,CAAA;QAE1B;;;WAGG;QACH,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YACjC;;;;;eAKG;YACH,MAAM,QAAQ,GAAG,qBAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;YAC3D,IAAI,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAA,2BAAW,EAAC,qBAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YACnF,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,CAAC;oBACH,IAAI,GAAG,IAAA,2BAAW,EAAC,MAAM,qBAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;gBACpE,CAAC;gBAAC,MAAM,CAAC;oBACP,mDAAmD;gBACrD,CAAC;YACH,CAAC;YACD,mDAAmD;YACnD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAA,0BAAW,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YACpD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAA,oBAAI,EAAC,CAAC,EAAE,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YACnG;;;;;;;;eAQG;YACH,IAAI,IAAI,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAA;YAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;oBACL,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM;oBAC3C,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,EAAE;oBAC1N,QAAQ,EAAE,IAAI;oBACd,QAAQ,EAAE,IAAI;oBACd,YAAY,EAAE,IAAI;oBAClB;;;uBAGG;oBACH,eAAe,EAAE,aAAsB;oBACvC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ;oBACzG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,CAAC;oBAC5L,oEAAoE;oBACpE,eAAe,EAAE,IAAA,uCAAiB,EAAC,IAAI,CAAC;oBACxC;;;;uBAIG;oBACH,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE;iBACjE,CAAA;YACH,CAAC;YACD,MAAM,KAAK,GAAG,IAAA,wBAAQ,EAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAA,yBAAS,EAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAA;YACpF,OAAO;gBACL,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM;gBAC3C,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,EAAE;gBAC1N;;;;mBAIG;gBACH,QAAQ,EAAE,IAAI;gBACd,QAAQ,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,KAAK,CAAC;gBAC/D,YAAY,EAAE,IAAI;gBAClB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACrC,qDAAqD;gBACrD,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBAC7C,SAAS,EAAE,QAAQ;gBACnB,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,CAAC;gBACxJ,oEAAoE;gBACpE,eAAe,EAAE,IAAA,uCAAiB,EAAC,IAAI,CAAC;gBAC1C,KAAK,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC;gBAC9D,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvD,KAAK;gBACL,UAAU,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE;aACtD,CAAA;QACH,CAAC;QAED,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,KAAK,GAAQ,MAAM,IAAA,qBAAa,EAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;gBACzD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAS,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAS;aAC5G,CAAC,CAAA;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;gBACtF,QAAQ,GAAG,IAAI,CAAA;gBACf,mDAAmD;gBACnD,UAAU,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;YACvD,CAAC;QACH,CAAC;QAED;;;WAGG;QACH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,IAAA,kBAAE,EAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;YAChC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YACvD,kDAAkD;YAClD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAA,oBAAI,EAAC,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACpH,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;gBAC3F,UAAU,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;YACpC,CAAC;QACH,CAAC;QAED;sDAC8C;QAC9C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACtE,MAAM,QAAQ,GAAG,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;QACpD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAA;QAEvC,uDAAuD;QACvD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAE9D;;;;WAIG;QACH,MAAM,SAAS,GAA2B,EAAE,CAAA;QAC5C,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,uBAAQ,CAAC;iBACxC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAS,EAAS,EAAE,CAAC;iBACpG,KAAK,CAAC,GAAG,EAAE,CAAC,EAAW,CAAC,CAAA;YAC3B,KAAK,MAAM,CAAC,IAAI,KAAc;gBAAE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,IAAI;oBAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAA;QACxF,CAAC;QAED,OAAO;YACL,UAAU;YACV,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM;YACN,yCAAyC;YACzC,QAAQ,EAAE;gBACR,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI;gBACzC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;gBAC/B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;gBACjC;;;mBAGG;gBACH,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI;gBACrC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI;aACtC;YACD;;;;;;eAMG;YACH,SAAS,EACP,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAA,kBAAE,EAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAA,kBAAE,EAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI;YACzG,kEAAkE;YAClE,QAAQ;YACR,QAAQ;YACR;;;eAGG;YACH,GAAG,CAAC,OAAO,IAAI,IAAI;gBACjB,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;gBAClH,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;YACtC,8CAA8C;YAC9C,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,CAAC;YACpJ;;;;eAIG;YACH,eAAe,EAAE,IAAA,uCAAiB,EAAC,IAAI,CAAC;YACxC,KAAK;YACL;;;;;eAKG;YACH,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;YAC5C;;;;;;eAMG;YACH,GAAG,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YACzE;;;;;eAKG;YACH,KAAK,EAAE,IAAA,wBAAQ,EACb,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAC3E,EAAE,GAAG,IAAA,yBAAS,EAAC,KAAK,CAAC,EAAE,GAAG,SAAS,EAAE,CACtC;YACD,UAAU;SACX,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACK,SAAS,CAAC,KAAU;QAC1B,MAAM,GAAG,GAA2B,EAAE,CAAA;QACtC,KAAK,MAAM,IAAI,IAAI,SAAkB,EAAE,CAAC;YACtC,qDAAqD;YACrD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,UAAU;gBAAE,SAAQ;YAClD,MAAM,GAAG,GAAG,IAAA,kBAAE,EAAC,KAAK,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YACxD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,MAAM,EAAE,GAAG,IAAA,oBAAI,EAAC,CAAC,CAAC,CAAA;gBAClB,IAAI,CAAC,EAAE,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,SAAQ;gBAC1C,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,CAAA;gBAChD,iDAAiD;gBACjD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBAAE,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAA;YACrF,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED;;;;;OAKG;IACK,QAAQ,CAAC,IAAW,EAAE,KAA6B;QACzD,MAAM,GAAG,GAA2B,EAAE,CAAA;QACtC,MAAM,IAAI,GAAG,CAAC,CAAM,EAAE,KAAa,EAAQ,EAAE;YAC3C,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC;gBAAE,OAAM;YAClC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAAC,IAAI,KAAK,CAAC,CAAC,CAAC;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAAC,OAAM;YAAC,CAAC;YACtE,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAC,KAAK,MAAM,CAAC,IAAI,CAAC;oBAAE,IAAI,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;gBAAC,OAAM;YAAC,CAAC;YACvE,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;oBAAE,IAAI,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;QACjF,CAAC,CAAA;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YAAC,IAAI,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAAC,IAAI,OAAO,CAAC,EAAE,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAAC,CAAC;QACxH,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,kEAAkE;IAC1D,WAAW,CAAC,KAAU;QAC5B,MAAM,GAAG,GAA2B,EAAE,CAAA;QACtC,KAAK,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,cAAc,EAAE,iBAAiB,CAAC;YAC3F,wEAAwE;YACxE,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAU;gBAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,CAAC;oBAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,CAAA;QAC5H,OAAO,GAAG,CAAA;IACZ,CAAC;IAED;;;OAGG;IACH;;;;;;;;;;;;;OAaG;IACK,KAAK,CAAC,qBAAqB,CACjC,QAAgB,EAChB,UAAkB,EAClB,IAAY,EACZ,MAAc;QAEd,IAAI,IAAI,KAAK,YAAY;YAAE,OAAO,EAAE,CAAA;QACpC,IAAI,CAAC,qBAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC;YAAE,OAAO,EAAE,CAAA;QAC1D,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAA;QACvB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,CAAA;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACpH,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,qBAAU,CAAC,oBAAoB,CAChD,QAAQ,EACR,EAAE,UAAU,EAAE,EACd,CAAC,EACD,MAAM,EACN,EAAE,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAC3D,CAAA;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,EAAE,MAAM,CAAA;YACzE,MAAM,KAAK,GAAG,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,CAAA;YAC5E,IAAI,CAAC,KAAK;gBAAE,OAAO,EAAE,CAAA;YACrB,uDAAuD;YACvD,OAAO,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,GAAG,KAAK,EAAE,EAAE,CAAA;QACnG,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;YAC/D,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACK,KAAK,CAAC,UAAU,CACtB,QAAgB,EAChB,UAAkB,EAClB,IAAY,EACZ,MAAc;QAEd,MAAM,IAAI,GAAG,qBAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;QACvD,IAAI,KAAK,GAAQ,IAAI,CAAA;QACrB,IAAI,MAA0B,CAAA;QAC9B,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,GAAG,IAAA,2BAAW,EAAC,qBAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;QAChE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,qBAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;gBAC1D,MAAM,GAAG,MAAM,CAAE,GAAW,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAA;gBACpD;;;;mBAIG;gBACH,IAAI,MAAM,IAAI,IAAI;oBAAE,OAAO,EAAE,OAAO,EAAE,aAAsB,EAAE,CAAA;gBAC9D,KAAK,GAAG,IAAA,2BAAW,EAAC,GAAG,CAAC,CAAA;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,OAAO,EAAE,aAAsB,EAAE,CAAA;YAC5C,CAAC;QACH,CAAC;QACD,8DAA8D;QAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAA,0BAAW,EAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC5E;;;;WAIG;QACH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,cAAuB,EAAE,CAAA;QACvE,yDAAyD;QACzD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAA,oBAAI,EAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,CAAA;QACzE,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,OAAO,EAAE,cAAuB,EAAE,CAAA;QACvD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IAC5G,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,OAAO,CACnB,QAAgB,EAChB,IAAS,EACT,IAAY,EACZ,MAAc;IACd;;;OAGG;IACH,KAAW;QAEX,MAAM,YAAY,GAAG,EAAE,CAAA;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;QAE9B;;;WAGG;QACH,IAAI,aAAkB,CAAA;QACtB,IAAI,cAAc,GAAG,KAAK,CAAA;QAC1B,MAAM,cAAc,GAAG,KAAK,EAAE,CAAS,EAAkB,EAAE;YACzD,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,cAAc,GAAG,IAAI,CAAA;gBACrB,IAAI,CAAC;oBACH,aAAa,GAAG,qBAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC;wBAC7D,CAAC,CAAC,IAAA,2BAAW,EAAC,qBAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;wBAC7D,CAAC,CAAC,IAAA,2BAAW,EAAC,MAAM,qBAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAA;gBACtE,CAAC;gBAAC,MAAM,CAAC;oBACP,aAAa,GAAG,IAAI,CAAA;gBACtB,CAAC;YACH,CAAC;YACD,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAE,aAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAC1D,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAClC,CAAC,CAAA;QAED;;;;;;;;;WASG;QACH,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;QACnF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAA,kBAAE,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3E,MAAM,IAAI,GAAG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAA,oBAAI,EAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAA;QAElE;;;;;;;;WAQG;QACH,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAA;QACjD,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,KAAK,kBAAkB,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;gBAAE,SAAQ;YACpF,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YACrC,MAAM,GAAG,GAAG,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAA,kBAAE,EAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAC3H,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YACvD,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAA,oBAAI,EAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAClG,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAU,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAA;QAE7E,6CAA6C;QAC7C,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE;YAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YACtD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACzD,OAAO;gBACL,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ;gBACtB;sEACsD;gBACtD,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB;;;;;;;;mBAQG;gBACH,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;gBACjB,SAAS,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACvC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;gBAC/B,KAAK,EAAE,GAAG,CAAC,MAAM;aAClB,CAAA;QACH,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAM,EAAE,EAAE;YACpB,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,KAAK,kBAAkB;gBAAE,OAAO,CAAC,CAAC,CAAC,CAAA;YACrD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAChG,MAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;YACrD,MAAM,IAAI,GAAG,CAAC,MAAW,EAAE,GAAa,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;YAC7I,MAAM,KAAK,GAAG;gBACZ,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClG,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACvH,CAAA;YACD,mDAAmD;YACnD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACnC,CAAC,CAAC,CAAA;QAEF;;;;;;;WAOG;QACH,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM;gBAAE,SAAQ;YAC5D,MAAM,GAAG,GAAG,MAAM,IAAA,sCAAe,EAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,IAAA,iBAAQ,EAAC,CAAC,CAAC,CAAC,CAAA;YACtH,IAAI,GAAG,CAAC,IAAI;gBAAG,CAAS,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAA;;gBAClC,CAAS,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAA;QAC7C,CAAC;QAED;;;;;;;;;WASG;QAEH,8DAA8D;QAC9D,MAAM,QAAQ,GAAU,EAAE,CAAA;QAC1B;;;WAGG;QACH,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAA,uCAAgB,EAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,IAAA,iBAAQ,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACrG,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;YACjC,IAAI,CAAC,QAAQ;gBAAE,SAAQ;YACvB,MAAM,IAAI,GAAa,EAAE,CAAA;YACzB;;;;eAIG;YACH,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YACtE,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,GAAG,CAAC,MAAM,CAAC,CAAA;gBACtC;;;;;;;mBAOG;gBACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAA;gBACnF,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBACxD,MAAM,IAAI,GAAU,MAAM,IAAI,CAAC,IAAI,CAAC;oBAClC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAS,EAAE;oBAC5E,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3D,IAAI,EAAE,IAAI;iBACX,CAAC,CAAA;gBACF,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBACrB,8CAA8C;oBAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;oBACnD,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;wBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;gBACpD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN;;;;;;;;;mBASG;gBACH,MAAM,GAAG,GACP,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAA,kBAAE,EAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;gBAC/F,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;gBACvD,KAAK,MAAM,CAAC,IAAI,GAAG;oBAAE,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;wBAClF,MAAM,EAAE,GAAG,IAAA,oBAAI,EAAC,CAAC,CAAC,CAAA;wBAClB,IAAI,EAAE;4BAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;oBACvB,CAAC;YACH,CAAC;YACD;;;;;;;;;;;eAWG;YACH,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;gBACjB,SAAS,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACvC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;gBAChC,KAAK,EAAE,IAAI,CAAC,MAAM;aACnB,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAA;IAC1B,CAAC;IAED;;;OAGG;IACK,UAAU,CAAC,GAAQ,EAAE,KAAa;QACxC,IAAI,GAAG,GAAU,CAAC,GAAG,CAAC,CAAA;QACtB,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAClC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;YAC5C,MAAM,IAAI,GAAU,EAAE,CAAA;YACtB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;gBACpB,IAAI,CAAC,IAAI,IAAI;oBAAE,SAAQ;gBACvB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;gBAChB,IAAI,CAAC,IAAI,IAAI;oBAAE,SAAQ;gBACvB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;;oBAChC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACnB,CAAC;YACD,GAAG,GAAG,IAAI,CAAA;QACZ,CAAC;QACD,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAA,oBAAI,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAA;IACtG,CAAC;IAED;;;;;OAKG;IACK,kBAAkB,CAAC,MAAW,EAAE,KAAa,EAAE,UAAkB;QACvE,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACpD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QACrB,IAAI,CAAC,IAAI,IAAI;YAAE,OAAO,EAAE,CAAA;QACxB,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC,CAAC,CAAA;QACrC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAA,oBAAI,EAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACpG,+DAA+D;QAC/D,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAA;QAC9C,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAA,oBAAI,EAAC,CAAC,CAAC,CAAA;QACtC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACjC,CAAC;CACF,CAAA;AAl5BY,gDAAkB;AAMvB;IALL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE;QAC9B,QAAQ,EAAE,IAAI;QACd,WAAW,EACT,qMAAqM;KACxM,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IACjB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IACX,mBAAA,IAAA,kBAAG,GAAE,CAAA;IACL,mBAAA,IAAA,kBAAG,EAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACjC,mBAAA,IAAA,kBAAG,EAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9C,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAO7C,mBAAA,IAAA,kBAAG,EAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;;;;2DA+JtC;AAoFK;IALL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE;QAC9B,QAAQ,EAAE,IAAI;QACd,WAAW,EACT,oPAAoP;KACvP,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IACjB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IACX,mBAAA,IAAA,kBAAG,EAAC,QAAQ,CAAC,CAAA;IACb,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;uDA2NP;6BAreU,kBAAkB;IAF9B,IAAA,uBAAQ,GAAE;IACV,IAAA,4BAAa,EAAC,qBAAa,CAAC;GAChB,kBAAkB,CAk5B9B","sourcesContent":["import type { ReadBasis } from '@operato/ops-contract'\n\nimport { twinWarn } from '../../engine/log.js'\nimport { Arg, Ctx, Int, Query, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { ScalarObject, SpeakRefusals, getRepository } from '@things-factory/shell'\n\nimport { itemRefOf } from './item-ref.js'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { unwrapState } from '../../engine/warm-start.js'\nimport { propertyEffectsOf } from '../../engine/property-effects.js'\n/* 축이 사는 자리를 읽는 **한 곳** — 카드(`twin-model-query`)와 같은 규칙을 쓴다. */\nimport { axisValueOf } from '@things-factory/headless-twin/dist-shared/axis-read.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinLocation } from './twin-location.js'\nimport { TwinEquipment } from './twin-equipment.js'\nimport { TwinOperation } from './twin-operation.js'\nimport { TwinArea } from '../twin-space/twin-area.js'\nimport { at, idOf, nameIndex, namesFor } from './name-index.js'\n\n/* 커널 런타임 로드 — 축·관계·속성 선언의 SSOT. 이 파일은 도메인 모양을 알지 않는다. */\nconst { TWIN_AXES, TWIN_RELATIONS, axisInfo, axisSource, documentPath, isCacheableTense, relationsFrom, relationsTo, propertiesOf, splitRelationIds, tenseOf } =\n require('@operato/ops-contract')\n\n/**\n * 목록의 답 — **근거는 계약이 닫아 둔 다섯 중 하나다**(`READ_BASIS`).\n *\n * 2026-09-18 판정(ADR-0075 결정 3 을 코드에 대어 본 결과): 이 문이 `'rows-scanned'` 를 내고 있었다.\n * 그것은 출처가 아니라 **우리가 어떻게 셌나**이고, 목록 소비자가 근거로 갈래를 나눌 때 계약에 없는\n * 값을 만나게 된다. 출처는 `rows` 이고, 훑어 걸렀다는 사실은 `scanned` · `truncated` 가 말한다.\n * 여기에 칸을 묶어 두면 계약 밖의 값이 다시 생길 때 타입 검사가 잡는다.\n */\ntype AxisListAnswer = {\n axis: string\n label: string\n basis: ReadBasis\n total: number | null\n offset: number\n /** 훑어 센 경우에만 — 몇 줄을 읽었나, 상한에서 잘렸나. */\n scanned?: number\n truncated?: boolean\n [key: string]: unknown\n}\nimport { externalIncoming, resolveExternal } from './external-resolver.js'\n\n/**\n * 축 → 그 축이 이미 **행으로 옮겨졌나**, 그리고 행의 어느 컬럼이 id 인가.\n *\n * 옮겨진 축은 **DB 가 페이징하고 센다.** 아직인 축은 문서 배열을 읽어야 하고, 그 차이를 응답이\n * `basis` 로 밝힌다 — 밝히지 않으면 \"이 축은 검색이 되는데 저 축은 왜 느린가\" 를 아무도 설명할 수 없다.\n */\nconst ROW_BACKED: Record<string, { entity: any; idColumn: string; order: any }> = {\n locations: { entity: TwinLocation, idColumn: 'locationId', order: { locationId: 'ASC' } },\n equipment: { entity: TwinEquipment, idColumn: 'equipmentId', order: { equipmentId: 'ASC' } },\n operations: { entity: TwinOperation, idColumn: 'operationKey', order: { seq: 'ASC' } }\n}\n\n/*\n * `productionSpec.binding` 의 키가 사는 축 — 자재가 둘로 갈려 있다.\n *\n * materials productionSpec.definition.materials 레시피의 투입 자재\n * materialDefinitions materialDefinitions 마스터 품목 목록\n *\n * 예전에는 `materials` 하나만 봤다. 커넥터에 따라 `binding` 키가 어느 축의 id 인지 달라서, MES 연결\n * 둘은 품목이 자기 GS1 참조를 한 건도 답하지 못했다. 오류는 안 나고 칸이 비어서 나온다.\n *\n * 실측(2026-09-06, 인티그레이션 레인이 찾음):\n *\n * 트윈 binding def.materials 맞음 materialDefinitions 맞음\n * mes-miratek 106 0 106\n * mes-line-a 21 0 21\n * operato-chef-v1-pocheon 2789 1789 0\n * rosarito-mes 20 20 0\n *\n * **두 축이 동시에 맞는 트윈은 없다**(양쪽 id 에 다 있으면서 binding 키인 것 0개). 그래서 두 축에\n * 다 걸어도 어느 쪽을 붙일지 모호해지지 않는다. 조회가 판정한다 — `binding[id]` 는 키가 아닌 축에서\n * 그냥 없다.\n *\n * 두 축을 한 이름으로 합치지 않는다. 레시피 투입 자재와 마스터 품목은 서로 다른 것이고, 합치면\n * 둘 다 있는 트윈(chef)에서 어느 쪽 목록인지 알 수 없게 된다.\n */\nconst BINDING_AXES = new Set(['materials', 'materialDefinitions'])\n\n\n/** 검색 — 항목의 값 어디든 걸리면 맞는 것으로 본다. 축마다 검색 컬럼을 정해 두면 축이 늘 때마다 여기를 고쳐야 한다. */\nfunction matches(o: any, q: string): boolean {\n if (!q) return true\n const needle = q.toLowerCase()\n const walk = (v: any, depth: number): boolean => {\n if (v == null || depth > 3) return false\n if (typeof v === 'string' || typeof v === 'number') return String(v).toLowerCase().includes(needle)\n if (Array.isArray(v)) return v.some(x => walk(x, depth + 1))\n if (typeof v === 'object') return Object.values(v).some(x => walk(x, depth + 1))\n return false\n }\n return walk(o, 0)\n}\n\n/**\n * 항목 조회 — **개념 안의 목록**(③)과 **항목 하나의 상세**(④).\n *\n * ── 이 파일이 도메인을 알지 않는다 ─────────────────────────────────────────────\n * 어느 축이 있고 무엇을 가리키는지는 **커널 카탈로그가 선언**한다(`TWIN_AXES`·`TWIN_RELATIONS`).\n * 그래서 야드의 도크도어나 에너지의 계량기가 늘어도 여기 손댈 것이 없다(ADR-0031). 이 파일에\n * 도메인 이름이 한 번도 나오지 않는 것이 그 증거다.\n *\n * ── 알리지 않고 자르지 않는다 ──────────────────────────────────────────────────────\n * 목록은 항상 **총 건수**와 함께 온다. 그리고 어떻게 셌는지(`basis`)를 밝힌다 — 행이면 DB 가\n * 페이징했고, 문서면 서버가 문서를 통째로 읽어 잘라 냈다. 후자는 규모에서 한계가 되므로 그 사실이\n * 화면에 드러나야 이주 압력이 살아 있다.\n */\n@Resolver()\n@UseMiddleware(SpeakRefusals)\nexport class TwinModelItemQuery {\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'Page through the items of one standard concept in a twin. Always returns the total and how it was counted (rows = the database paged it, document = the server read the whole document and sliced).'\n })\n async twinModelEntities(\n @Arg('instanceId') instanceId: string,\n @Arg('axis') axis: string,\n @Ctx() context: ResolverContext,\n @Arg('search', { nullable: true }) search?: string,\n @Arg('offset', type => Int, { nullable: true }) offset?: number,\n @Arg('limit', type => Int, { nullable: true }) limit?: number,\n /**\n * 어느 시각의 사실인가 — **관측 축에만 뜻이 있다.**\n *\n * 선언 축은 시간축이 없다(그 시점의 선언은 구조 리비전이 답한다). 그래서 문서 축에 이 값을 주면\n * 쓰지 않는다 — 무시했다는 사실은 응답의 `basis` 가 말한다(`document`).\n */\n @Arg('untilTime', { nullable: true }) untilTime?: string\n ): Promise<any | null> {\n const domainId = context.state.domain.id\n const info = axisInfo(axis)\n /* 모르는 축은 **거절한다.** 빈 목록으로 답하면 \"이 개념은 비어 있다\" 로 읽히고, 오타 하나가\n \"우리 트윈에는 그게 없다\" 는 결론으로 굳는다. */\n if (!info) throw new Error(`unknown concept axis: \"${axis}\" — the kernel catalog does not declare it`)\n\n const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!inst) return null\n\n const take = Math.min(Math.max(limit ?? 50, 1), 200)\n const skip = Math.max(offset ?? 0, 0)\n const q = (search ?? '').trim()\n /* 시각 커서는 시간축을 가진 축만 쓴다(`historical`) — 선언 축에서는 뜻이 없다. */\n const at_ = axisInfo(axis)?.historical ? untilTime || null : null\n const row = ROW_BACKED[axis]\n\n if (row && !q) {\n /* 검색어가 없으면 **DB 가 페이징한다** — 이것이 규모에서 유일하게 성립하는 길이다. */\n const repo = getRepository(row.entity)\n const where = { domain: { id: domainId } as any, instance: { id: inst.id } as any }\n const [rows, total] = await repo.findAndCount({ where, order: row.order, skip, take })\n const answer: AxisListAnswer = {\n axis,\n label: info.label,\n basis: 'rows',\n total,\n offset: skip,\n /* 목록도 등급 이름을 쓴다 — 목록 칸에 `assembler-op` 이 그대로 서면 목록이 제 일을 못 한다. */\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n items: rows.map((r: any) => this.rowItem(axis, r))\n }\n return answer\n }\n\n if (row && q) {\n /*\n * 검색은 아직 DB 로 내리지 않았다. **그 사실을 밝힌다** — 흉내로 덮으면 규모가 오는 날까지\n * 아무도 이 한계를 모른다. 훑는 건수를 상한으로 막고, 상한에 닿았으면 잘렸다고 말한다\n * (알리지 않고 자르지 않는다).\n *\n * 말하는 자리는 `scanned` · `truncated` 다. 근거(`basis`)는 그대로 `rows` 이고 — 값이 어디서\n * 왔는지는 훑었든 DB 가 골랐든 같은 행이다 — 계약이 닫아 둔 다섯 밖으로 나가지 않는다.\n */\n const SCAN_MAX = 5000\n const repo = getRepository(row.entity)\n const where = { domain: { id: domainId } as any, instance: { id: inst.id } as any }\n const rows = await repo.find({ where, order: row.order, take: SCAN_MAX })\n const hit = rows.filter((r: any) => matches(this.rowItem(axis, r), q))\n const answer: AxisListAnswer = {\n axis,\n label: info.label,\n basis: 'rows',\n total: hit.length,\n offset: skip,\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n scanned: rows.length,\n truncated: rows.length >= SCAN_MAX,\n ...(() => {\n const items = hit.slice(skip, skip + take).map((r: any) => this.rowItem(axis, r))\n return { items, names: namesFor(items, nameIndex(inst.model ?? {})) }\n })()\n }\n return answer\n }\n\n /*\n * **선언이 아닌 축** — 일정·실적(ISA-95 Part 4). 이 축의 집은 트윈 모델이 아니라 **커널 상태**다\n * (커널이 `source: 'state'` 로 선언한다).\n *\n * ── 멈춘 트윈은 0 이 아니다 ──────────────────────────────────────────────────\n * 커널이 동작하지 않으면 관측이 **없다**. 그때 빈 목록을 내면 \"작업이 0 건\" 으로 읽히고, 그건\n * 거짓이다 — 이 화면이 관측 열에서 내내 지켜 온 구분(관측 없음 ≠ 0)을 목록에서도 지킨다.\n *\n * ── 규모 ────────────────────────────────────────────────────────────────────\n * 상태 배열은 지금의 사실만 담아 유한하다(진행 중 오더·작업). 과거까지 세는 것은 저널의 일이고\n * 커서 페이징이 필요하다 — 그건 `historical` 축의 후속이며, 여기서 흉내내지 않는다.\n */\n if (axisSource(axis) === 'state') {\n /* 봉투를 벗긴다 — `{revision, state}` 안에 축이 있다. 그리고 **실행 중일 때만** 관측이다. */\n /*\n * **라이브는 권위, 히스토리는 파생.**\n *\n * 지금 도는 커널의 상태가 이 축의 진실이다. 그런데 커널이 멈춰 있거나 사용자가 **과거 시각**을\n * 물으면 답할 것이 없어진다 — 그때 저널을 그 시점까지 계산해 답한다(`recover`). 둘은 같은 모양이지만\n * **성질이 다르므로 `basis` 로 구별해 낸다**: 파생을 권위처럼 내면 다시 계산한 값을 보고 \"지금 이렇다\"\n * 로 읽게 된다.\n *\n * 규모: 계산 비용은 이벤트 수에 비례한다. 감추지 않고 **어느 리비전까지 계산했는지 함께 낸다** —\n * 이 화면이 목록마다 `basis` 를 밝혀 온 규율 그대로다.\n */\n const live = TwinEngine.isRunning(domainId, instanceId) && !at_\n let snap = live ? unwrapState(TwinEngine.snapshot(domainId, instanceId)) : null\n let folded: number | undefined\n if (!snap) {\n try {\n const rec = await TwinEngine.recover(domainId, instanceId, undefined, at_ ?? undefined)\n snap = unwrapState(rec)\n folded = Number((rec as any)?.revision) || undefined\n } catch {\n /* 다시 계산할 것이 없다(모델도 저널도 없다) — 없는 것을 0 으로 메우지 않는다. */\n snap = null\n }\n }\n if (!snap) {\n return { axis, label: info.label, basis: 'state', total: null, observed: false, offset: skip, items: [] }\n }\n /* 축이 사는 자리는 **커널 선언이 말한다**(`path`) — 축 이름으로만 읽으면 중첩된 축이 언제나\n 비어 보인다. 카드는 `axisValueOf` 로 읽는데 여기가 그 규칙을 지나지 않아, 「42」를 센 개념의\n 목록이 「0건」으로 나왔다(에너지의 수요 구간). 규칙의 집은 `axisValueOf` 하나다. */\n const bucket = axisValueOf(snap, info)\n const list: any[] = Array.isArray(bucket) ? bucket : []\n const hitState = q ? list.filter(o => matches(o, q)) : list\n const items = hitState\n .slice(skip, skip + take)\n .map(o => ({ id: idOf(o, info), fields: this.withOrderMaterial(axis, inst.model ?? {}, o) }))\n return {\n axis,\n label: info.label,\n /* 권위(라이브)와 파생(저널)을 구별해 낸다 — 화면이 이 낱말을 그대로 보인다. */\n basis: live ? 'state' : 'journal',\n ...(folded != null ? { foldedRevision: folded } : {}),\n ...(at_ ? { at: at_ } : {}),\n observed: true,\n total: hitState.length,\n offset: skip,\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n items,\n names: namesFor(items, nameIndex(inst.model ?? {}))\n }\n }\n\n /* 아직 문서 안에 사는 축 — 문서를 읽어 자른다. 규모 한계를 `basis` 로 드러낸다. */\n const raw = at(inst.model ?? {}, documentPath(axis))\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n const hit = q ? all.filter(o => matches(o, q)) : all\n return {\n axis,\n label: info.label,\n basis: 'document',\n total: hit.length,\n offset: skip,\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n ...(() => {\n /*\n * **한 벌뿐인 선언은 축 이름이 곧 식별자다.**\n *\n * `productionSpec` 처럼 문서에 객체 하나로 있는 축은 `id`/`key` 가 없다. 그것을 그대로\n * 목록에 실으면 \"식별자 없음 — 가리킬 수 없습니다\" 라는 줄 하나가 뜨고, 정작 그 선언을\n * 열어 볼 방법이 없다. 하나뿐인 것은 축 자신으로 가리킨다(상세도 같은 규칙으로 찾는다).\n */\n const singular = !Array.isArray(raw) && !!raw\n const items = hit\n .slice(skip, skip + take)\n .map(o => ({ id: idOf(o) ?? (singular ? axis : null), fields: this.withBinding(axis, inst.model ?? {}, o) }))\n return { items, names: namesFor(items, nameIndex(inst.model ?? {})), singular }\n })()\n }\n }\n\n /**\n * 행에서 **내부 배관을 걷어낸다** — 사용자가 볼 것은 현장의 사실이지 우리 스키마가 아니다.\n *\n * 손으로 목록을 두지 않는다. 관계와 그 조인 컬럼이 무엇인지는 **엔티티 메타데이터**가 알고,\n * 표로 두면 컬럼이 늘 때마다 여기를 고쳐야 하며 잊으면 그대로 새어 나간다 — 실제로\n * `domainId`·`instanceRowId` 같은 내부 UUID 가 화면까지 갔다.\n *\n * 식별자도 뺀다: 항목 자신의 id 는 이미 `id`/`itemId` 로 나가므로 두 번 보일 이유가 없다.\n */\n private strip(entityClass: any, idColumn: string, r: any): any {\n const meta = getRepository(entityClass).metadata\n const hidden = new Set<string>(['id', 'createdAt', 'updatedAt', 'creator', 'updater', 'creatorId', 'updaterId', idColumn])\n for (const rel of meta.relations) {\n hidden.add(rel.propertyName)\n for (const jc of rel.joinColumns) hidden.add(jc.propertyName)\n }\n /* `@RelationId` 로 승격한 내부 UUID(`domainId`·`instanceRowId`·`areaRowId`) — 관계 목록에는 없고\n 여기에만 있다. 이 한 줄이 없어서 실제로 화면까지 샜다. */\n for (const rid of meta.relationIds) hidden.add(rid.propertyName)\n const out: any = {}\n for (const [k, v] of Object.entries(r)) if (!hidden.has(k)) out[k] = v\n return out\n }\n\n\n /**\n * **자재는 자기 GS1 품목 참조를 안다** — 읽기 경계에서 이어 붙인다.\n *\n * 정본은 `productionSpec.binding` 하나다(커널이 EPC↔자재를 그 표로 잇는다). 그런데 그 사실은\n * **자재마다의 속성**이다: 이 자재가 GS1 품목 몇 번인가, 그래서 개체로 추적되는가(= 계보를 비교할\n * 수 있는가). 자재 목록에 그것이 없으면 자재는 자기 정체를 모르고, 사용자는 그 사실을 딴 축에서\n * 찾아야 한다.\n *\n * 그래서 **저장은 한 곳(binding), 표시는 읽는 자리에서 이어 붙임** — 이름표와 같은 방식이다.\n * 값을 복제해 두면 두 곳이 어긋나고, 어긋난 쪽을 아무도 모른다.\n */\n private withBinding(axis: string, model: any, fields: any): any {\n if (!BINDING_AXES.has(axis) || !fields || typeof fields !== 'object') return fields\n const binding: Record<string, string> = model?.productionSpec?.binding ?? {}\n const ref = binding[fields.key ?? fields.id]\n /* 없으면 키를 만들지 않는다 — 빈 값이 있는 것과 선언되지 않은 것은 다르다. */\n return ref ? { ...fields, gs1Ref: ref } : fields\n }\n\n /**\n * **오더가 무엇을 만드나** — GS1 품목 참조를 자재로 다시 계산해 붙인다.\n *\n * 커널의 오더는 품목을 GS1 으로 말한다(`urn:epc:idpat:sgtin:0614141.078101.*`). 사람에게 그 문자열은\n * 아무 뜻이 없고, 그 품목의 이름은 **자재 선언**이 갖고 있다. 둘을 잇는 것은 `productionSpec.binding`\n * (자재 키 → 품목 참조)이므로 **역방향으로 다시 계산한다.**\n *\n * 정본은 그대로 둔다: `gtin` 은 커널이 말한 값이고, 여기서 더하는 것은 **자재 키 하나**다(그 이름은\n * 이름표가 붙인다 — 값을 복제하지 않는다). 다시 계산하지 못하면 아무것도 더하지 않는다: 짐작으로 이으면\n * \"이 오더는 저것을 만든다\" 는 거짓이 되고, 그건 모르는 것보다 나쁘다.\n */\n private withOrderMaterial(axis: string, model: any, fields: any): any {\n if (axis !== 'orders' || !fields || typeof fields !== 'object') return fields\n const binding: Record<string, string> = model?.productionSpec?.binding ?? {}\n const refToMaterial = new Map(Object.entries(binding).map(([mat, r]) => [String(r), mat]))\n /* 단일 품목 작업지시는 `gtin`, 여러 품목이면 라인마다 말한다 — 첫 라인으로 대표하지 않는다. */\n /* 정체성 모양은 하나가 아니다 — 규칙의 집은 `item-ref` 하나다(웹 URI 원본에서 이 자리가 언제나\n 빈칸이었다). */\n const refOf = itemRefOf\n const mat = refToMaterial.get(String(refOf(fields.gtin) ?? ''))\n if (mat) return { ...fields, material: mat }\n const lineMats = (fields.lines ?? [])\n .map((l: any) => refToMaterial.get(String(refOf(l?.gtin) ?? '')))\n .filter(Boolean)\n return lineMats.length ? { ...fields, materials: [...new Set(lineMats)] } : fields\n }\n\n /** 행 하나 → 목록 항목. 컬럼 이름을 화면이 알지 않아도 되게 `id` + 나머지로 낸다. */\n private rowItem(axis: string, r: any): any {\n const { entity, idColumn } = ROW_BACKED[axis]\n return { id: r[idColumn], fields: this.strip(entity, idColumn, r) }\n }\n\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'One item of a standard concept: what the source declared, what the twin observed, what it links to and is linked from (declared relations, both directions), and where it came from. Never invents a value for a field the source did not provide.'\n })\n async twinModelItem(\n @Arg('instanceId') instanceId: string,\n @Arg('axis') axis: string,\n @Arg('itemId') itemId: string,\n @Ctx() context: ResolverContext\n ): Promise<any | null> {\n const domainId = context.state.domain.id\n const info = axisInfo(axis)\n if (!info) throw new Error(`unknown concept axis: \"${axis}\" — the kernel catalog does not declare it`)\n\n const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!inst) return null\n\n const model = inst.model ?? {}\n const row = ROW_BACKED[axis]\n let declared: any = null\n let provenance: any = null\n\n /*\n * **관측 축의 상세** — 일정·실적은 상태에서 찾는다. 커널이 멈춰 있으면 항목이 아니라 **모른다**를\n * 낸다(그 트윈에 그 오더가 없다는 뜻이 아니다 — 지금 관측이 없다는 뜻이다).\n */\n if (axisSource(axis) === 'state') {\n /*\n * 동작하지 않으면 **목록과 같은 길로 저널을 계산한다.**\n *\n * 목록만 계산하고 상세는 안 계산했더니, 목록에는 472건이 보이는데 그 줄을 열면 \"자기 속성이 없습니다\"\n * 가 나왔다 — 한 화면에서 두 답이 갈리면 어느 쪽이 맞는지 사용자가 알 수 없다.\n */\n const liveItem = TwinEngine.isRunning(domainId, instanceId)\n let snap = liveItem ? unwrapState(TwinEngine.snapshot(domainId, instanceId)) : null\n if (!snap) {\n try {\n snap = unwrapState(await TwinEngine.recover(domainId, instanceId))\n } catch {\n /* 다시 계산할 것이 없다 — 아래에서 \"모른다\" 를 낸다(0 으로 메우지 않는다). */\n }\n }\n /* 같은 규칙 — 축 이름이 아니라 선언된 자리에서 읽는다(§axisValueOf). */\n const bucket = snap ? axisValueOf(snap, info) : null\n const found = Array.isArray(bucket) ? bucket.find((o: any) => idOf(o, info) === itemId) : undefined\n /*\n * **상태를 읽었는데 그 개체가 없으면, 그런 개체가 없는 것이다** (2026-09-18).\n *\n * 이 갈래가 `!snap || !found` 하나였다. 그래서 없는 식별자로 물어도 「트윈이 실제로 본 것입니다」\n * 라고 적힌 패널이 돌아왔다 — 화면은 그것을 그려서, 있지도 않은 개체가 값이 비어 있는 개체처럼\n * 보였다. 문서 축은 같은 물음에 `null` 을 답한다(없는 것은 없다고 답한다). 상태 축도 같다.\n *\n * 못 읽은 것은 다른 사실이라 아래에서 따로 답한다 — 「없다」로 접지 않는다.\n */\n if (snap && !found) return null\n if (!snap) {\n return {\n instanceId, axis, label: info.label, itemId,\n identity: { standardClass: info.standardClass ?? null, typeRole: info.typeRole ?? null, kind: info.kind, gs1Scheme: info.gs1Scheme ?? null, journalAxis: info.journalAxis ?? null, describedBy: info.describedBy ?? null },\n declared: null,\n observed: null,\n observedOnly: true,\n /*\n * **왜 관측 열이 비었나** — 커널이 멈춰 있고 저널로도 되세우지 못했다. 코드는 목록·비교 열이\n * 쓰는 것과 같은 것을 쓴다(`not-running`) — 같은 사실에 두 낱말을 만들지 않는다.\n */\n observedAbsence: 'not-running' as const,\n basis: liveItem ? 'state' : 'journal', observedBasis: liveItem ? 'state' : 'journal', observing: liveItem,\n links: { out: [], incoming: [] }, properties: propertiesOf(axis).map((pr: any) => ({ key: pr.key, label: pr.label, kind: pr.kind, uom: pr.uom ?? null, observedBy: pr.observedBy ?? null })),\n /* 어떤 속성이 **효과가 있나** — 등록부가 말한다(§property-effects). 없는 것은 표시만 된다. */\n propertyEffects: propertyEffectsOf(axis),\n /*\n * 출처는 이 답의 `basis` 와 같은 규칙이다(아래 읽은 갈래도 같다). 여기를 `state` 로 박아 두어서, 커널이 멈춰\n * 저널로 되세우려던 답이 「지금 상태에서 읽었다」고 말했다(ADR-0075 결정 3 · 결함 넘김 2026-09-24).\n * 아무것도 못 읽었다는 사실은 `observedAbsence` 가 말한다 — 출처를 비우지 않는다(`READ_BASIS` 주석).\n */\n names: {}, provenance: { basis: liveItem ? 'state' : 'journal' }\n }\n }\n const names = namesFor([{ id: itemId, fields: found }], nameIndex(inst.model ?? {}))\n return {\n instanceId, axis, label: info.label, itemId,\n identity: { standardClass: info.standardClass ?? null, typeRole: info.typeRole ?? null, kind: info.kind, gs1Scheme: info.gs1Scheme ?? null, journalAxis: info.journalAxis ?? null, describedBy: info.describedBy ?? null },\n /*\n * **선언이 없는 축이다.** 두 열 중 왼쪽이 비는 것이 정상이고, 그 사실을 값으로 말한다\n * (`observedOnly`) — 빈 열을 \"원본이 침묵했다\" 로 읽으면 안 된다. 원본은 애초에 이 축을\n * 선언하지 않는다.\n */\n declared: null,\n observed: this.withOrderMaterial(axis, inst.model ?? {}, found),\n observedOnly: true,\n basis: liveItem ? 'state' : 'journal',\n /* 관측 열의 근거는 **한 이름으로** 낸다 — 두 이름을 두면 화면이 한쪽을 잊는다. */\n observedBasis: liveItem ? 'state' : 'journal',\n observing: liveItem,\n properties: propertiesOf(axis).map((pr: any) => ({ key: pr.key, label: pr.label, kind: pr.kind, uom: pr.uom ?? null, observedBy: pr.observedBy ?? null })),\n /* 어떤 속성이 **효과가 있나** — 등록부가 말한다(§property-effects). 없는 것은 표시만 된다. */\n propertyEffects: propertyEffectsOf(axis),\n links: await this.linksOf(domainId, inst, axis, itemId, found),\n resourceClassLabels: this.classLabels(inst.model ?? {}),\n names,\n provenance: { basis: liveItem ? 'state' : 'journal' }\n }\n }\n\n if (row) {\n const found: any = await getRepository(row.entity).findOne({\n where: { domain: { id: domainId } as any, instance: { id: inst.id } as any, [row.idColumn]: itemId } as any\n })\n if (found) {\n const { sourceRef, ingestedAt, ...rest } = this.strip(row.entity, row.idColumn, found)\n declared = rest\n /* 출처는 속성이 아니라 **근거**다 — 두 열이 아니라 아래 근거 묶음으로 간다. */\n provenance = { sourceRef, ingestedAt, basis: 'rows' }\n }\n }\n\n /*\n * 행에 없으면 문서를 본다 — **투영이 낡은 트윈에서도 항목을 볼 수 있어야 한다.** 행만 보고\n * \"없다\" 고 답하면, 문서에는 있는 자리가 화면에서 사라진다(이 프로젝트가 내내 잡아 온 부류).\n */\n if (!declared) {\n const raw = at(model, info.path)\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n /* 한 벌뿐인 선언은 축 이름으로 찾는다 — 목록이 그 이름으로 가리켰기 때문이다. */\n const found = all.find(o => idOf(o) === itemId) ?? (!Array.isArray(raw) && raw && itemId === axis ? raw : undefined)\n if (found) {\n declared = typeof found === 'string' ? { id: found } : this.withBinding(axis, model, found)\n provenance = { basis: 'document' }\n }\n }\n\n /* 선언에도 문서에도 없다 — 그런데 **관측에는 있을 수 있다**(원본이 모르는 자원). 그 경우도\n 항목으로 열려야 한다. 둘 다 없으면 진짜로 없는 것이므로 `null`. */\n const seen = await this.observedOf(domainId, instanceId, axis, itemId)\n const observed = 'value' in seen ? seen.value : null\n if (!declared && !observed) return null\n\n /* 이웃을 먼저 구한다 — 이름표가 이웃의 id 까지 덮으려면 반환 전에 손에 있어야 한다. */\n const links = await this.linksOf(domainId, inst, axis, itemId)\n\n /*\n * **구역 이름은 모델에 없다** — 구역은 호스트 개념이고(`TwinArea`), 인제스트가 모델에서 갈라\n * 공간 쪽으로 보낸다. 그래서 모델만 조회하는 이름표에는 `a-floor` 의 이름이 없고, 관계 그림에 그 id 가\n * 그대로 섰다. 그 행에서 가져와 이름표에 합친다(이 트윈의 공간 것만).\n */\n const areaNames: Record<string, string> = {}\n if (inst.spaceId) {\n const areas = await getRepository(TwinArea)\n .find({ where: { domain: { id: domainId } as any, space: { spaceId: inst.spaceId } as any } as any })\n .catch(() => [] as any[])\n for (const a of areas as any[]) if (a?.areaId && a?.name) areaNames[a.areaId] = a.name\n }\n\n return {\n instanceId,\n axis,\n label: info.label,\n itemId,\n /* 정체 — 표준 클래스·식별 스킴은 전부 카탈로그 선언에서 온다. */\n identity: {\n standardClass: info.standardClass ?? null,\n typeRole: info.typeRole ?? null,\n kind: info.kind,\n gs1Scheme: info.gs1Scheme ?? null,\n /*\n * 선언 둘을 그대로 나른다 (ADR-0074) — 이 개체의 이력을 저널의 어느 축으로 묻나,\n * 그리고 식별자 말고 무엇이 이 개체를 말하나. 화면이 그 목록을 갖지 않게 한다.\n */\n journalAxis: info.journalAxis ?? null,\n describedBy: info.describedBy ?? null\n },\n /*\n * **그릇인가** — 문서에 객체 하나로 있는 축(`productionSpec`)인지.\n *\n * `kind` 로는 갈리지 않는다: 커널은 라우트·레시피·공정도 `spec` 이라 부른다(같은 선언 부류라는\n * 뜻). 화면이 `kind` 로 갈랐더니 **라우트 상세가 그릇 틀로 그려져** 가장 중요한 정보(공정 순서)가\n * 개수 칩 하나로 줄어들었다. 그릇인지 아닌지는 모양이 말한다.\n */\n container:\n axisSource(axis) === 'document' && !Array.isArray(at(model, info.path)) && at(model, info.path) != null,\n /* 두 열 — 원본이 말한 값, 트윈이 관측한 값. 한쪽이 없으면 **없다고 낸다**(0 으로 메우지 않는다). */\n declared,\n observed,\n /*\n * 관측 열이 **자기 근거를 말한다** — 목록의 그 낱말 그대로(`state`=라이브 권위, `journal`=다시 계산한\n * 파생). 없으면 비교하지 못한 것이다. 파생이면 몇 번째 리비전까지 계산했는지 함께 낸다.\n */\n ...('value' in seen\n ? { observedBasis: seen.basis, ...(seen.foldedRevision != null ? { observedRevision: seen.foldedRevision } : {}) }\n : { observedAbsence: seen.absence }),\n /* 선언된 속성 — 어느 관측 축에서 오는지도 함께(카탈로그가 말한 대로). */\n properties: propertiesOf(axis).map((p: any) => ({ key: p.key, label: p.label, kind: p.kind, uom: p.uom ?? null, observedBy: p.observedBy ?? null })),\n /*\n * **효과가 있는 속성과 표시만 되는 속성은 다르다.** 속성은 열려 있어 아무 사실이나 실어 보낼 수\n * 있지만, 값이 계산을 바꾸려면 그 규칙을 코드가 알아야 한다. 지금 무엇이 그런지 화면이 말할 수\n * 있게 등록부를 함께 낸다 — 사용자가 넣고 나서 아무 일도 안 일어나는 이유를 알 수 있게.\n */\n propertyEffects: propertyEffectsOf(axis),\n links,\n /*\n * **등급 이름은 등급이 갖고 있다.** 공정은 자격을 등급 id 로만 요구하므로(표준이 그렇다),\n * 그 id 를 그대로 화면에 내면 `assembler-op` 이 사용자에게 간다. 등급의 표시명은 등급 선언의\n * `description`(i18n 키)에 있고 그것은 **다른 축**이다 — 화면이 축을 하나 더 읽지 않아도 되게\n * 여기서 이어 붙인다(서버는 이미 모델을 손에 들고 있다).\n */\n resourceClassLabels: this.classLabels(model),\n /*\n * **공정이면 그 공정의 능력도 함께 낸다** — ISA-95 Part 4 `OperationsCapability`.\n *\n * 공정 상세에서 사람이 묻는 것은 \"이 공정이 지금 얼마나 더 할 수 있나\" 이고, 그 답은 명세만\n * 봐서는 안 나온다(약정과 지금 못 쓰는 자원을 빼야 한다). 화면이 축을 하나 더 읽지 않게\n * 여기서 이어 붙인다 — 이름표·등급 라벨을 붙이는 것과 같은 이유다.\n */\n ...(await this.capabilityOfOperation(domainId, instanceId, axis, itemId)),\n /*\n * 상세도 같은 표를 쓴다 — 목록과 상세가 같은 이름으로 말해야 사용자가 같은 것으로 읽는다.\n *\n * **이웃의 이름도 함께 싣는다.** 관계 그림의 이웃은 대개 *들어오는* 링크(이 자리를 기준 자리로\n * 삼는 설비·사람)라, 이 항목 자신의 필드에는 그 id 가 없다 — 필드만 훑으면 그림이 id 로 채워진다.\n */\n names: namesFor(\n [{ id: itemId, fields: declared }, { fields: observed }, { fields: links }],\n { ...nameIndex(model), ...areaNames }\n ),\n provenance\n }\n }\n\n /**\n * **id → 이름**, 모든 축을 한 표로.\n *\n * ── 왜 이 표가 필요한가 ──────────────────────────────────────────────────────\n * 행은 다른 것을 **id 로** 가리킨다(사람의 `personnelClassIds`, 설비의 `homeLocationId`, 공정의\n * `locationType`). 그 id 의 이름은 **가리켜진 축의 행**에 있으므로, 화면이 그것을 알려면 축을\n * 하나씩 더 읽어야 한다 — 그래서 지금까지 표면마다 그냥 id 를 찍었다(`cutter-op`, `cut-station`).\n * 표면을 하나씩 고치는 것은 끝이 없다: 새 화면은 처음부터 다시 id 를 찍는다.\n *\n * 그래서 **서버가 붙인다.** 서버는 이미 모델을 손에 들고 있고, 어느 축이 있는지는 커널 카탈로그가\n * 선언한다(`TWIN_AXES`) — 도메인이 늘어도 이 함수는 그대로다.\n *\n * 값은 그 항목이 **자기 이름이라고 말한 것**이다(`name`·`label`·`description`). 그중 어떤 것은\n * i18n 키이므로(등급의 `description`) 번역은 화면의 일로 남긴다. 이름이 없으면 표에 넣지 않는다 —\n * 없는 것을 지어내지 않고, 그 경우 화면은 id 를 그대로 보인다.\n */\n private nameIndex(model: any): Record<string, string> {\n const out: Record<string, string> = {}\n for (const info of TWIN_AXES as any[]) {\n /* 관측 축(상태·저널)은 문서에 없다 — 경로가 없는 축을 읽으면 모델 루트를 훑는다. */\n if (axisSource(info.axis) !== 'document') continue\n const raw = at(model ?? {}, info.path)\n const list = Array.isArray(raw) ? raw : raw ? [raw] : []\n for (const o of list) {\n const id = idOf(o)\n if (!id || typeof o !== 'object') continue\n const label = o.name ?? o.label ?? o.description\n /* 이름이 id 와 같으면 표에 넣지 않는다 — 같은 값을 두 번 보이는 셈이다. */\n if (typeof label === 'string' && label && label !== id && !out[id]) out[id] = label\n }\n }\n return out\n }\n\n /**\n * 이 응답이 **실제로 가리킨 것만** 골라 낸다.\n *\n * 모델 전체 표를 그대로 실으면 자리가 10만인 현장에서 목록 한 페이지에 10만 줄짜리 이름표가\n * 따라온다. 나온 값에 걸리는 것만 싣는다 — 규모에서 성립하는 유일한 방식이다.\n */\n private namesFor(rows: any[], index: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {}\n const take = (v: any, depth: number): void => {\n if (v == null || depth > 4) return\n if (typeof v === 'string') { if (index[v]) out[v] = index[v]; return }\n if (Array.isArray(v)) { for (const x of v) take(x, depth + 1); return }\n if (typeof v === 'object') for (const x of Object.values(v)) take(x, depth + 1)\n }\n for (const r of rows) { take(r?.fields ?? r, 0); if (typeof r?.id === 'string' && index[r.id]) out[r.id] = index[r.id] }\n return out\n }\n\n /** 등급 id → 표시명 키. 인원·설비·자산·품목 등급을 한 표로 — 어느 자원이든 같은 방식으로 요구된다. */\n private classLabels(model: any): Record<string, string> {\n const out: Record<string, string> = {}\n for (const key of ['personnelClasses', 'equipmentClasses', 'assetClasses', 'materialClasses'])\n /* 표시명은 `name` 이 정본이다 — 옛 모델는 `description` 에 담고 있어 둘 다 본다(읽기 경계 하나). */\n for (const c of (model?.[key] ?? []) as any[]) if (c?.id && (c.name || c.description)) out[c.id] = c.name || c.description\n return out\n }\n\n /**\n * 관측이 본 이 항목 — 커널이 실행 중일 때만. **실행 중이 아니면 `null` 이지 빈 객체가 아니다**\n * (관측이 없는 것과 비교하지 못한 것은 다르다).\n */\n /**\n * 이 공정의 **생산 능력** — 공정 축 항목에만 붙는다.\n *\n * 구간은 **앞으로 24시간**이다. 표준의 약정·가용은 *앞으로 쓸* 용량이므로 지난 구간을 두고 말하면\n * 뜻이 없고, 이 화면에는 사용자가 고른 창이 없다. 그래서 하루를 쓰고 **그 사실을 값과 함께 낸다**\n * (화면이 라벨로 말한다) — 어느 구간의 값인지 모르면 능력은 읽을 수 없다.\n *\n * **수요를 지어내지 않는다.** 여기서 내는 값(상한·약정·달성불가·가용·제약하는 축)은 전부 공급 쪽이다 —\n * 자원 수·사이클·가동률에서 나온다. 수요는 `ok`·병목·하루 상한에만 쓰이고 그것들은 내지 않으므로,\n * 계산에 넘기는 수요 `1` 은 결과에 새지 않는다(성과 화면은 사용자가 걸어 둔 목표를 쓴다 — 그 화면은\n * \"목표를 낼 수 있나\" 에 답하고 여기서는 \"얼마나 더 할 수 있나\" 에 답한다).\n *\n * 안 실행 중이면 붙이지 않는다 — 능력은 지금 자원의 사실에서 나오고, 없는 것을 지어내지 않는다.\n */\n private async capabilityOfOperation(\n domainId: string,\n instanceId: string,\n axis: string,\n itemId: string\n ): Promise<{ capability?: any } > {\n if (axis !== 'operations') return {}\n if (!TwinEngine.isRunning(domainId, instanceId)) return {}\n const from = new Date()\n const to = new Date(from.getTime() + 24 * 3_600_000)\n const monday = Date.UTC(from.getUTCFullYear(), from.getUTCMonth(), from.getUTCDate() - ((from.getUTCDay() + 6) % 7))\n try {\n const rows = await TwinEngine.operationsCapability(\n domainId,\n { instanceId },\n 1,\n monday,\n { fromTime: from.toISOString(), toTime: to.toISOString() }\n )\n const report = rows.find((r: any) => r.instanceId === instanceId)?.report\n const entry = report?.perOperation?.find((o: any) => o.operation === itemId)\n if (!entry) return {}\n /* 병목·상한은 **넣지 않는다** — 그 둘만 수요에 달려 있고, 여기서는 수요를 모른다. */\n return { capability: { window: report.window, operationsType: report.operationsType, ...entry } }\n } catch {\n /* 능력을 못 냈다고 상세가 안 열릴 이유는 없다 — 없으면 없는 대로 낸다(화면이 그 줄을 안 그린다). */\n return {}\n }\n }\n\n /**\n * 이 항목을 트윈이 **관측한 값** — 그리고 **무엇을 근거로** 아는지.\n *\n * 봉투를 푸는 것을 빠뜨려서(`unwrapState`) 문서 축의 관측 열이 통째로 비어 있던 자리다(사람을 열면\n * 트윈이 아는 것이 전부 `—` 였다).\n *\n * 근거를 값과 함께 낸다 — 목록이 오래 해 온 그대로다(§twinModelItemList). 라이브(권위)와 저널\n * 폴드(파생)는 **같은 모양의 객체**라서, 근거가 없으면 다시 계산한 값을 \"지금 이렇다\" 로 읽는다. 근거를\n * 실을 자리가 없던 동안에는 멈춘 트윈의 저널을 아예 계산하지 않고 `—` 로 두는 편이 정직했다. 이제\n * 자리가 있으니 계산한다 — 멈춘 트윈에도 마지막으로 알던 사실이 있고, 그것을 감출 이유는 없다.\n *\n * 다시 계산할 것이 없으면(모델도 저널도 없다) `null` 이다 — **없는 것과 비교하지 못한 것은 다르다.**\n */\n private async observedOf(\n domainId: string,\n instanceId: string,\n axis: string,\n itemId: string\n ): Promise<{ value: any; basis: 'state' | 'journal'; foldedRevision?: number } | { absence: 'not-running' | 'not-observed' }> {\n const live = TwinEngine.isRunning(domainId, instanceId)\n let state: any = null\n let folded: number | undefined\n if (live) {\n state = unwrapState(TwinEngine.snapshot(domainId, instanceId))\n } else {\n try {\n const rec = await TwinEngine.recover(domainId, instanceId)\n folded = Number((rec as any)?.revision) || undefined\n /*\n * **이벤트를 하나도 계산하지 않은 폴드는 관측이 아니다.** 저널이 비어도 복원은 선언을 다시 투영한\n * 기준선을 돌려준다 — 그것을 \"트윈이 관측한 값\" 열에 실으면 **선언이 관측으로 위장한다**\n * (원본이 말한 값이 오른쪽에도 똑같이 앉아, 견준 것처럼 보인다). 계산한 것이 없으면 없다고 한다.\n */\n if (folded == null) return { absence: 'not-running' as const }\n state = unwrapState(rec)\n } catch {\n return { absence: 'not-running' as const }\n }\n }\n /* 같은 규칙 — 선언된 자리에서 읽는다. 축 이름으로 읽으면 중첩된 축이 언제나 「관측 없음」이 된다. */\n const bucket = state ? axisValueOf(state, axisInfo(axis) ?? { axis }) : null\n /*\n * **왜 관측이 없는지 말한다.** 예전에는 그냥 `null` 이었고 화면은 그것을 \"트윈이 실행 중이지 않아\"\n * 로 읽었다 — 실행 중인데도 그렇게 말했다(공정 상세에서 관측됨). 공정·레시피처럼 **관측 축이\n * 아닌 것**은 트윈이 돌든 말든 관측이 없다. 이유가 다르면 화면이 다르게 말해야 한다.\n */\n if (!Array.isArray(bucket)) return { absence: 'not-observed' as const }\n /* 같은 규칙 — 선언이 말하는 자리로 찾는다. `id` 로만 찾으면 수요 구간을 열 수 없다. */\n const value = bucket.find((x: any) => idOf(x, axisInfo(axis)) === itemId)\n if (!value) return { absence: 'not-observed' as const }\n return { value, basis: live ? 'state' : 'journal', ...(folded != null ? { foldedRevision: folded } : {}) }\n }\n\n /**\n * 이어진 것 — **양방향.** 선언된 관계(`TWIN_RELATIONS`)만 따라간다.\n *\n * 관계를 코드가 알지 않으므로 도메인이 늘어도 여기 손댈 것이 없다. 대신 **선언에 없는 관계는\n * 그리지 않는다** — 지도에 없는 길을 그리는 것보다 없다고 두는 것이 정직하다.\n *\n * 들어오는 쪽(누가 나를 가리키나)은 그 축의 항목을 살펴야 안다. 규모 규율상 **깊이 1 · 방향별\n * 상한**이고, 넘치면 몇이 더 있는지 말한다(목록으로 보낼 수 있게).\n */\n private async linksOf(\n domainId: string,\n inst: any,\n axis: string,\n itemId: string,\n /*\n * 이 항목 자신 — **상태 축은 문서에서 찾을 수 없다.** 부르는 쪽이 이미 손에 들고 있으므로 넘겨\n * 받는다. 없으면 예전처럼 문서에서 찾는다(문서 축의 거동은 그대로).\n */\n self0?: any\n ): Promise<any> {\n const NEIGHBOR_MAX = 20\n const model = inst.model ?? {}\n\n /*\n * 관측 축의 항목들 — **한 번만** 읽는다(관계마다 다시 계산하면 저널을 여러 번 계산한다).\n * 라이브가 있으면 그것, 없으면 저널 폴드. 없으면 빈 배열(없는 것을 지어내지 않는다).\n */\n let observedState: any\n let observedLoaded = false\n const observedBucket = async (a: string): Promise<any[]> => {\n if (!observedLoaded) {\n observedLoaded = true\n try {\n observedState = TwinEngine.isRunning(domainId, inst.instanceId)\n ? unwrapState(TwinEngine.snapshot(domainId, inst.instanceId))\n : unwrapState(await TwinEngine.recover(domainId, inst.instanceId))\n } catch {\n observedState = null\n }\n }\n const b = observedState ? (observedState as any)[a] : null\n return Array.isArray(b) ? b : []\n }\n\n /*\n * **관계는 선언 어휘로 푼다** — 문서에서 이 항목을 찾아 그것을 본다.\n *\n * 관계 선언의 필드 이름(`locations.parentId`)은 **원본 문서의 어휘**다. 행은 같은 사실을 자기\n * 컬럼 이름으로 담는다(자리의 구역은 `area` FK). 행을 보고 `parentId` 를 찾으면 늘 비어서\n * \"이어진 것이 없다\" 로 알리지 않고 답한다 — 실제로 그랬다.\n *\n * 어느 쪽이 정본인가로 구분하면 답이 분명하다: 관계를 선언한 어휘가 문서 어휘이므로 **문서에서\n * 푼다.** 행에만 있고 문서에 없는 항목(있을 수 있다)은 이어진 것이 비지만, 그것은 사실이다.\n */\n const axisPath = axisSource(axis) === 'document' ? axisInfo(axis)?.path : undefined\n const rawSelf = axisPath ? at(model, axisPath) : undefined\n const selfAll = Array.isArray(rawSelf) ? rawSelf : rawSelf ? [rawSelf] : []\n const self = self0 ?? selfAll.find((o: any) => idOf(o) === itemId)\n\n /*\n * ── 한 필드가 두 곳을 가리킬 때 (계약 0.9.24, 2026-09-17) ──────────────────────\n * `locations.parentId` 는 다른 자리(라인 · 셀 · 존)이거나, 그 id 의 자리가 없으면 공간의 구역이다\n * (`axis-or-external`). 어느 쪽인지는 **조회로** 갈린다 — 규칙은 계약의 `splitRelationIds` 하나다.\n *\n * 화면에는 두 줄로 낸다: 자리 쪽은 그 자리로 걷는 링크(`target.kind: 'axis'`), 나머지는 구역으로\n * 풀린 것(`external`). 한 줄에 섞으면 화면이 그 줄 전체를 외부로 그리거나 전체를 링크로 그려 둘 중\n * 하나가 틀린다. 선언은 `declaredTarget` 으로 함께 남긴다.\n */\n const axisIdSets = new Map<string, Set<string>>()\n for (const r of relationsFrom(axis)) {\n if (r.target?.kind !== 'axis-or-external' || axisIdSets.has(r.target.axis)) continue\n const tInfo = axisInfo(r.target.axis)\n const raw = tInfo && axisSource(r.target.axis) === 'document' ? at(model, tInfo.path) : await observedBucket(r.target.axis)\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n axisIdSets.set(r.target.axis, new Set(all.map((o: any) => idOf(o)).filter(Boolean).map(String)))\n }\n const inAxis = (a: string, id: string) => axisIdSets.get(a)?.has(id) ?? false\n\n /* 나가는 쪽 — 내 필드가 가리키는 것. 선언이 필드 이름을 알려 준다. */\n const out = relationsFrom(axis).map((r: any) => {\n const raw = self ? this.fieldValue(self, r.field) : []\n const ids = raw.filter((v: any) => v != null).map(String)\n return {\n via: r.via,\n field: r.field,\n optional: !!r.optional,\n /* 대상이 축이면 그 축의 항목으로 갈 수 있다. 타입·외부(구역)면 **갈 곳이 다르다** —\n 화면이 링크를 만들지 말지 알아야 하므로 대상 종류를 그대로 낸다(막다른 링크 금지). */\n target: r.target,\n /*\n * ── 언제의 일인가, 그리고 담아 둬도 되나 (2026-09-06) ────────────────\n * 판정을 계약이 낸다. 화면이 `standing` 을 보고 스스로 정하면 값이 하나 늘 때 한 화면만\n * 따라간다. UX 레인이 이 칸을 요청했고, 그쪽에 있던 규칙은 걷었다.\n *\n * `tense` 가 없는 관계도 `cacheable: false` 다. 모를 때는 다시 조회하는 쪽이 낫다 —\n * 낡은 값을 자신 있게 보여 주는 것이 비어 있는 것보다 나쁘다. 그래서 `tense` 는 없을 수\n * 있고 `cacheable` 은 언제나 있다.\n */\n tense: tenseOf(r),\n cacheable: isCacheableTense(tenseOf(r)),\n ids: ids.slice(0, NEIGHBOR_MAX),\n total: ids.length\n }\n }).flatMap((l: any) => {\n if (l.target?.kind !== 'axis-or-external') return [l]\n const all = self ? this.fieldValue(self, l.field).filter((v: any) => v != null).map(String) : []\n const split = splitRelationIds(l.target, all, inAxis)\n const part = (target: any, ids: string[]) => ({ ...l, target, declaredTarget: l.target, ids: ids.slice(0, NEIGHBOR_MAX), total: ids.length })\n const parts = [\n ...(split.axis?.ids.length ? [part({ kind: 'axis', axis: split.axis.axis }, split.axis.ids)] : []),\n ...(split.external?.ids.length ? [part({ kind: 'external', entity: split.external.entity }, split.external.ids)] : [])\n ]\n /* 비어 있는 관계도 낸다(아래 주석) — 가리키는 것이 없으면 선언 그대로 한 줄. */\n return parts.length ? parts : [l]\n })\n\n /*\n * ── 밖을 가리키는 관계를 푼다 (2026-09-05) ─────────────────────────────────\n * 계약이 `kind: 'external'` 을 선언하며 「해소는 호스트가 한다」고 적어 두었는데 **부르는 곳이\n * 0이었다.** 그래서 화면은 id 만 받고 그것이 무엇인지, 갈 수 있는지 몰랐다.\n *\n * 못 풀면 **못 푼다고 말한다** — 링크를 지우면 화면이 「그런 관계가 없다」로 읽고, 실제로는\n * 「아무도 답할 수 없다」다. 사람이 할 일이 다르다.\n */\n for (const l of out) {\n if (l.target?.kind !== 'external' || !l.ids.length) continue\n const got = await resolveExternal(l.target.entity, domainId, l.ids, { instanceId: inst.instanceId }, m => twinWarn(m))\n if (got.refs) (l as any).refs = got.refs\n else (l as any).unresolved = got.unresolved\n }\n\n /*\n * **비어 있는 관계도 낸다.** 예전에는 `total > 0` 만 냈다 — 그러면 사람은 없다는 것조차 모른다.\n *\n * 실측으로 그 값이 드러났다(2026-09-05): 설비 64대에 시험 규격이 전부 비어 있는 것을 「빈 묶음」\n * 으로 세워 두니 **「이 설비에 검사 기준이 없다」와 「화면이 그것을 안 본다」가 구별됐다.** 지우면\n * 그 구별이 사라진다.\n *\n * 선택이 아닌 관계(`optional: false`)가 비어 있으면 그것은 **끊어진 참조**이고, 그 사실이 화면에\n * 닿아야 한다.\n */\n\n /* 들어오는 쪽 — 나를 가리키는 항목들. 그 축이 행이면 DB 가 세고, 문서면 문서를 전수 조회한다. */\n const incoming: any[] = []\n /*\n * 밖에서 오는 것을 함께 싣는다 — 제품이 자기 저장소에서 모은다(커널은 그 표를 모른다).\n * 꽂힌 해소기가 없으면 빈 배열이고 그것은 정상이다.\n */\n incoming.push(...(await externalIncoming(domainId, inst.instanceId, axis, itemId, m => twinWarn(m))))\n for (const r of relationsTo(axis)) {\n const fromInfo = axisInfo(r.from)\n if (!fromInfo) continue\n const hits: string[] = []\n /*\n * 행은 `axis` 관계만 담는다. `axis-or-external`(자리 → 부모 자리 또는 구역)은 행에 구역 FK(`area`)만\n * 있고 부모 **자리**를 담는 칸이 없어서, 행에서 세면 「이 존 아래 자리들」이 조용히 0이 된다.\n * 그 관계는 선언 어휘가 사는 문서에서 센다.\n */\n const row = r.target?.kind === 'axis' ? ROW_BACKED[r.from] : undefined\n if (row) {\n const repo = getRepository(row.entity)\n /*\n * **FK 는 부르지 않으면 오지 않는다.** 관계 필드를 로딩하지 않고 조회하면 값이 늘 `undefined`\n * 라서 \"나를 가리키는 것이 하나도 없다\" 로 알리지 않고 답한다 — 실제로 그랬다(설비 둘이 이 자리를\n * 기준으로 삼는데 이웃이 비어 있었다).\n *\n * 어느 필드가 관계인지는 **엔티티 메타데이터**가 안다. 축마다 표를 두면 축이 늘 때마다\n * 여기를 고쳐야 하고, 고치는 것을 잊으면 같은 침묵이 다시 생긴다.\n */\n const relationNames = new Set(repo.metadata.relations.map(rel => rel.propertyName))\n const field = r.field.replace(/\\[\\]$/, '').split('.')[0]\n const rows: any[] = await repo.find({\n where: { domain: { id: domainId } as any, instance: { id: inst.id } as any },\n ...(relationNames.has(field) ? { relations: [field] } : {}),\n take: 5000\n })\n for (const x of rows) {\n /* 행에서는 관계가 FK 객체이거나 컬럼이다 — 이름 후보를 순서대로 본다. */\n const v = this.relationValueOfRow(x, r.field, axis)\n if (v.includes(itemId)) hits.push(x[row.idColumn])\n }\n } else {\n /*\n * 들어오는 쪽을 훑는다 — **어디를 훑을지는 그 축의 `source` 가 정한다.**\n *\n * 문서 축은 모델에서, 관측 축은 **상태에서** 훑는다(작업 → 이 오더, 작업 → 이 자리). 한동안\n * 관측 축을 건너뛰었더니 오더 상세가 \"닿는 관계가 없습니다\" 라고 답했다 — `tasks.orderId` 를\n * 선언해 두고도 그 관계를 그리지 않은 것이다. 선언한 것을 그리지 않으면 선언이 거짓이 된다.\n *\n * 규모: 상태는 지금의 사실만 담아 유한하고, 상한과 총계는 문서 축과 같은 규율을 쓴다\n * (넘치면 몇이 더 있는지 말한다). 저널 전체를 전수 조회하는 일은 여기서 하지 않는다.\n */\n const raw =\n axisSource(r.from) === 'document' ? at(model, fromInfo.path) : (await observedBucket(r.from))\n const all = Array.isArray(raw) ? raw : raw ? [raw] : []\n for (const x of all) if (this.fieldValue(x, r.field).map(String).includes(itemId)) {\n const id = idOf(x)\n if (id) hits.push(id)\n }\n }\n /*\n * **들어오는 쪽도 빈 것을 낸다** — 나가는 쪽과 같은 이유다(위 주석).\n *\n * 「이 설비를 가리키는 작업이 없다」는 사실이고, 그것을 지우면 화면은 그 물음을 물어보지도\n * 못한다. 축당 들어오는 관계는 0~8개다(실측 2026-09-05: 시험규격 8 · 자리 6 · 나머지 2 이하)\n * — 다 내도 읽을 수 있는 분량이다.\n *\n * 값도 안 든다. 행 축은 0을 알아내려면 이미 `find` 를 돌렸고, 그 0을 말하는 비용은 없다.\n *\n * `externalIncoming` 은 여기서 예외다 — 그쪽의 빈 묶음은 「그 제품이 이 축을 안 본다」는\n * 뜻이고 우리 선언에 없는 관계이므로 할 말이 없다.\n */\n incoming.push({\n via: r.via,\n from: r.from,\n field: r.field,\n tense: tenseOf(r),\n cacheable: isCacheableTense(tenseOf(r)),\n ids: hits.slice(0, NEIGHBOR_MAX),\n total: hits.length\n })\n }\n\n return { out, incoming }\n }\n\n /**\n * 선언 필드 경로 → 값들. `inputs[].material` 처럼 **배열을 지나는 경로**를 다룬다.\n * 배열 표기(`[]`)가 관계 선언의 문법이므로 그것을 따르는 것이 곧 선언을 존중하는 것이다.\n */\n private fieldValue(obj: any, field: string): any[] {\n let cur: any[] = [obj]\n for (const seg of field.split('.')) {\n const isArray = seg.endsWith('[]')\n const key = isArray ? seg.slice(0, -2) : seg\n const next: any[] = []\n for (const c of cur) {\n if (c == null) continue\n const v = c[key]\n if (v == null) continue\n if (Array.isArray(v)) next.push(...v)\n else next.push(v)\n }\n cur = next\n }\n return cur.map(v => (typeof v === 'object' && v !== null ? idOf(v) ?? v : v)).filter(v => v != null)\n }\n\n /**\n * 행에서 관계 값을 꺼낸다 — FK 는 객체(관계 미로딩이면 없음)이고 문서 필드명과 컬럼명이 다를 수 있다.\n *\n * 여기서 컬럼 이름을 **축마다 표로 두지 않는다.** 후보를 순서대로 보는 편이 축이 늘 때 고칠 것이\n * 없다: 관계 필드 이름 그대로 · 그 이름의 FK 객체의 id 컬럼.\n */\n private relationValueOfRow(rowObj: any, field: string, targetAxis: string): string[] {\n const key = field.replace(/\\[\\]$/, '').split('.')[0]\n const v = rowObj[key]\n if (v == null) return []\n if (typeof v === 'string') return [v]\n if (Array.isArray(v)) return v.map(x => (typeof x === 'string' ? x : idOf(x) ?? '')).filter(Boolean)\n /* FK 객체 — 대상 축의 id 컬럼으로 읽는다(관계를 로딩하지 않았으면 값이 없고, 그것도 사실이다). */\n const idCol = ROW_BACKED[targetAxis]?.idColumn\n const got = idCol ? v[idCol] : idOf(v)\n return got ? [String(got)] : []\n }\n}\n"]}
|