import type { CommandTypeSpec } from '@operato/ops-contract'; import { type CommandStore } from './command-dispatcher.js'; import { type ActuationRuleSpec, type AttentionLike, type RuleSkip } from './rule-evaluate.js'; /** 이 프로세스가 든 트윈 하나. */ export interface OwnedTwin { domainId: string; instanceId: string; } /** 한 트윈을 돌고 나서 남는 사실. */ export interface TwinRunReport { domainId: string; instanceId: string; /** 실제로 적힌 커맨드 수. */ proposed: number; /** 규칙마다 몇 개를 냈나 — 규칙 행에 누계를 적으려면 나누어 세어야 한다. */ proposedByRule: Record; /** 왜 안 올렸나 — 규칙이 조용히 안 도는 것과 조건이 없어서 안 내는 것을 구별한다. */ skips: RuleSkip[]; /** 상한에 닿아 두고 온 수. */ withheld?: number; /** 이 트윈을 아예 못 돌았으면 그 이유. */ failed?: string; } /** 밖에서 받는 것들 — 저장소도 엔진도 시계도 인자다. 그래야 시험이 재기동과 상한을 걸을 수 있다. */ export interface RuleRunnerDeps { /** 이 프로세스가 든 트윈들. 남의 프로세스가 든 트윈은 그쪽이 돈다. */ ownedTwins(): OwnedTwin[]; /** 이 트윈에 걸린 규칙 — 없으면 스냅샷을 읽지 않는다. */ rulesOf(twin: OwnedTwin): Promise; /** 지금 서 있는 주의들. */ attentionsOf(twin: OwnedTwin): AttentionLike[] | undefined; /** * 이 트윈이 **무엇을 비추고 있나** — 관측(`live`)인가 가정(`sim`)인가. * * 이 값이 없거나 `live` 가 아니면 조치를 내지 않는다(§`runOneTwin`). 모름을 통과로 읽지 않는다. */ modeOf(twin: OwnedTwin): 'live' | 'sim' | undefined; /** 커맨드가 사는 자리. */ store: CommandStore; /** 선언된 조치 종류 — 없는 종류를 가리키는 규칙은 판정이 걸러 낸다. */ specs: readonly CommandTypeSpec[]; nowMs(): number; /** 돈 결과를 규칙 행에 남긴다 — 화면이 「이 규칙이 돌고 있나」를 말할 수 있게. */ noteRun?(twin: OwnedTwin, report: TwinRunReport): Promise; maxPerRun?: number; } /** * 한 바퀴 돈다 — **한 트윈이 실패해도 나머지는 돈다.** * * 트윈 하나의 규칙이 잘못됐다고 다른 공장의 규칙이 멈추면, 고치는 동안 전체가 멈춘 셈이 된다. */ export declare function runRulesOnce(deps: RuleRunnerDeps): Promise;