import { type PendingConfirmFile, type PendingDecision } from "./dev-confirm-paths.js"; /** * v1.3.0 Part A — bot-side half of the dev-confirm gate. Watches one org's * `pending-confirms/` directory; when the PreToolUse hook drops a `.json` * request, the bridge: * * 1. posts an approval card to command- (via the injected poster, * implemented by the Discord adapter — Part B buttons), * 2. awaits the user's verdict (button click) or the gate timeout, * 3. writes `.decision` ("y"/"n") for the hook to read, and * 4. appends an enriched audit record (commit hashes + workflow id) to * `/memory/dev-confirmations.jsonl`. * * The controller lifecycle + timeout + audit write are reused from * `dev-confirm.ts:createDevConfirm`; the bridge only adds the file IPC and the * commit-hash mapping (via the `writeAudit` seam). Single-bot-process invariant * (v0.7) means an in-memory in-flight set is enough — no file locks. * * Restart recovery (PRD risk #5): `start()` scans for leftover `.json` * without a sibling `.decision` and re-posts them, so a bot restart mid * confirm doesn't strand a pending push forever. */ /** Posts the approval card and resolves with the user's verdict. */ export type ApprovalPoster = (req: PendingConfirmFile) => Promise; export interface DevConfirmBridgeOpts { workspace: string; orgSlug: string; /** Posts the approval card + awaits the verdict. */ postApproval: ApprovalPoster; /** Override approval timeout (ms). Defaults to dev-confirm's 30 min. */ timeoutMs?: number; /** Test seam. */ now?: () => number; /** Stale-file sweep horizon (ms). Files older than this are GC'd on start. */ staleMs?: number; } export declare class DevConfirmBridge { private readonly opts; private readonly dir; private watcher; /** Confirm ids currently being handled — dedupes watch event storms. */ private readonly inFlight; constructor(opts: DevConfirmBridgeOpts); /** Begin watching. Idempotent. Best-effort — never throws. */ start(): void; stop(): void; /** Scan the directory once for unresolved requests (recovery / fallback). */ scanOnce(): Promise; private handleId; private readRequest; private process; private writeDecision; private appendAudit; /** Delete pending/decision files older than `staleMs` to bound growth. */ private sweepStale; }