@delegance/claude-autopilot 7.10.1 → 7.11.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,163 @@
1
+ import { GuardrailError } from '../errors.ts';
2
+ import { SerializedWriter } from '../run-state/serialized-writer.ts';
3
+ /** Budget caps for a single run. `perRunUSD` is the hard ceiling on total
4
+ * committed spend (spent + active reservations) across all concurrent
5
+ * tasks. `perSubagentUSD` is the per-task hard cap that dispatch refuses
6
+ * to exceed even if perRunUSD has headroom. */
7
+ export interface BudgetCaps {
8
+ /** Total USD this run is allowed to commit across all subagents +
9
+ * in-flight reservations. */
10
+ perRunUSD: number;
11
+ /** Hard per-subagent cap. A pre-flight estimate exceeding this rejects
12
+ * dispatch; an actual cost exceeding it mid-execution triggers the
13
+ * scheduler's SIGTERM path (PR 4) — this layer just emits the
14
+ * `task.failed` event with `error_type: 'budget_exceeded'`. */
15
+ perSubagentUSD: number;
16
+ }
17
+ /** Per-task ledger entry. Reconstructed via `replayFromEvents` at startup
18
+ * / resume. */
19
+ export interface ReservationEntry {
20
+ task_id: string;
21
+ /** Latest reservation value (after any
22
+ * `task.budget_increased_reservation` events; ABSOLUTE, not delta). */
23
+ reserved_usd: number;
24
+ /** True once `task.budget_released` has landed for this task. */
25
+ released: boolean;
26
+ /** Actual cost if `released` is true. */
27
+ actual_cost_usd?: number;
28
+ }
29
+ /** Result of replaying events.ndjson into a fresh ledger state. */
30
+ export interface BudgetReplaySummary {
31
+ /** Sum of `actual_cost_usd` across released tasks. Committed against
32
+ * `perRunUSD` permanently. */
33
+ spentTotal: number;
34
+ /** Sum of `reserved_usd` for tasks NOT yet released. Each task
35
+ * contributes its LATEST reservation (absolute value), not the sum of
36
+ * reserved + increased values. */
37
+ activeReservedTotal: number;
38
+ /** `spentTotal + activeReservedTotal`. The number the headroom check
39
+ * compares against `perRunUSD`. */
40
+ committedTotal: number;
41
+ /** Per-task latest state. */
42
+ perTask: Map<string, ReservationEntry>;
43
+ }
44
+ /** Thrown by `reserve()` / `increaseReservation()` when the requested
45
+ * amount would push the run over `perRunUSD`, or when a pre-flight
46
+ * exceeds `perSubagentUSD`. Carries the GuardrailError code
47
+ * `budget_exceeded` for upstream resume classification. */
48
+ export declare class BudgetExceededError extends GuardrailError {
49
+ constructor(message: string, details: Record<string, unknown>);
50
+ }
51
+ export interface ReserveOptions {
52
+ /** Pre-flight cost estimate for the task in USD. */
53
+ preFlightEstimateUsd: number;
54
+ /** Budget caps for this run. */
55
+ caps: BudgetCaps;
56
+ }
57
+ export interface IncreaseReservationOptions {
58
+ /** New reservation total (NOT a delta — the absolute new value). */
59
+ newReservedUsd: number;
60
+ /** Free-form reason captured on the event. */
61
+ reason: string;
62
+ /** Budget caps for this run. */
63
+ caps: BudgetCaps;
64
+ }
65
+ export interface ReleaseOptions {
66
+ /** Actual cost spent by the subagent (from telemetry). */
67
+ actualCostUsd: number;
68
+ }
69
+ /**
70
+ * Budget reservation ledger. One instance per run, owned by the scheduler.
71
+ * All mutations route through the supplied `SerializedWriter` and re-replay
72
+ * events.ndjson under the exclusive lock so they are atomic against
73
+ * concurrent callers AND any other `BudgetReservation` instances pointed at
74
+ * the same run.
75
+ */
76
+ export declare class BudgetReservation {
77
+ private readonly writer;
78
+ /** In-memory mirror of disk state, kept for fast `snapshot()` reads.
79
+ * NOT authoritative — every mutating operation re-replays the on-disk
80
+ * log inside the writer's exclusive lock before checking caps. Per-task
81
+ * reservations stored in USD (public API); the running totals below are
82
+ * in MICROS (integer-safe arithmetic). */
83
+ private reservations;
84
+ private spentMicros;
85
+ private activeReservedMicros;
86
+ constructor(writer: SerializedWriter);
87
+ /** Re-seed in-memory state from events.ndjson. Call on construction OR
88
+ * on resume. Safe to call multiple times — overwrites the cache. */
89
+ hydrateFromEvents(eventsNdjsonPath: string): Promise<void>;
90
+ /** Read the current in-memory state. Best-effort: a concurrent writer
91
+ * in another instance could make this stale until the next mutating
92
+ * call re-hydrates from disk. */
93
+ snapshot(): BudgetReplaySummary;
94
+ /**
95
+ * Reserve budget for a task. Atomic under the writer lock:
96
+ *
97
+ * 1. HARD cap check (pre-lock): `preFlightEstimate <= caps.perSubagentUSD`
98
+ * 2. Acquire SerializedWriter lock
99
+ * 3. Re-replay events.ndjson from disk (authoritative)
100
+ * 4. Verify task doesn't already have an in-flight reservation
101
+ * 5. Verify `caps.perRunUSD - committedTotal >= preFlightEstimate`
102
+ * (committedTotal = spent + active reservations)
103
+ * 6. If pass: append `task.budget_reserved` event + fsync
104
+ * If fail: append `task.budget_halt` event + fsync, then throw
105
+ * 7. Release lock
106
+ *
107
+ * Throws `BudgetExceededError` on cap violations. The `task.budget_halt`
108
+ * variant is durable: the event lands inside the same critical section
109
+ * before the throw propagates, so a crash post-throw still surfaces the
110
+ * halt on resume.
111
+ */
112
+ reserve(taskId: string, opts: ReserveOptions): Promise<void>;
113
+ /**
114
+ * Bump an in-flight reservation to a new ABSOLUTE value. Atomic under
115
+ * the writer lock; re-replays disk state before checking caps.
116
+ * Re-checks `perRunUSD` against the NEW reservation total; halts the
117
+ * run with `task.budget_halt` if the bump would exceed the cap.
118
+ *
119
+ * Throws `BudgetExceededError` (with durable `task.budget_halt`) if no
120
+ * prior reservation exists, the bump is downward (use `release`
121
+ * instead), or the bump exceeds caps.
122
+ */
123
+ increaseReservation(taskId: string, opts: IncreaseReservationOptions): Promise<void>;
124
+ /**
125
+ * Release a reservation with the actual cost. Atomic under the writer
126
+ * lock; re-replays disk state. Moves the task's commitment from
127
+ * `activeReserved` to `spent`. Emits `task.budget_released` with
128
+ * `delta_vs_reservation_usd` (positive = under, negative = over).
129
+ *
130
+ * Note: a release with `actualCostUsd > reserved_usd` is NOT a halt —
131
+ * the budget was already committed at reservation time. The scheduler
132
+ * is expected to issue `increaseReservation` mid-flight when telemetry
133
+ * suggests overrun, and to emit `task.failed{error_type:'budget_exceeded'}`
134
+ * if the increase itself fails. This `release` just records the truth.
135
+ */
136
+ release(taskId: string, opts: ReleaseOptions): Promise<void>;
137
+ /** Internal: replace in-memory ledger from a replay summary (in micros).
138
+ * Used by every mutating method to re-sync cache with disk under the
139
+ * lock. */
140
+ private applyReplayMicros;
141
+ /**
142
+ * Replay events.ndjson into a fresh `BudgetReplaySummary` (decimal USD).
143
+ * Used by:
144
+ * 1. `hydrateFromEvents` — runtime cache seed on resume / startup
145
+ * 2. tests — to assert reconstruction is exact
146
+ *
147
+ * Internally calls `replayFromEventsMicros` and converts to USD at the
148
+ * boundary so external consumers see decimal numbers, but the fold itself
149
+ * is integer-micro arithmetic.
150
+ *
151
+ * Line parsing is lenient: blank lines are skipped, parse failures stop
152
+ * the walk (treated as truncated tail; the next `appendEvent` would
153
+ * emit `run.recovery`, and budget state stays consistent up to the
154
+ * last-known-good line).
155
+ */
156
+ static replayFromEvents(eventsNdjsonPath: string): BudgetReplaySummary;
157
+ /**
158
+ * Internal: micro-precision replay. Used by every mutating method INSIDE
159
+ * `withExclusive` so cap checks operate on integer arithmetic.
160
+ */
161
+ private static replayFromEventsMicros;
162
+ }
163
+ //# sourceMappingURL=budget-reservation.d.ts.map