/** * Channel-reply resolution of pending work proposals. * * When the gate proposes a workstream over a channel, agreement has to be * answerable over that same channel, a gate that requires walking to a * terminal is the same friction with extra steps. This module is the * counterpart to approval-reply.ts and hangs off the same shared ingress * hook (`authorizeSurfaceIngress`), so every surface adapter gets it without * any per-adapter wiring. */ import type { ChannelIngressPolicyInput } from '../channels/index.js'; import type { WorkProposalRecord, WorkProposalStore } from '../agents/work-proposal-store.js'; export type WorkProposalReplyOutcome = { readonly consumed: false; } | { readonly consumed: true; readonly action: 'accepted' | 'declined' | 'expired'; }; export interface WorkProposalReplyDeps { readonly proposals?: Pick | undefined; /** * Start the agreed work. Called only after an affirmative reply resolved a * pending proposal, so the run is pre-authorized by construction and must * NOT be re-gated. */ readonly startAgreedWork: (proposal: WorkProposalRecord, note?: string) => Promise; /** Send a short acknowledgement back over the proposal's own channel. */ readonly replyOnChannel: (proposal: WorkProposalRecord, text: string) => Promise; } /** * Match an inbound message against the pending proposals for its surface. * * Matching is deliberately narrow: the proposal must be pending, on the same * surface, and (when both are known) from the same user. Only the most recent * such proposal is considered, so a bare "yes" can never resolve something the * owner has forgotten about. An expired proposal is not silently ignored, it * is reported back as expired, which is what "disclosed" means for state the * owner can no longer act on. */ export declare function findProposalForReply(input: Pick, pending: readonly WorkProposalRecord[]): WorkProposalRecord | null; /** * Consume an inbound message if it answers a pending work proposal. * * Returns `consumed: true` when the message was an answer, the adapter must * then neither create a chat turn nor spawn anything, because this function * has already done whatever the answer called for. */ export declare function tryResolveWorkProposalReplyFromChannel(input: ChannelIngressPolicyInput, deps: WorkProposalReplyDeps): Promise; //# sourceMappingURL=work-proposal-reply.d.ts.map