/** * Live-state diff: compares declared vs observed-now vs observed-then. * * Produces structured drift signal — *what is in the cloud right now* against * both *what was declared in source* and *what was observed at the last * snapshot*. Pure function; all I/O happens in the caller. * * Two diff flavors: * - diffLive — entity-keyed (declared ↔ observedNow ↔ observedThen) * - diffLiveArtifacts — context-keyed (observedNow ↔ observedThen only; * no `declared` axis since artifacts aren't declared * as chant entities — they're created by tooling * outside chant's entity model) */ import type { ResourceMetadata, ArtifactMetadata } from "../lexicon.js"; import type { UnobservedEntity, UnobservedReason } from "../observation.js"; export interface AttributeChange { /** Attribute path (e.g. "status", "physicalId", "attributes.tags.env"). */ path: string; oldValue: unknown; newValue: unknown; } export interface ResourceDrift { name: string; type: string; changes: AttributeChange[]; } /** A declared entity the lexicon could not observe, as reported by the diff (#1089). */ export interface UnobservedResource { name: string; type?: string; reason: UnobservedReason; detail?: string; /** The resolved address the failed read was issued against (#1620), when the lexicon reported one. */ queried?: string; } /** * A live, undeclared resource whose owner-reference chain reaches a declared * entity (#1077) — a Pod a declared Deployment's controller created, for * instance. Reported separately from `orphan`: it is expected runtime, not a * delete/adopt candidate, and is never counted as drift. */ export interface RuntimeChildResource { name: string; type: string; /** The declared chant entity this resource's owner chain resolves to. */ owner: string; } export interface LiveDiffResult { /** * Declared in current build, and the provider reported it absent. Entities * the lexicon could not observe are NOT here — they are in `unobserved` * (#1089), so "missing" keeps meaning "confirmed not there". */ missing: string[]; /** * Observed in cloud right now, not declared, and either carries no owner * chain, or the chain does not reach a declared entity (unowned, foreign, * or unresolvable — #1077 never escalates an incomplete chain read to * `runtimeChildren`). A resource whose chain *does* reach a declared entity * is in `runtimeChildren` instead. */ orphan: string[]; /** * Observed in cloud right now, not declared, whose owner-reference chain * reaches a declared entity (#1077) — expected runtime, not drift. Never a * delete/adopt candidate; excluded from `orphan` and from drift counts. */ runtimeChildren: RuntimeChildResource[]; /** Was in last snapshot but isn't observed now. */ disappeared: string[]; /** Observed now and declared, but not in the previous snapshot. */ newlyObserved: string[]; /** Observed both then and now; metadata changed. */ driftedSinceSnapshot: ResourceDrift[]; /** Observed both then and now; metadata identical. */ unchanged: string[]; /** * Declared, and the lexicon could not look (#1089) — no reader for the kind, * the read failed, no credentials, no binding. Not drift, not absence: a hole * in the observation. Sorted by name. */ unobserved: UnobservedResource[]; /** * The resolved query address per entity name (#1620) — what the live read * was actually issued against, as the lexicon reported it. Present only when * the lexicon supplied addresses; other lexicons omitting it stays valid. * This is where a `missing` entry explains itself: `missing` is a bare name * list, and `queried[name]` says which address the provider answered 404 * for — a declared k8s object with no namespace reads from the *defaulted* * namespace, and only this field makes that visible. */ queried?: Record; } export interface DiffLiveInput { /** Entity names from the current build. */ declared: Set; /** Resources returned by `plugin.describeResources()` right now. */ observedNow: Record; /** Resources captured by the previous snapshot, if any. */ observedThen: Record | undefined; /** * Declared entities `describeResources()` reported as NOT-OBSERVED (#1089), * keyed by entity name. Absent/empty means every declared entity was looked * at, so absence from `observedNow` is a confirmed absence. */ unobserved?: Record; /** * Resolved query address per entity name (#1620), as the observation * reported it. Passed through to the result and joined onto unobserved rows; * never consulted for classification. */ queried?: Record; } /** The delta between two saved snapshots (#822): a two-way observed diff. */ export interface SnapshotDiffResult { /** In `next`, not in `prev`. */ added: string[]; /** In `prev`, not in `next`. */ removed: string[]; /** In both; metadata differs (with the attribute-level changes). */ changed: ResourceDrift[]; /** In both; metadata identical. */ unchanged: string[]; } /** * Diff two **observed** snapshots (#822) — `prev` vs `next`, each a resources map * read from the orphan branch. A two-way diff (no "declared" axis), so it answers * "what changed in the cloud between two points" independent of source. Pure and * deterministic (results sorted). Feeds the deployment-lanes frame-pair diff. */ export declare function diffSnapshots(prev: Record, next: Record): SnapshotDiffResult; export declare function diffLive(input: DiffLiveInput): LiveDiffResult; export interface LiveArtifactDiffResult { /** Observed now, not in previous snapshot. */ added: string[]; /** In previous snapshot, not observed now. */ removed: string[]; /** In both; metadata changed. */ changed: ResourceDrift[]; /** In both; metadata identical. */ unchanged: string[]; } export interface DiffLiveArtifactsInput { /** Artifacts returned by `plugin.listArtifacts()` right now. */ observedNow: Record; /** Artifacts captured by the previous snapshot, if any. */ observedThen: Record | undefined; } export declare function diffLiveArtifacts(input: DiffLiveArtifactsInput): LiveArtifactDiffResult; //# sourceMappingURL=live-diff.d.ts.map