import type { FleetConfig } from '../config.js'; import type { Problem } from '../application/types.js'; import { type RuntimeRoleItem, type TopologyEdge, type TopologyNode } from './topology.js'; import type { DraftFieldValue, DraftPosition, TopologyDraftRead } from './topology-draft-store.js'; /** * The console's read model: authoritative configuration overlaid with the * sketches and canvas positions from the draft sidecar. * * `deriveTopology` stays a pure function of resolved config plus the runtime * role list — this layer calls it and annotates the result, so the derivation * and its tests keep their meaning. Everything drafts add is additive. */ export type NodeOrigin = 'draft' | 'config'; /** One actionable reason a node is not yet ready, phrased for the owner. */ export interface MissingRequirement { field: string; why: string; fix: string; } export interface MergedTopologyNode extends TopologyNode { origin: NodeOrigin; /** Would `loadConfig` accept this node's name today. */ valid: boolean; /** Meets the bar for being added to the fleet. */ complete: boolean; /** * Whether a process may be started for this node. A draft is never launchable, * and not because the UI hides a button: a draft is in no file the supervisor * or `ours-fleet up` reads. */ launchable: boolean; missing: MissingRequirement[]; position?: DraftPosition; enabled?: boolean; /** Sketched values, on draft nodes only — what promotion writes. */ fields?: Record; } export interface MergedTopologyEdge extends TopologyEdge { origin: NodeOrigin; /** A watchdog with no `watch:` list watches every agent, including later ones. */ implicit: boolean; /** An endpoint that no longer exists — kept visible rather than swallowed. */ dangling: boolean; } export interface MergedTopology { nodes: MergedTopologyNode[]; edges: MergedTopologyEdge[]; unknownLineage: string[]; problems: Problem[]; draftRevision: string; draftWritable: boolean; } export declare const IMPLICIT_WATCH_LABEL = "watches all agents (default)"; /** * Merge configuration and drafts into the graph the console renders. * * Drift is surfaced, never silently repaired: a draft whose name is now taken * by real configuration is reported as a problem rather than shadowing it, a * draft edge to a vanished node is kept and marked dangling, and a position for * a node that no longer exists is simply dropped. */ export declare function mergeTopology(config: FleetConfig, roles: RuntimeRoleItem[], draft: TopologyDraftRead): MergedTopology;