/** * Deterministic Factory health check. * * Every finding is computed from storage rows alone — no model, no controller — * so the supervisor agent explains findings rather than inventing them, and the * same list can be rendered by the UI or polled by a timer. Each finding names * the row it came from and the standard repair a person (or the supervisor's * write tools) would apply. */ import type { BoardRegistry, PhaseSemantics } from '../boards/index.js'; import type { FactoryDeferredDecisionRecord, FactoryPendingStartRecord, FactoryRunBindingRecord, WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js'; export type FactoryHealthFindingKind = 'decision-stuck' | 'start-stalled' | 'seat-orphaned' | 'seat-missing' | 'held-waiting' | 'label-drift'; export type FactoryHealthRepair = { action: 'revoke-binding'; bindingId: string; } | { action: 'accept-work-item'; workItemId: string; } | { action: 'start-run'; workItemId: string; role: string; } | { action: 'reconcile-labels'; workItemId: string; }; export interface FactoryHealthFinding { kind: FactoryHealthFindingKind; /** Stable per (kind, subject) so the UI and attention inbox can dedupe. */ id: string; workItemId: string | null; /** Card number as shown on the board, when the row carries one. */ workItemNumber: number | null; title: string; /** One sentence of grounded evidence: ids, timestamps, error text. */ evidence: string; /** ISO instant the condition began, when it is age-based. */ beganAt: string | null; suggestedRepair: FactoryHealthRepair | null; } export interface FactoryHealthReport { checkedAt: string; findings: FactoryHealthFinding[]; counts: Record; } export interface FactoryHealthThresholds { /** A retry/pending decision whose `availableAt` is this far in the past never got picked up. */ stuckDecisionMs: number; /** A lease this far past its expiry belongs to a worker that died mid-dispatch. */ expiredLeaseMs: number; /** A pending start this old is not "booting", it is stalled. */ stalledStartMs: number; /** Held cards older than this are worth nudging a maintainer about. */ waitingOnPersonMs: number; } export declare const DEFAULT_HEALTH_THRESHOLDS: FactoryHealthThresholds; interface HealthInputs { items: WorkItemRow[]; decisions: FactoryDeferredDecisionRecord[]; bindings: FactoryRunBindingRecord[]; pendingStarts: FactoryPendingStartRecord[]; /** * What the item's installed board says its current phase means. Undefined when the * board is not installed, the phase is undeclared, or the row spans several stages; * the check then neither revokes nor starts anything on a guess. */ phaseSemantics: (item: WorkItemRow) => PhaseSemantics | undefined; } /** Pure: findings from rows. Exported so tests can feed fixtures directly. */ export declare function computeFactoryHealth(inputs: HealthInputs, now: Date, thresholds?: FactoryHealthThresholds): FactoryHealthReport; export declare function runFactoryHealthCheck(workItems: WorkItemsStorage, boards: BoardRegistry, scope: { orgId: string; factoryProjectId: string; }, options?: { now?: Date; thresholds?: FactoryHealthThresholds; }): Promise; export {}; //# sourceMappingURL=health.d.ts.map