import { type CanonicalRecord, type CanonicalAggregationRecord, type CanonicalTransformationRecord, type AdapterRule, type EnergyRecord, type EnergyEquipmentRecord, type OperationalRecord, type IngestResult, type MasterDataRecord } from '@operato/ops-contract'; export declare function canonicalRulesForTest(): AdapterRule[]; /** 정규 레코드[] → 검증된 CanonicalEnvelope[] (+ 거부분). 순수 함수. 단일→객체도 배열로 정규화. */ export declare function ingestCanonicalRecords(records: CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord | EnergyRecord | EnergyEquipmentRecord | OperationalRecord | MasterDataRecord | (CanonicalRecord | CanonicalAggregationRecord | CanonicalTransformationRecord | EnergyRecord | EnergyEquipmentRecord | OperationalRecord | MasterDataRecord)[] | undefined | null, tenantId: string, defaultEventTime: string, /** * **이 사실들이 어느 트윈의 것인가** — 마감된 구간 사실의 이름에 쓰인다(커널 §`SubjectBasis`). * * 커널은 도메인으로 서므로 자기가 어느 트윈인지 모른다. 그런데 설비 번호·계량 지점 번호는 트윈 * 안에서만 통하는 이름표라, 한 도메인에 현장이 둘이면 서로 다른 설비의 같은 날이 한 사실이 된다. * 실측으로 그 일이 났다 — 두 발전소의 `002` 가 겹쳤다. * * 주지 않으면 이름표를 그대로 쓰고 `twin-local` 로 표시된다 — 겹칠 수 있다는 뜻이다. */ scope?: { scopeId?: string; identityOf?: (kind: 'equipment' | 'meter', localId: string) => string | undefined; }): CanonicalIngestResult; /** * 유입 결과 — 사건(봉투)과 **사건이 아닌 것**을 갈라 낸다. * * 마스터데이터를 `accepted` 에 섞지 않는 이유: 부르는 쪽이 그것을 저널에 적게 되고, 시각축이 없는 값이 * 「그때 일어난 일」로 남는다. 갈래를 타입으로 갈라 두면 그 실수를 할 수 없다. */ export interface CanonicalIngestResult extends IngestResult { masterData: MasterDataRecord[]; /** * 시각을 못 읽어 ingest 시각으로 떨어진 record 를 **type 별로** 센다. * * 비어 있으면 전부 자기 시각을 말한 것이다. 값이 있어도 오류는 아니다 — 절대값 snapshot 은 * polling 순간이 맞는 시각이다. 다만 그 수가 남아야 「5일 틀린 값이 저장됐다」를 나중에 찾을 수 * 있다(2026-09-06 에 그것을 backfill 로 찾았다). */ undated: Record; }