@wrongstack/core 0.9.19 → 0.10.0

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.
Files changed (73) hide show
  1. package/README.md +37 -33
  2. package/dist/{agent-bridge-DMVOX0cF.d.ts → agent-bridge-DBBGP5O4.d.ts} +1 -1
  3. package/dist/{agent-subagent-runner-C4qt9e5Y.d.ts → agent-subagent-runner-KwufTWwn.d.ts} +3 -4
  4. package/dist/compactor-D1RHFRmF.d.ts +41 -0
  5. package/dist/{config-CWva0qoL.d.ts → config-CJXBka2r.d.ts} +38 -2
  6. package/dist/{context-BRNbHmRM.d.ts → context-7u93AcGD.d.ts} +140 -0
  7. package/dist/coordination/index.d.ts +13 -13
  8. package/dist/coordination/index.js +786 -200
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/{default-config-Uzla85H-.d.ts → default-config-DEXI4jsl.d.ts} +10 -1
  11. package/dist/defaults/index.d.ts +24 -24
  12. package/dist/defaults/index.js +1612 -528
  13. package/dist/defaults/index.js.map +1 -1
  14. package/dist/{events-CiG9qUM_.d.ts → events-Bw1K5E6K.d.ts} +49 -1
  15. package/dist/execution/index.d.ts +46 -32
  16. package/dist/execution/index.js +663 -169
  17. package/dist/execution/index.js.map +1 -1
  18. package/dist/extension/index.d.ts +6 -6
  19. package/dist/extension/index.js.map +1 -1
  20. package/dist/goal-store-BeRsj7YX.d.ts +188 -0
  21. package/dist/{index-p95HQ22A.d.ts → index-DIt5TIaF.d.ts} +8 -8
  22. package/dist/{index-aizK8olO.d.ts → index-DgQWnZxP.d.ts} +11 -8
  23. package/dist/index.d.ts +338 -41
  24. package/dist/index.js +2747 -787
  25. package/dist/index.js.map +1 -1
  26. package/dist/infrastructure/index.d.ts +6 -6
  27. package/dist/infrastructure/index.js +36 -0
  28. package/dist/infrastructure/index.js.map +1 -1
  29. package/dist/kernel/index.d.ts +9 -9
  30. package/dist/kernel/index.js +57 -8
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mcp-servers-BkVEqkRe.d.ts → mcp-servers-BgINZzuo.d.ts} +25 -3
  33. package/dist/models/index.d.ts +3 -3
  34. package/dist/models/index.js +164 -11
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/models-registry-gwMAo6E3.d.ts +86 -0
  37. package/dist/{multi-agent-3ZnTB1aT.d.ts → multi-agent-C1O8EFzb.d.ts} +77 -24
  38. package/dist/{multi-agent-coordinator-bRaI_aD1.d.ts → multi-agent-coordinator-DoVSBFNx.d.ts} +20 -2
  39. package/dist/{null-fleet-bus-DKM3Iy9d.d.ts → null-fleet-bus-T-s3JaOt.d.ts} +413 -110
  40. package/dist/observability/index.d.ts +2 -2
  41. package/dist/{path-resolver-TcJfc29Y.d.ts → path-resolver-BfyK-I7w.d.ts} +2 -2
  42. package/dist/{permission-bPuzAy4x.d.ts → permission-B6sldrSp.d.ts} +1 -1
  43. package/dist/{permission-policy-BUQSutpl.d.ts → permission-policy-CtNscWOA.d.ts} +10 -9
  44. package/dist/{plan-templates-fkQTyz3U.d.ts → plan-templates-BWs6Je7j.d.ts} +8 -8
  45. package/dist/{provider-runner-BEpikbbN.d.ts → provider-runner-BmPe2RuU.d.ts} +3 -3
  46. package/dist/{retry-policy-BYkq0ugs.d.ts → retry-policy-KF18W4dg.d.ts} +1 -1
  47. package/dist/sdd/index.d.ts +9 -10
  48. package/dist/sdd/index.js +350 -122
  49. package/dist/sdd/index.js.map +1 -1
  50. package/dist/security/index.d.ts +65 -4
  51. package/dist/security/index.js +67 -19
  52. package/dist/security/index.js.map +1 -1
  53. package/dist/{selector-pox8abg0.d.ts → selector-DmXxpFyM.d.ts} +1 -1
  54. package/dist/{session-reader-CSWcb5Ga.d.ts → session-reader-CCSBfQmd.d.ts} +2 -2
  55. package/dist/skills/index.d.ts +1 -1
  56. package/dist/skills/index.js +1 -1
  57. package/dist/skills/index.js.map +1 -1
  58. package/dist/storage/index.d.ts +392 -8
  59. package/dist/storage/index.js +796 -40
  60. package/dist/storage/index.js.map +1 -1
  61. package/dist/{system-prompt-Bs-Wliab.d.ts → system-prompt-CM6zOhd2.d.ts} +19 -1
  62. package/dist/{tool-executor-Boo3dekH.d.ts → tool-executor-D7RxLtg4.d.ts} +9 -4
  63. package/dist/types/index.d.ts +16 -16
  64. package/dist/types/index.js +404 -14
  65. package/dist/types/index.js.map +1 -1
  66. package/dist/utils/index.d.ts +40 -8
  67. package/dist/utils/index.js +127 -57
  68. package/dist/utils/index.js.map +1 -1
  69. package/dist/{wstack-paths-BCgmTNlG.d.ts → wstack-paths-eMXnY1_X.d.ts} +8 -0
  70. package/package.json +1 -1
  71. package/dist/compactor-DVTKL7XD.d.ts +0 -23
  72. package/dist/goal-store-C7jcumEh.d.ts +0 -96
  73. package/dist/models-registry-OG_30xqZ.d.ts +0 -46
@@ -1,17 +1,401 @@
1
- export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-fkQTyz3U.js';
2
- export { D as DefaultSessionReader } from '../session-reader-CSWcb5Ga.js';
1
+ export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-BWs6Je7j.js';
2
+ export { D as DefaultSessionReader, f as DefaultSessionReaderOptions, S as SessionReader } from '../session-reader-CCSBfQmd.js';
3
+ import { p as Request, q as Response, w as SessionEvent } from '../context-7u93AcGD.js';
3
4
  import { S as SessionRewinder, C as CheckpointInfo, a as RewindResultExtended } from '../session-rewinder-C9HnMkhP.js';
4
5
  export { D as DirectorStateCheckpoint, a as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BmYi3DGA.js';
5
- export { G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, a as appendJournal, e as emptyGoal, f as formatGoal, g as goalFilePath, l as loadGoal, s as saveGoal, b as summarizeUsage } from '../goal-store-C7jcumEh.js';
6
- import { a as WstackPaths } from '../wstack-paths-BCgmTNlG.js';
7
- import { S as SyncCategory, m as SyncConfig } from '../config-CWva0qoL.js';
8
- import '../events-CiG9qUM_.js';
9
- import '../context-BRNbHmRM.js';
6
+ export { A as AuditLevel, C as CORE_RECONSTRUCT_EVENTS, G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, S as STANDARD_AUDIT_EVENTS, a as SessionEventBridge, b as SessionEventBridgeOptions, c as SessionSamplingOptions, T as ToolProgressSamplingOptions, d as appendJournal, e as createSessionEventBridge, f as emptyGoal, g as formatGoal, h as goalFilePath, l as loadGoal, r as resolveAuditLevel, i as resolveSessionLoggingConfig, s as saveGoal, j as summarizeUsage } from '../goal-store-BeRsj7YX.js';
7
+ import { a as WstackPaths } from '../wstack-paths-eMXnY1_X.js';
8
+ import { m as SyncCategory, n as SyncConfig } from '../config-CJXBka2r.js';
9
+ import '../events-Bw1K5E6K.js';
10
10
  import '../secret-scrubber-3MHDDAtm.js';
11
11
  import '../memory-CEXuo7sz.js';
12
12
  import '../secret-vault-DoISxaKO.js';
13
13
  import '../models-registry-BcYJDKLm.js';
14
14
 
15
+ /**
16
+ * L2-B: AnnotationsStore — sidecar storage for collaboration annotations
17
+ * (Phase 2 of idea #13 from IDEAS.md).
18
+ *
19
+ * Why a sidecar file, not the session JSONL?
20
+ *
21
+ * The session log is an event-sourced append-only journal
22
+ * (`packages/core/src/types/session.ts` invariant: events are
23
+ * append-only, with `truncateToCheckpoint` only as an explicit
24
+ * rewind). Mixing in human-typed annotations would break that
25
+ * invariant — the user's note about "this rm looks dangerous"
26
+ * is not part of the agent's event history; it is meta-commentary
27
+ * on the history.
28
+ *
29
+ * So we keep annotations in a sibling file: one JSON document per
30
+ * session, at `<sessionDir>/<sessionId>.annotations.json`. The
31
+ * shape is a simple versioned array, written atomically.
32
+ *
33
+ * Concurrency model:
34
+ *
35
+ * The store uses a per-session Promise chain to serialize writes.
36
+ * Multiple annotators adding notes at the same time will queue,
37
+ * not race. The atomic write itself is the second line of
38
+ * defense (in case the chain is bypassed — e.g. two processes
39
+ * pointing at the same dir).
40
+ */
41
+ /** Wire/storage shape for one annotation. */
42
+ interface Annotation {
43
+ /** Stable id (UUIDv4-ish). Referenced by resolve/delete. */
44
+ id: string;
45
+ /** Session this annotation belongs to. */
46
+ sessionId: string;
47
+ /** Index into the session event log the annotation refers to. */
48
+ atEventIndex: number;
49
+ /** Participant id of the annotator (matches WSCollabParticipantJoined.participantId). */
50
+ authorId: string;
51
+ /** Human-readable role label snapshot for display (e.g. "annotator"). */
52
+ authorRole: 'annotator';
53
+ /** The note itself. Trimmed, capped at `MAX_TEXT_LENGTH` on add. */
54
+ text: string;
55
+ /** ISO timestamp of creation. */
56
+ createdAt: string;
57
+ /** Resolved state. Annotations start unresolved. */
58
+ resolved: boolean;
59
+ /** ISO timestamp when resolved (if resolved). */
60
+ resolvedAt?: string;
61
+ /** Participant id of the resolver (if resolved). */
62
+ resolvedBy?: string;
63
+ }
64
+ interface AnnotationsStoreOptions {
65
+ /** Directory where `<sessionId>.annotations.json` files live. */
66
+ dir: string;
67
+ }
68
+ declare class AnnotationsStore {
69
+ private readonly dir;
70
+ /** Per-session write queue. Created lazily on first add. */
71
+ private readonly writeChains;
72
+ constructor(opts: AnnotationsStoreOptions);
73
+ /**
74
+ * Return all annotations for `sessionId` in insertion order
75
+ * (oldest first). Returns an empty array when no file exists
76
+ * yet (the normal case for a fresh session).
77
+ */
78
+ list(sessionId: string): Promise<Annotation[]>;
79
+ /**
80
+ * Convenience: only unresolved annotations, newest first — the
81
+ * common UI rendering for "what still needs attention?".
82
+ */
83
+ listOpen(sessionId: string): Promise<Annotation[]>;
84
+ /**
85
+ * Add a new annotation. Returns the persisted record (with id
86
+ * and timestamps filled in). Throws when `text` is empty or
87
+ * exceeds `MAX_TEXT_LENGTH`.
88
+ */
89
+ add(input: {
90
+ sessionId: string;
91
+ atEventIndex: number;
92
+ authorId: string;
93
+ text: string;
94
+ }): Promise<Annotation>;
95
+ /**
96
+ * Mark an annotation as resolved. Returns the updated record, or
97
+ * `null` if no annotation with that id exists in this session.
98
+ * Idempotent: resolving an already-resolved annotation refreshes
99
+ * `resolvedAt` / `resolvedBy` to the latest call.
100
+ */
101
+ resolve(input: {
102
+ sessionId: string;
103
+ annotationId: string;
104
+ resolvedBy: string;
105
+ }): Promise<Annotation | null>;
106
+ private filePath;
107
+ private readFile;
108
+ private writeFile;
109
+ /**
110
+ * Serialize writes per-sessionId. We chain promises instead of
111
+ * using a Mutex class so the contract is obvious from the
112
+ * call-site: `enqueue(sid, fn)` runs `fn` after every prior
113
+ * enqueue for `sid` has settled.
114
+ */
115
+ private enqueue;
116
+ }
117
+
118
+ /**
119
+ * ReplayLogStore — sidecar store for deterministic-replay support
120
+ * (idea #2 from IDEAS.md). One JSONL file per session, recording
121
+ * every provider request/response pair so the same agent loop can
122
+ * be re-run later with frozen API responses.
123
+ *
124
+ * Why a sidecar (not the session JSONL)?
125
+ *
126
+ * Same reason as `AnnotationsStore` — the session log is
127
+ * event-sourced and append-only; a provider request payload can be
128
+ * tens of kilobytes (especially with long conversation history),
129
+ * and we want replay to be opt-in (recorded only when the user
130
+ * runs with `--replay` or a future equivalent). Mixing it into
131
+ * the event log would inflate every read for replay-irrelevant
132
+ * paths.
133
+ *
134
+ * File layout: `<dir>/<sessionId>.replay.jsonl`, one entry per line.
135
+ * Each entry: `{ hash, ts, request, response }`. The `hash` is
136
+ * computed via `hashRequest` so lookups are O(1) by hash.
137
+ *
138
+ * Concurrency: per-session write queue (same pattern as
139
+ * `AnnotationsStore`). Reads are lock-free; the write chain makes
140
+ * the append + rehash sequence atomic.
141
+ */
142
+ interface ReplayEntry {
143
+ hash: string;
144
+ ts: string;
145
+ request: Request;
146
+ response: Response;
147
+ }
148
+ interface ReplayLogStoreOptions {
149
+ /** Directory where `<sessionId>.replay.jsonl` files live. */
150
+ dir: string;
151
+ /**
152
+ * Cap on the number of entries per session. When a `record` would
153
+ * push the file beyond this, the oldest entries are evicted (LRU
154
+ * by insertion order). Set to `Infinity` to disable rotation.
155
+ * Defaults to 1000 — a single LLM call averages ~5KB serialized
156
+ * (messages + tools + response), so 1000 entries is ~5MB per
157
+ * session which is a reasonable upper bound.
158
+ */
159
+ maxEntries?: number;
160
+ }
161
+ declare class ReplayLogStore {
162
+ private readonly dir;
163
+ private readonly writeChains;
164
+ /** Per-session hash → entry index, kept in memory after the first load. */
165
+ private readonly cache;
166
+ private readonly maxEntries;
167
+ constructor(opts: ReplayLogStoreOptions);
168
+ /**
169
+ * Record a request/response pair. Idempotent on hash: a second
170
+ * `record` for the same hash is a no-op (the existing entry wins).
171
+ * Returns the hash.
172
+ */
173
+ record(input: {
174
+ sessionId: string;
175
+ request: Request;
176
+ response: Response;
177
+ }): Promise<string>;
178
+ /**
179
+ * Look up an entry by hash. Returns `null` when the request has
180
+ * not been recorded for this session. O(1) after the first call
181
+ * per session (in-memory cache).
182
+ */
183
+ lookup(sessionId: string, hash: string): Promise<ReplayEntry | null>;
184
+ /** All recorded entries for a session, in insertion order. */
185
+ load(sessionId: string): Promise<ReplayEntry[]>;
186
+ /**
187
+ * List every session id that has a replay log in the store dir.
188
+ * Returns an array of `{ sessionId, entryCount, path }` sorted
189
+ * by sessionId for stable output. Used by `wstack replay --list`.
190
+ */
191
+ list(): Promise<Array<{
192
+ sessionId: string;
193
+ entryCount: number;
194
+ path: string;
195
+ }>>;
196
+ private filePath;
197
+ private readAll;
198
+ private writeAll;
199
+ private ensureCache;
200
+ private enqueue;
201
+ }
202
+
203
+ /**
204
+ * Idea #1 from IDEAS.md — Stateful Session Recovery.
205
+ *
206
+ * `SessionRecovery` is the read-side companion to the in-flight
207
+ * marker mechanism. When the agent loop is running, it writes an
208
+ * `in_flight_start` event at the current point in the log. On
209
+ * clean shutdown, a matching `in_flight_end` follows. If the
210
+ * process dies (crash, OOM, machine sleep, SIGKILL) the marker
211
+ * is the last event in the file — and `detectStale` flags the
212
+ * session as "incomplete, can be resumed".
213
+ *
214
+ * Phase 1 of this feature is **detection only**. The actual
215
+ * re-execution of incomplete work is a follow-up: it requires
216
+ * tracking pending tool calls, mid-stream LLM responses, and
217
+ * uncommitted file changes — and re-running the agent loop from
218
+ * the last `checkpoint` event. The detection layer is independent
219
+ * and ships first because (a) it gives the user immediate
220
+ * visibility into what died, and (b) it's the foundation for the
221
+ * resume command and the CLI's "Incomplete sessions" surface.
222
+ *
223
+ * Concurrency: pure read; no writes. Safe to call from multiple
224
+ * processes simultaneously.
225
+ */
226
+ interface StaleSession {
227
+ sessionId: string;
228
+ /** Path to the JSONL log. */
229
+ path: string;
230
+ /** Last event ts (the in_flight_start timestamp). */
231
+ lastEventTs: string;
232
+ /** Context the agent was working on when it died. */
233
+ context: string;
234
+ /** Total events in the log. */
235
+ eventCount: number;
236
+ }
237
+ interface RecoveryPlan {
238
+ sessionId: string;
239
+ /** True if the session is stale (has a dangling in_flight_start). */
240
+ stale: boolean;
241
+ /** The last `checkpoint` event before the un-replayed work, or null. */
242
+ lastCheckpoint: SessionEvent | null;
243
+ /** All events after the last checkpoint (i.e. the work that needs re-execution). */
244
+ pendingEvents: SessionEvent[];
245
+ /** The dangling in_flight_start event, if any. */
246
+ inFlightStart: SessionEvent | null;
247
+ /** Free-form context the agent was working on, if any. */
248
+ context: string | null;
249
+ }
250
+ /**
251
+ * Result of `SessionRecovery.recover(sessionId)`. Distinct from
252
+ * `StaleSession`: a session is "stale" if the last event is an
253
+ * open marker, but a "recovery plan" can also be generated for
254
+ * clean sessions whose last checkpoint is older than the
255
+ * conversation history (e.g. a user-initiated "rewind to last
256
+ * good state" flow). Phase 2 of idea #1: this returns the plan;
257
+ * the actual kernel re-execution is a follow-up.
258
+ */
259
+ declare class SessionRecovery {
260
+ private readonly dir;
261
+ /**
262
+ * Scan a session log and return a `StaleSession` if and only
263
+ * if the last event is an `in_flight_start` without a matching
264
+ * `in_flight_end`. Returns `null` when:
265
+ * - the log does not exist;
266
+ * - the log is empty;
267
+ * - the last event is `in_flight_end` (clean shutdown);
268
+ * - the last event is something else (e.g. an unannotated
269
+ * legacy log without in-flight markers).
270
+ */
271
+ detectStale(sessionId: string): Promise<StaleSession | null>;
272
+ /**
273
+ * Generate a recovery plan for a session. The plan describes
274
+ * "what would be re-executed" if the user chose to resume —
275
+ * everything after the last `checkpoint` event, plus the
276
+ * dangling in-flight marker if present.
277
+ *
278
+ * Returns a non-null plan for ANY session that has at least
279
+ * one event after a checkpoint (or, for legacy sessions, at
280
+ * least one event). Pure read; no mutation.
281
+ */
282
+ recover(sessionId: string): Promise<RecoveryPlan | null>;
283
+ /**
284
+ * List every stale session in a directory. Returns an array
285
+ * (possibly empty) sorted by `lastEventTs` descending — most
286
+ * recent crash first.
287
+ */
288
+ listResumable(): Promise<StaleSession[]>;
289
+ private filePath;
290
+ /**
291
+ * Stream-parse the last few lines of a JSONL log. We do NOT load
292
+ * the whole file into memory — for long-running sessions the log
293
+ * can be megabytes. Instead we read tail-ward and find the last
294
+ * `in_flight_start` / `in_flight_end` pair.
295
+ */
296
+ private parseForStale;
297
+ constructor(dir: string);
298
+ }
299
+
300
+ /**
301
+ * ToolAuditLog — idea #9 from IDEAS.md.
302
+ *
303
+ * Tamper-evident audit trail for tool calls. Every tool_use /
304
+ * tool_result pair is appended to a sidecar JSONL with a chained
305
+ * SHA-256 — each entry's `prevHash` is the prior entry's `hash`,
306
+ * so any post-hoc modification of a single line breaks the chain
307
+ * from that point forward.
308
+ *
309
+ * Why a sidecar (not the session JSONL)?
310
+ * Same reason as `AnnotationsStore` and `ReplayLogStore`: the
311
+ * session log is an event-sourced journal. Mixing in a hash
312
+ * chain would inflate every read and tightly couple the
313
+ * integrity check to the event format. Sidecar keeps both
314
+ * concerns orthogonal.
315
+ *
316
+ * What "tamper-evident" means here:
317
+ * - The hash covers the full serialized entry: tool name, id,
318
+ * input, output, timestamp, author. Changing any byte
319
+ * changes the hash.
320
+ * - The chain is sequential — a verifier walks the file in
321
+ * order, recomputing each hash, and checks `prevHash`
322
+ * matches the previous entry's `hash`.
323
+ * - Any insertion, deletion, or modification of a single
324
+ * entry surfaces as a "chain broken at entry N" verdict.
325
+ *
326
+ * What it does NOT defend against:
327
+ * - An attacker who rewrites the whole file consistently.
328
+ * For that you'd need an external anchor (signing key,
329
+ * transparency log, etc.) — out of scope for Phase 1.
330
+ * - The agent itself misbehaving; this is post-hoc audit, not
331
+ * real-time enforcement. Use `PermissionPolicy` for that.
332
+ *
333
+ * File layout: `<dir>/<sessionId>.audit.jsonl`, one entry per
334
+ * line. The chain starts with a `genesis` entry whose
335
+ * `prevHash` is all zeros.
336
+ */
337
+ interface AuditEntry {
338
+ /** Monotonic index (0-based). */
339
+ index: number;
340
+ /** UUID for cross-referencing with logs. */
341
+ id: string;
342
+ /** ISO timestamp. */
343
+ ts: string;
344
+ /** Hash of the previous entry (or all-zeros for the genesis entry). */
345
+ prevHash: string;
346
+ /** Hash of this entry's content (sha256 over the canonical JSON). */
347
+ hash: string;
348
+ toolName: string;
349
+ toolUseId: string;
350
+ input: unknown;
351
+ output: unknown;
352
+ isError: boolean;
353
+ }
354
+ type VerifyResult = {
355
+ ok: true;
356
+ entries: number;
357
+ } | {
358
+ ok: false;
359
+ brokenAt: number;
360
+ reason: string;
361
+ };
362
+ interface ToolAuditLogOptions {
363
+ /** Directory where `<sessionId>.audit.jsonl` files live. */
364
+ dir: string;
365
+ }
366
+ declare class ToolAuditLog {
367
+ private readonly dir;
368
+ /** In-memory cache of the last entry's hash (per session), to compute chains efficiently. */
369
+ private readonly tailHash;
370
+ private readonly writeChains;
371
+ constructor(opts: ToolAuditLogOptions);
372
+ /**
373
+ * Append a tool call/result pair to the chain. Returns the
374
+ * resulting entry. Idempotency is not guaranteed — if you
375
+ * record the same tool_use twice you get two entries. That's
376
+ * intentional: the audit log is a record, not a cache.
377
+ */
378
+ record(input: {
379
+ sessionId: string;
380
+ toolName: string;
381
+ toolUseId: string;
382
+ input: unknown;
383
+ output: unknown;
384
+ isError: boolean;
385
+ }): Promise<AuditEntry>;
386
+ /**
387
+ * Walk the chain and verify every entry's hash and prevHash.
388
+ * Returns a structured verdict — never throws.
389
+ */
390
+ verify(sessionId: string): Promise<VerifyResult>;
391
+ /** All entries for a session, in insertion order. */
392
+ load(sessionId: string): Promise<AuditEntry[]>;
393
+ private filePath;
394
+ private readAll;
395
+ private appendLine;
396
+ private enqueue;
397
+ }
398
+
15
399
  interface SessionRewinderOptions {
16
400
  sessionsDir: string;
17
401
  /** The project root directory; used to validate rewind targets stay inside it. */
@@ -100,4 +484,4 @@ declare class CloudSync {
100
484
  private walkDir;
101
485
  }
102
486
 
103
- export { ALL_SYNC_CATEGORIES, CloudSync, DefaultPromptStore, DefaultSessionRewinder, type PromptEntry, type PromptStore, type SessionRewinderOptions, SyncCategory, SyncConfig, type SyncResult };
487
+ export { ALL_SYNC_CATEGORIES, type Annotation, AnnotationsStore, type AnnotationsStoreOptions, type AuditEntry, CloudSync, DefaultPromptStore, DefaultSessionRewinder, type PromptEntry, type PromptStore, type RecoveryPlan, type ReplayEntry, ReplayLogStore, type ReplayLogStoreOptions, SessionRecovery, type SessionRewinderOptions, type StaleSession, SyncCategory, SyncConfig, type SyncResult, ToolAuditLog, type ToolAuditLogOptions, type VerifyResult };