/** * Child notification policy helpers. * * Implements the decision logic described in the * "Child Contract Notification Policy" proposal: * * - `wakeOn: "any"` - wake parent for any child update * - `wakeOn: "material_change"` - wake parent for material changes only * (default; suppresses clear heartbeats) * - `wakeOn: "completion"` - wake parent only on terminal/blocked/error * * `wakeOn` only controls AUTONOMOUS parent wakeups. Explicit parent tools such * as `check_agents` and `wait_for_agents` always reveal child state regardless * of policy. * * This module is intentionally pure and side-effect-free so it is easy to * unit test and safe to call from orchestration helpers. * * @module */ import type { ChildSessionResult, ChildSessionContract } from "./types.js"; export type ChildWakePolicy = "any" | "material_change" | "completion"; export type ChildUpdateClassification = "heartbeat" | "material" | "completion" | "error" | "unknown"; /** Compact representation of a child update suitable for wake-decision logic. */ export interface ChildUpdateSnapshot { /** Kind of orchestration update being delivered to the parent. */ kind: "completed" | "wait" | "progress" | "error" | "cancelled"; /** Last assistant content / summary text emitted by the child. */ summary?: string; /** Structured child result if available (final or interim). */ result?: Partial; /** Optional explicit material flag from the child (overrides classifier). */ material?: boolean; /** * True when this update was produced by a recurring cron/cron_at timer fire * (a periodic watcher cycle), as opposed to a genuine finished answer or a * reply to the parent. A cyclic completion with no terminal verdict and no * explicit `material` flag is treated as a no-op heartbeat regardless of its * prose, so quiet watcher cycles do not wake the parent under * `material_change` / `completion`. Set only by the orchestration for * cron-origin turns. */ cyclic?: boolean; /** * Orchestration ≥1.0.71 sets this on a child's `wait` notification. A * plain wait ("I am sleeping 60s, will check again") is then a heartbeat: * it does not wake the parent unless the child said `material: true` on * the wait tool, or the wait carries a verdict hint, or it is the * QUESTION-FOR-PARENT coercion. Measured on waldemort chk (2026-08-30): * 20 of the 41 updates that woke a 690K-token manager for nothing were * bare waits. Absent on ≤1.0.70 executions, which keep the old rule so * their replay is unchanged. */ waitIsHeartbeat?: boolean; } /** Default policy when a contract is missing or unset. */ export declare const DEFAULT_CHILD_WAKE_POLICY: ChildWakePolicy; /** Normalize an arbitrary input value to a valid `ChildWakePolicy`. */ export declare function normalizeWakeOn(value: unknown): ChildWakePolicy; /** Read `wakeOn` off a contract (or a contract-shaped record) safely. */ export declare function readWakeOn(contract: Partial | Record | null | undefined): ChildWakePolicy; /** * Conservative no-op classifier. * * Returns true only for clear heartbeat/no-op text. Unknown / arbitrary * natural-language summaries default to material under `material_change`. */ export declare function isHeartbeatText(text: string | undefined): boolean; /** Classify a child update for wake-decision purposes. */ export declare function classifyChildUpdate(update: ChildUpdateSnapshot): ChildUpdateClassification; export interface ParentWakeDecisionInput { update: ChildUpdateSnapshot; contract?: Partial | Record | null; } export interface ParentWakeDecision { wake: boolean; policy: ChildWakePolicy; classification: ChildUpdateClassification; reason: string; } /** * Decide whether the parent session should be woken for the given child update. * * The conservative rule: when the helper cannot confidently classify an * update as a heartbeat under `material_change`, it wakes the parent * rather than risk silently swallowing important work. */ export declare function shouldWakeParentForChildUpdate(input: ParentWakeDecisionInput): ParentWakeDecision; /** * Evaluate a batch of pending child updates against the parent's active wait. * * Used as the digest-defense guard described in the proposal: a heartbeat-only * batch should not interrupt an active parent cron wait; a mixed batch with * any material update wakes the parent. */ export declare function shouldWakeParentForChildDigest(updates: Array): ParentWakeDecision; //# sourceMappingURL=child-notifications.d.ts.map