/** * Calendar approval gate — propose (write pending marker, ZERO events) → * approve out-of-band → apply (writeEvents exactly once) → adjust (pure re-slot). * * Reuses src/state/approval-state.ts for marker storage — no new approval mechanism. * checkpointId convention: `calendar-${planId}` mirrors do-bridge's `promote-${findingId}` * so the existing `bober approve calendar-` / `/approve calendar-` flows work * with zero new wiring. * * ALL filesystem writes (pending marker, plan sidecar) live in this module. * src/cli/commands/calendar.ts MUST NOT import writeFile — the Sprint-1 source-scan * test (calendar.test.ts:129-141) enforces this. */ import type { CalendarConnector } from "./connector.js"; import type { Finding, BusyInterval, SlotConstraints, ProposedPlan } from "./types.js"; /** Arguments for proposePlan — all I/O dependencies are injected for testability. */ export interface ProposeArgs { /** Absolute project root (used for .bober/approvals and .bober/calendar paths). */ projectRoot: string; /** Plan id — checkpointId = `calendar-${planId}`. */ planId: string; /** The proposed plan from planSlots. */ plan: ProposedPlan; /** Name of the chosen connector (informational; stored in sidecar). */ connectorName: string; /** Clock injection — returns an ISO string. */ now: () => string; /** Timeout in ms before the pending marker expires. Default 24 hours. */ timeoutMs?: number; } export type ApplyOutcome = { status: "applied"; writtenCount: number; } | { status: "rejected"; feedback?: string; } | { status: "pending"; }; /** * A constraint delta for adjustPlan — models a /tell-style user correction. * Note: SlotConstraints has no `excludeInterval` field; model exclusions by appending * a BusyInterval to the busy[] array (do NOT add new fields to SlotConstraints). */ export interface ConstraintDelta { /** Appended to busy[] to model an excluded interval. */ excludeInterval?: BusyInterval; /** Shift the planning window start. */ windowStartIso?: string; /** Shift the planning window end. */ windowEndIso?: string; } /** * Write a pending approval marker + plan sidecar for the proposed schedule. * Calls ZERO connector.writeEvents — approval is strictly out-of-band. * * All filesystem writes live here: * 1. Plan sidecar (.bober/calendar/.plan.json) — holds ProposedPlan + connectorName. * 2. Pending marker (.bober/approvals/.pending.json) — artifact.path → sidecar. */ export declare function proposePlan(args: ProposeArgs): Promise<{ checkpointId: string; }>; /** * Gate on the approval marker; on approval reload the plan sidecar and call * connector.writeEvents exactly once; on rejection skip the write entirely. * * There is no readApproved/readRejected export from approval-state.ts. * We detect the marker by building the path inline — mirrors the approach in * src/cli/commands/approve.ts:41 and src/do-bridge/promote.ts:140-146. * * Note: deletePending is best-effort (never throws); gate control is based on * the presence of the approved/rejected marker, not on the pending marker. */ export declare function applyPlan(projectRoot: string, checkpointId: string, connector: CalendarConnector): Promise; /** * PURE re-slot under a constraint delta — models a /tell-style user correction. * Re-runs the Sprint-1 planSlots with a modified busy[] or window; writes NOTHING. * * Model an "exclude interval" by appending a BusyInterval (SlotConstraints has * no excludeInterval field — do NOT add one). */ export declare function adjustPlan(findings: Finding[], busy: BusyInterval[], constraints: SlotConstraints, delta: ConstraintDelta): ProposedPlan; //# sourceMappingURL=proposal-gate.d.ts.map