@basou/core 0.7.0 → 0.9.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.
package/dist/index.d.ts CHANGED
@@ -112,6 +112,7 @@ declare const SessionInnerImportSchema: z.ZodObject<{
112
112
  }>;
113
113
  version: z.ZodLiteral<"0.1.0">;
114
114
  external_id: z.ZodOptional<z.ZodString>;
115
+ source_size_bytes: z.ZodOptional<z.ZodNumber>;
115
116
  }, z.core.$strip>;
116
117
  started_at: z.ZodString;
117
118
  ended_at: z.ZodOptional<z.ZodString>;
@@ -148,6 +149,10 @@ declare const SessionInnerImportSchema: z.ZodObject<{
148
149
  active_time_method: z.ZodOptional<z.ZodString>;
149
150
  machine_active_time_ms: z.ZodOptional<z.ZodNumber>;
150
151
  }, z.core.$strip>>;
152
+ integrity: z.ZodOptional<z.ZodObject<{
153
+ head_hash: z.ZodString;
154
+ event_count: z.ZodNumber;
155
+ }, z.core.$strict>>;
151
156
  }, z.core.$strict>;
152
157
  /**
153
158
  * Schema for the round-trip JSON payload accepted by `basou session import
@@ -172,6 +177,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
172
177
  }>;
173
178
  version: z.ZodLiteral<"0.1.0">;
174
179
  external_id: z.ZodOptional<z.ZodString>;
180
+ source_size_bytes: z.ZodOptional<z.ZodNumber>;
175
181
  }, z.core.$strip>;
176
182
  started_at: z.ZodString;
177
183
  ended_at: z.ZodOptional<z.ZodString>;
@@ -208,6 +214,10 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
208
214
  active_time_method: z.ZodOptional<z.ZodString>;
209
215
  machine_active_time_ms: z.ZodOptional<z.ZodNumber>;
210
216
  }, z.core.$strip>>;
217
+ integrity: z.ZodOptional<z.ZodObject<{
218
+ head_hash: z.ZodString;
219
+ event_count: z.ZodNumber;
220
+ }, z.core.$strict>>;
211
221
  }, z.core.$strict>;
212
222
  events: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
213
223
  schema_version: z.ZodLiteral<"0.1.0">;
@@ -215,6 +225,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
215
225
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
216
226
  occurred_at: z.ZodString;
217
227
  source: z.ZodString;
228
+ prev_hash: z.ZodOptional<z.ZodString>;
218
229
  type: z.ZodLiteral<"session_started">;
219
230
  }, z.core.$strip>, z.ZodObject<{
220
231
  schema_version: z.ZodLiteral<"0.1.0">;
@@ -222,6 +233,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
222
233
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
223
234
  occurred_at: z.ZodString;
224
235
  source: z.ZodString;
236
+ prev_hash: z.ZodOptional<z.ZodString>;
225
237
  type: z.ZodLiteral<"session_ended">;
226
238
  exit_code: z.ZodOptional<z.ZodNumber>;
227
239
  }, z.core.$strip>, z.ZodObject<{
@@ -230,6 +242,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
230
242
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
231
243
  occurred_at: z.ZodString;
232
244
  source: z.ZodString;
245
+ prev_hash: z.ZodOptional<z.ZodString>;
233
246
  type: z.ZodLiteral<"session_status_changed">;
234
247
  from: z.ZodString;
235
248
  to: z.ZodString;
@@ -239,6 +252,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
239
252
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
240
253
  occurred_at: z.ZodString;
241
254
  source: z.ZodString;
255
+ prev_hash: z.ZodOptional<z.ZodString>;
242
256
  type: z.ZodLiteral<"approval_requested">;
243
257
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
244
258
  expires_at: z.ZodDefault<z.ZodNullable<z.ZodString>>;
@@ -259,6 +273,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
259
273
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
260
274
  occurred_at: z.ZodString;
261
275
  source: z.ZodString;
276
+ prev_hash: z.ZodOptional<z.ZodString>;
262
277
  type: z.ZodLiteral<"approval_approved">;
263
278
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
264
279
  resolver: z.ZodOptional<z.ZodString>;
@@ -269,6 +284,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
269
284
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
270
285
  occurred_at: z.ZodString;
271
286
  source: z.ZodString;
287
+ prev_hash: z.ZodOptional<z.ZodString>;
272
288
  type: z.ZodLiteral<"approval_rejected">;
273
289
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
274
290
  resolver: z.ZodOptional<z.ZodString>;
@@ -279,6 +295,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
279
295
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
280
296
  occurred_at: z.ZodString;
281
297
  source: z.ZodString;
298
+ prev_hash: z.ZodOptional<z.ZodString>;
282
299
  type: z.ZodLiteral<"approval_expired">;
283
300
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
284
301
  }, z.core.$strip>, z.ZodObject<{
@@ -287,6 +304,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
287
304
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
288
305
  occurred_at: z.ZodString;
289
306
  source: z.ZodString;
307
+ prev_hash: z.ZodOptional<z.ZodString>;
290
308
  type: z.ZodLiteral<"command_executed">;
291
309
  command: z.ZodString;
292
310
  args: z.ZodArray<z.ZodString>;
@@ -301,6 +319,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
301
319
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
302
320
  occurred_at: z.ZodString;
303
321
  source: z.ZodString;
322
+ prev_hash: z.ZodOptional<z.ZodString>;
304
323
  type: z.ZodLiteral<"git_snapshot">;
305
324
  head: z.ZodString;
306
325
  branch: z.ZodString;
@@ -316,6 +335,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
316
335
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
317
336
  occurred_at: z.ZodString;
318
337
  source: z.ZodString;
338
+ prev_hash: z.ZodOptional<z.ZodString>;
319
339
  type: z.ZodLiteral<"file_changed">;
320
340
  path: z.ZodString;
321
341
  change_type: z.ZodEnum<{
@@ -331,6 +351,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
331
351
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
332
352
  occurred_at: z.ZodString;
333
353
  source: z.ZodString;
354
+ prev_hash: z.ZodOptional<z.ZodString>;
334
355
  type: z.ZodLiteral<"decision_recorded">;
335
356
  decision_id: z.ZodString & z.ZodType<`decision_${string}`, string, z.core.$ZodTypeInternals<`decision_${string}`, string>>;
336
357
  title: z.ZodString;
@@ -345,6 +366,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
345
366
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
346
367
  occurred_at: z.ZodString;
347
368
  source: z.ZodString;
369
+ prev_hash: z.ZodOptional<z.ZodString>;
348
370
  type: z.ZodLiteral<"task_created">;
349
371
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
350
372
  title: z.ZodString;
@@ -354,6 +376,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
354
376
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
355
377
  occurred_at: z.ZodString;
356
378
  source: z.ZodString;
379
+ prev_hash: z.ZodOptional<z.ZodString>;
357
380
  type: z.ZodLiteral<"task_status_changed">;
358
381
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
359
382
  from: z.ZodString;
@@ -364,6 +387,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
364
387
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
365
388
  occurred_at: z.ZodString;
366
389
  source: z.ZodString;
390
+ prev_hash: z.ZodOptional<z.ZodString>;
367
391
  type: z.ZodLiteral<"task_reconciled">;
368
392
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
369
393
  removed_created_in_session: z.ZodDefault<z.ZodNullable<z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>>>;
@@ -375,6 +399,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
375
399
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
376
400
  occurred_at: z.ZodString;
377
401
  source: z.ZodString;
402
+ prev_hash: z.ZodOptional<z.ZodString>;
378
403
  type: z.ZodLiteral<"task_linkage_refreshed">;
379
404
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
380
405
  added_linked_sessions: z.ZodDefault<z.ZodArray<z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>>>;
@@ -386,6 +411,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
386
411
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
387
412
  occurred_at: z.ZodString;
388
413
  source: z.ZodString;
414
+ prev_hash: z.ZodOptional<z.ZodString>;
389
415
  type: z.ZodLiteral<"task_deleted">;
390
416
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
391
417
  title: z.ZodString;
@@ -395,6 +421,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
395
421
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
396
422
  occurred_at: z.ZodString;
397
423
  source: z.ZodString;
424
+ prev_hash: z.ZodOptional<z.ZodString>;
398
425
  type: z.ZodLiteral<"task_archived">;
399
426
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
400
427
  title: z.ZodString;
@@ -404,6 +431,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
404
431
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
405
432
  occurred_at: z.ZodString;
406
433
  source: z.ZodString;
434
+ prev_hash: z.ZodOptional<z.ZodString>;
407
435
  type: z.ZodLiteral<"note_added">;
408
436
  body: z.ZodString;
409
437
  }, z.core.$strip>, z.ZodObject<{
@@ -412,6 +440,7 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
412
440
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
413
441
  occurred_at: z.ZodString;
414
442
  source: z.ZodString;
443
+ prev_hash: z.ZodOptional<z.ZodString>;
415
444
  type: z.ZodLiteral<"adapter_output">;
416
445
  stream: z.ZodEnum<{
417
446
  stdout: "stdout";
@@ -451,6 +480,14 @@ type ClaudeTranscriptToPayloadOptions = {
451
480
  * back to the `sessionId` read from the records when omitted.
452
481
  */
453
482
  externalId?: string;
483
+ /**
484
+ * Byte size of the source transcript that produced `records`, stored as
485
+ * `session.source.source_size_bytes` so a later import can detect growth and
486
+ * re-import the session. The caller passes the size of the buffer it actually
487
+ * read (an immutable snapshot of the parsed bytes), so the stored size always
488
+ * matches the imported content. Omitted => the field is not recorded.
489
+ */
490
+ sourceSizeBytes?: number;
454
491
  };
455
492
  /**
456
493
  * Transform a Claude Code native transcript into a Basou
@@ -506,6 +543,14 @@ type CodexRolloutToPayloadOptions = {
506
543
  * to the id read from the rollout's `session_meta` record when omitted.
507
544
  */
508
545
  externalId?: string;
546
+ /**
547
+ * Byte size of the source rollout that produced `records`, stored as
548
+ * `session.source.source_size_bytes` so a later import can detect growth and
549
+ * re-import the session. The caller passes the size of the buffer it actually
550
+ * read (an immutable snapshot of the parsed bytes), so the stored size always
551
+ * matches the imported content. Omitted => the field is not recorded.
552
+ */
553
+ sourceSizeBytes?: number;
509
554
  };
510
555
  /**
511
556
  * Transform a Codex native rollout log into a Basou {@link SessionImportPayload},
@@ -710,6 +755,7 @@ declare const SessionStartedEventSchema: z.ZodObject<{
710
755
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
711
756
  occurred_at: z.ZodString;
712
757
  source: z.ZodString;
758
+ prev_hash: z.ZodOptional<z.ZodString>;
713
759
  type: z.ZodLiteral<"session_started">;
714
760
  }, z.core.$strip>;
715
761
  declare const SessionEndedEventSchema: z.ZodObject<{
@@ -718,6 +764,7 @@ declare const SessionEndedEventSchema: z.ZodObject<{
718
764
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
719
765
  occurred_at: z.ZodString;
720
766
  source: z.ZodString;
767
+ prev_hash: z.ZodOptional<z.ZodString>;
721
768
  type: z.ZodLiteral<"session_ended">;
722
769
  exit_code: z.ZodOptional<z.ZodNumber>;
723
770
  }, z.core.$strip>;
@@ -727,6 +774,7 @@ declare const SessionStatusChangedEventSchema: z.ZodObject<{
727
774
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
728
775
  occurred_at: z.ZodString;
729
776
  source: z.ZodString;
777
+ prev_hash: z.ZodOptional<z.ZodString>;
730
778
  type: z.ZodLiteral<"session_status_changed">;
731
779
  from: z.ZodString;
732
780
  to: z.ZodString;
@@ -737,6 +785,7 @@ declare const ApprovalRequestedEventSchema: z.ZodObject<{
737
785
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
738
786
  occurred_at: z.ZodString;
739
787
  source: z.ZodString;
788
+ prev_hash: z.ZodOptional<z.ZodString>;
740
789
  type: z.ZodLiteral<"approval_requested">;
741
790
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
742
791
  expires_at: z.ZodDefault<z.ZodNullable<z.ZodString>>;
@@ -758,6 +807,7 @@ declare const ApprovalApprovedEventSchema: z.ZodObject<{
758
807
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
759
808
  occurred_at: z.ZodString;
760
809
  source: z.ZodString;
810
+ prev_hash: z.ZodOptional<z.ZodString>;
761
811
  type: z.ZodLiteral<"approval_approved">;
762
812
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
763
813
  resolver: z.ZodOptional<z.ZodString>;
@@ -769,6 +819,7 @@ declare const ApprovalRejectedEventSchema: z.ZodObject<{
769
819
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
770
820
  occurred_at: z.ZodString;
771
821
  source: z.ZodString;
822
+ prev_hash: z.ZodOptional<z.ZodString>;
772
823
  type: z.ZodLiteral<"approval_rejected">;
773
824
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
774
825
  resolver: z.ZodOptional<z.ZodString>;
@@ -780,6 +831,7 @@ declare const ApprovalExpiredEventSchema: z.ZodObject<{
780
831
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
781
832
  occurred_at: z.ZodString;
782
833
  source: z.ZodString;
834
+ prev_hash: z.ZodOptional<z.ZodString>;
783
835
  type: z.ZodLiteral<"approval_expired">;
784
836
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
785
837
  }, z.core.$strip>;
@@ -789,6 +841,7 @@ declare const CommandExecutedEventSchema: z.ZodObject<{
789
841
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
790
842
  occurred_at: z.ZodString;
791
843
  source: z.ZodString;
844
+ prev_hash: z.ZodOptional<z.ZodString>;
792
845
  type: z.ZodLiteral<"command_executed">;
793
846
  command: z.ZodString;
794
847
  args: z.ZodArray<z.ZodString>;
@@ -804,6 +857,7 @@ declare const GitSnapshotEventSchema: z.ZodObject<{
804
857
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
805
858
  occurred_at: z.ZodString;
806
859
  source: z.ZodString;
860
+ prev_hash: z.ZodOptional<z.ZodString>;
807
861
  type: z.ZodLiteral<"git_snapshot">;
808
862
  head: z.ZodString;
809
863
  branch: z.ZodString;
@@ -820,6 +874,7 @@ declare const FileChangedEventSchema: z.ZodObject<{
820
874
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
821
875
  occurred_at: z.ZodString;
822
876
  source: z.ZodString;
877
+ prev_hash: z.ZodOptional<z.ZodString>;
823
878
  type: z.ZodLiteral<"file_changed">;
824
879
  path: z.ZodString;
825
880
  change_type: z.ZodEnum<{
@@ -836,6 +891,7 @@ declare const DecisionRecordedEventSchema: z.ZodObject<{
836
891
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
837
892
  occurred_at: z.ZodString;
838
893
  source: z.ZodString;
894
+ prev_hash: z.ZodOptional<z.ZodString>;
839
895
  type: z.ZodLiteral<"decision_recorded">;
840
896
  decision_id: z.ZodString & z.ZodType<`decision_${string}`, string, z.core.$ZodTypeInternals<`decision_${string}`, string>>;
841
897
  title: z.ZodString;
@@ -851,6 +907,7 @@ declare const TaskCreatedEventSchema: z.ZodObject<{
851
907
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
852
908
  occurred_at: z.ZodString;
853
909
  source: z.ZodString;
910
+ prev_hash: z.ZodOptional<z.ZodString>;
854
911
  type: z.ZodLiteral<"task_created">;
855
912
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
856
913
  title: z.ZodString;
@@ -861,6 +918,7 @@ declare const TaskStatusChangedEventSchema: z.ZodObject<{
861
918
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
862
919
  occurred_at: z.ZodString;
863
920
  source: z.ZodString;
921
+ prev_hash: z.ZodOptional<z.ZodString>;
864
922
  type: z.ZodLiteral<"task_status_changed">;
865
923
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
866
924
  from: z.ZodString;
@@ -872,6 +930,7 @@ declare const TaskReconciledEventSchema: z.ZodObject<{
872
930
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
873
931
  occurred_at: z.ZodString;
874
932
  source: z.ZodString;
933
+ prev_hash: z.ZodOptional<z.ZodString>;
875
934
  type: z.ZodLiteral<"task_reconciled">;
876
935
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
877
936
  removed_created_in_session: z.ZodDefault<z.ZodNullable<z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>>>;
@@ -884,6 +943,7 @@ declare const TaskLinkageRefreshedEventSchema: z.ZodObject<{
884
943
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
885
944
  occurred_at: z.ZodString;
886
945
  source: z.ZodString;
946
+ prev_hash: z.ZodOptional<z.ZodString>;
887
947
  type: z.ZodLiteral<"task_linkage_refreshed">;
888
948
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
889
949
  added_linked_sessions: z.ZodDefault<z.ZodArray<z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>>>;
@@ -896,6 +956,7 @@ declare const TaskDeletedEventSchema: z.ZodObject<{
896
956
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
897
957
  occurred_at: z.ZodString;
898
958
  source: z.ZodString;
959
+ prev_hash: z.ZodOptional<z.ZodString>;
899
960
  type: z.ZodLiteral<"task_deleted">;
900
961
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
901
962
  title: z.ZodString;
@@ -906,6 +967,7 @@ declare const TaskArchivedEventSchema: z.ZodObject<{
906
967
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
907
968
  occurred_at: z.ZodString;
908
969
  source: z.ZodString;
970
+ prev_hash: z.ZodOptional<z.ZodString>;
909
971
  type: z.ZodLiteral<"task_archived">;
910
972
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
911
973
  title: z.ZodString;
@@ -916,6 +978,7 @@ declare const NoteAddedEventSchema: z.ZodObject<{
916
978
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
917
979
  occurred_at: z.ZodString;
918
980
  source: z.ZodString;
981
+ prev_hash: z.ZodOptional<z.ZodString>;
919
982
  type: z.ZodLiteral<"note_added">;
920
983
  body: z.ZodString;
921
984
  }, z.core.$strip>;
@@ -925,6 +988,7 @@ declare const AdapterOutputEventSchema: z.ZodObject<{
925
988
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
926
989
  occurred_at: z.ZodString;
927
990
  source: z.ZodString;
991
+ prev_hash: z.ZodOptional<z.ZodString>;
928
992
  type: z.ZodLiteral<"adapter_output">;
929
993
  stream: z.ZodEnum<{
930
994
  stdout: "stdout";
@@ -945,6 +1009,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
945
1009
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
946
1010
  occurred_at: z.ZodString;
947
1011
  source: z.ZodString;
1012
+ prev_hash: z.ZodOptional<z.ZodString>;
948
1013
  type: z.ZodLiteral<"session_started">;
949
1014
  }, z.core.$strip>, z.ZodObject<{
950
1015
  schema_version: z.ZodLiteral<"0.1.0">;
@@ -952,6 +1017,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
952
1017
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
953
1018
  occurred_at: z.ZodString;
954
1019
  source: z.ZodString;
1020
+ prev_hash: z.ZodOptional<z.ZodString>;
955
1021
  type: z.ZodLiteral<"session_ended">;
956
1022
  exit_code: z.ZodOptional<z.ZodNumber>;
957
1023
  }, z.core.$strip>, z.ZodObject<{
@@ -960,6 +1026,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
960
1026
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
961
1027
  occurred_at: z.ZodString;
962
1028
  source: z.ZodString;
1029
+ prev_hash: z.ZodOptional<z.ZodString>;
963
1030
  type: z.ZodLiteral<"session_status_changed">;
964
1031
  from: z.ZodString;
965
1032
  to: z.ZodString;
@@ -969,6 +1036,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
969
1036
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
970
1037
  occurred_at: z.ZodString;
971
1038
  source: z.ZodString;
1039
+ prev_hash: z.ZodOptional<z.ZodString>;
972
1040
  type: z.ZodLiteral<"approval_requested">;
973
1041
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
974
1042
  expires_at: z.ZodDefault<z.ZodNullable<z.ZodString>>;
@@ -989,6 +1057,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
989
1057
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
990
1058
  occurred_at: z.ZodString;
991
1059
  source: z.ZodString;
1060
+ prev_hash: z.ZodOptional<z.ZodString>;
992
1061
  type: z.ZodLiteral<"approval_approved">;
993
1062
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
994
1063
  resolver: z.ZodOptional<z.ZodString>;
@@ -999,6 +1068,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
999
1068
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1000
1069
  occurred_at: z.ZodString;
1001
1070
  source: z.ZodString;
1071
+ prev_hash: z.ZodOptional<z.ZodString>;
1002
1072
  type: z.ZodLiteral<"approval_rejected">;
1003
1073
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
1004
1074
  resolver: z.ZodOptional<z.ZodString>;
@@ -1009,6 +1079,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1009
1079
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1010
1080
  occurred_at: z.ZodString;
1011
1081
  source: z.ZodString;
1082
+ prev_hash: z.ZodOptional<z.ZodString>;
1012
1083
  type: z.ZodLiteral<"approval_expired">;
1013
1084
  approval_id: z.ZodString & z.ZodType<`appr_${string}`, string, z.core.$ZodTypeInternals<`appr_${string}`, string>>;
1014
1085
  }, z.core.$strip>, z.ZodObject<{
@@ -1017,6 +1088,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1017
1088
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1018
1089
  occurred_at: z.ZodString;
1019
1090
  source: z.ZodString;
1091
+ prev_hash: z.ZodOptional<z.ZodString>;
1020
1092
  type: z.ZodLiteral<"command_executed">;
1021
1093
  command: z.ZodString;
1022
1094
  args: z.ZodArray<z.ZodString>;
@@ -1031,6 +1103,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1031
1103
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1032
1104
  occurred_at: z.ZodString;
1033
1105
  source: z.ZodString;
1106
+ prev_hash: z.ZodOptional<z.ZodString>;
1034
1107
  type: z.ZodLiteral<"git_snapshot">;
1035
1108
  head: z.ZodString;
1036
1109
  branch: z.ZodString;
@@ -1046,6 +1119,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1046
1119
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1047
1120
  occurred_at: z.ZodString;
1048
1121
  source: z.ZodString;
1122
+ prev_hash: z.ZodOptional<z.ZodString>;
1049
1123
  type: z.ZodLiteral<"file_changed">;
1050
1124
  path: z.ZodString;
1051
1125
  change_type: z.ZodEnum<{
@@ -1061,6 +1135,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1061
1135
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1062
1136
  occurred_at: z.ZodString;
1063
1137
  source: z.ZodString;
1138
+ prev_hash: z.ZodOptional<z.ZodString>;
1064
1139
  type: z.ZodLiteral<"decision_recorded">;
1065
1140
  decision_id: z.ZodString & z.ZodType<`decision_${string}`, string, z.core.$ZodTypeInternals<`decision_${string}`, string>>;
1066
1141
  title: z.ZodString;
@@ -1075,6 +1150,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1075
1150
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1076
1151
  occurred_at: z.ZodString;
1077
1152
  source: z.ZodString;
1153
+ prev_hash: z.ZodOptional<z.ZodString>;
1078
1154
  type: z.ZodLiteral<"task_created">;
1079
1155
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
1080
1156
  title: z.ZodString;
@@ -1084,6 +1160,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1084
1160
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1085
1161
  occurred_at: z.ZodString;
1086
1162
  source: z.ZodString;
1163
+ prev_hash: z.ZodOptional<z.ZodString>;
1087
1164
  type: z.ZodLiteral<"task_status_changed">;
1088
1165
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
1089
1166
  from: z.ZodString;
@@ -1094,6 +1171,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1094
1171
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1095
1172
  occurred_at: z.ZodString;
1096
1173
  source: z.ZodString;
1174
+ prev_hash: z.ZodOptional<z.ZodString>;
1097
1175
  type: z.ZodLiteral<"task_reconciled">;
1098
1176
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
1099
1177
  removed_created_in_session: z.ZodDefault<z.ZodNullable<z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>>>;
@@ -1105,6 +1183,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1105
1183
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1106
1184
  occurred_at: z.ZodString;
1107
1185
  source: z.ZodString;
1186
+ prev_hash: z.ZodOptional<z.ZodString>;
1108
1187
  type: z.ZodLiteral<"task_linkage_refreshed">;
1109
1188
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
1110
1189
  added_linked_sessions: z.ZodDefault<z.ZodArray<z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>>>;
@@ -1116,6 +1195,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1116
1195
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1117
1196
  occurred_at: z.ZodString;
1118
1197
  source: z.ZodString;
1198
+ prev_hash: z.ZodOptional<z.ZodString>;
1119
1199
  type: z.ZodLiteral<"task_deleted">;
1120
1200
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
1121
1201
  title: z.ZodString;
@@ -1125,6 +1205,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1125
1205
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1126
1206
  occurred_at: z.ZodString;
1127
1207
  source: z.ZodString;
1208
+ prev_hash: z.ZodOptional<z.ZodString>;
1128
1209
  type: z.ZodLiteral<"task_archived">;
1129
1210
  task_id: z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
1130
1211
  title: z.ZodString;
@@ -1134,6 +1215,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1134
1215
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1135
1216
  occurred_at: z.ZodString;
1136
1217
  source: z.ZodString;
1218
+ prev_hash: z.ZodOptional<z.ZodString>;
1137
1219
  type: z.ZodLiteral<"note_added">;
1138
1220
  body: z.ZodString;
1139
1221
  }, z.core.$strip>, z.ZodObject<{
@@ -1142,6 +1224,7 @@ declare const EventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1142
1224
  session_id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
1143
1225
  occurred_at: z.ZodString;
1144
1226
  source: z.ZodString;
1227
+ prev_hash: z.ZodOptional<z.ZodString>;
1145
1228
  type: z.ZodLiteral<"adapter_output">;
1146
1229
  stream: z.ZodEnum<{
1147
1230
  stdout: "stdout";
@@ -1327,6 +1410,20 @@ declare const SessionMetricsSchema: z.ZodObject<{
1327
1410
  }, z.core.$strip>;
1328
1411
  /** Inferred runtime type for {@link SessionMetricsSchema}. */
1329
1412
  type SessionMetrics = z.infer<typeof SessionMetricsSchema>;
1413
+ /**
1414
+ * Tamper-evidence head anchor for sessions whose `events.jsonl` was written
1415
+ * with hash chaining (import / in-place re-import): `head_hash` is the hex
1416
+ * sha-256 of the last written event line (excluding the trailing newline),
1417
+ * `event_count` the number of chained lines. Absent on live / ad-hoc /
1418
+ * pre-feature sessions. Additive optional => no schema_version bump.
1419
+ * `.strict()` because the import writer fully owns the shape.
1420
+ */
1421
+ declare const SessionIntegritySchema: z.ZodObject<{
1422
+ head_hash: z.ZodString;
1423
+ event_count: z.ZodNumber;
1424
+ }, z.core.$strict>;
1425
+ /** Inferred runtime type for {@link SessionIntegritySchema}. */
1426
+ type SessionIntegrity = z.infer<typeof SessionIntegritySchema>;
1330
1427
  /**
1331
1428
  * Schema for `.basou/sessions/<session_id>/session.yaml`. The minimal
1332
1429
  * session document carries the actual fields nested under the outer
@@ -1350,6 +1447,7 @@ declare const SessionSchema: z.ZodObject<{
1350
1447
  }>;
1351
1448
  version: z.ZodLiteral<"0.1.0">;
1352
1449
  external_id: z.ZodOptional<z.ZodString>;
1450
+ source_size_bytes: z.ZodOptional<z.ZodNumber>;
1353
1451
  }, z.core.$strip>;
1354
1452
  started_at: z.ZodString;
1355
1453
  ended_at: z.ZodOptional<z.ZodString>;
@@ -1386,6 +1484,10 @@ declare const SessionSchema: z.ZodObject<{
1386
1484
  active_time_method: z.ZodOptional<z.ZodString>;
1387
1485
  machine_active_time_ms: z.ZodOptional<z.ZodNumber>;
1388
1486
  }, z.core.$strip>>;
1487
+ integrity: z.ZodOptional<z.ZodObject<{
1488
+ head_hash: z.ZodString;
1489
+ event_count: z.ZodNumber;
1490
+ }, z.core.$strict>>;
1389
1491
  }, z.core.$strip>;
1390
1492
  }, z.core.$strip>;
1391
1493
  /** Inferred runtime type for {@link SessionSchema}. */
@@ -1520,6 +1622,64 @@ type DecisionsRendererResult = {
1520
1622
  */
1521
1623
  declare function renderDecisions(input: DecisionsRendererInput): Promise<DecisionsRendererResult>;
1522
1624
 
1625
+ /**
1626
+ * Session-bound genesis hash: the `prev_hash` carried by the FIRST event line
1627
+ * of a chained `events.jsonl`. Binding the genesis to the session id means a
1628
+ * chain copied verbatim from another session fails verification at line 1
1629
+ * even though its internal back-pointers are intact.
1630
+ */
1631
+ declare function genesisHash(sessionId: string): string;
1632
+ /**
1633
+ * Hex sha-256 of one event line's written bytes (EXCLUDING the trailing
1634
+ * `\n`). The hash covers the literal serialized bytes — no canonical JSON
1635
+ * form. Writers pass the line string (always valid UTF-8, so its UTF-8
1636
+ * encoding IS the written bytes); the verifier passes the RAW BYTES it read,
1637
+ * so a byte-level mutation that decodes to the same string (e.g. an invalid
1638
+ * UTF-8 sequence collapsing to U+FFFD) still breaks the chain.
1639
+ */
1640
+ declare function lineHash(rawLine: string | Buffer): string;
1641
+ /**
1642
+ * The single serializer for event lines. Every writer (bulk and append) MUST
1643
+ * go through this function so the bytes a chain hashes can never diverge from
1644
+ * the bytes another code path would write.
1645
+ */
1646
+ declare function serializeEventLine(event: Event): string;
1647
+ /** Result of {@link chainEvents}: the serialized lines plus the head anchor inputs. */
1648
+ type ChainedEvents = {
1649
+ /** Serialized event lines (no trailing newline on the entries). */
1650
+ lines: string[];
1651
+ /**
1652
+ * Hex sha-256 of the LAST line — the value `session.yaml.integrity.head_hash`
1653
+ * anchors. For an empty batch this is the genesis hash and no anchor is
1654
+ * written.
1655
+ */
1656
+ headHash: string;
1657
+ /** Number of chained lines (= `integrity.event_count`). */
1658
+ count: number;
1659
+ };
1660
+ /**
1661
+ * Thread a `prev_hash` back-pointer through `events` and serialize them:
1662
+ * line 0 carries `genesisHash(sessionId)`, line N carries the hash of line
1663
+ * N-1's written bytes. Any `prev_hash` already present on an incoming event
1664
+ * (e.g. a round-trip import payload) is discarded and recomputed — chains are
1665
+ * never trusted from input, only derived at write time.
1666
+ */
1667
+ declare function chainEvents(events: ReadonlyArray<Event>, sessionId: string): ChainedEvents;
1668
+ /**
1669
+ * Chain PRE-EXISTING serialized event lines WITHOUT re-serializing them
1670
+ * through the schema layer: each original line is JSON-parsed, given a
1671
+ * `prev_hash`, and stringified again. Because `JSON.parse`/`JSON.stringify`
1672
+ * round-trips key insertion order and every value verbatim, the output line
1673
+ * is the original line with only the `prev_hash` member appended — no zod
1674
+ * key-stripping or default materialization can occur. Used by the in-place
1675
+ * rechain migration of pre-chaining imported sessions.
1676
+ *
1677
+ * Callers MUST gate validity first (non-empty, JSON-parseable,
1678
+ * schema-valid, byte-identical JSON round-trip); this helper assumes
1679
+ * parseable lines and throws raw on a parse failure.
1680
+ */
1681
+ declare function chainRawJsonLines(rawLines: ReadonlyArray<string>, sessionId: string): ChainedEvents;
1682
+
1523
1683
  /**
1524
1684
  * Append a single Basou event to `<sessionDir>/events.jsonl`.
1525
1685
  *
@@ -1528,6 +1688,11 @@ declare function renderDecisions(input: DecisionsRendererInput): Promise<Decisio
1528
1688
  * Validation enforces the per-variant contract (required fields, source
1529
1689
  * vocabulary, strict variants such as `adapter_output`).
1530
1690
  *
1691
+ * Appended lines are NOT hash-chained: chaining is exclusive to the bulk
1692
+ * import writers ({@link writeEventsBulk} with `chain: true`), and imported
1693
+ * sessions reject every append path, so a chained file never receives an
1694
+ * unchained appended line.
1695
+ *
1531
1696
  * Atomicity: writes go through `appendFile` which uses `O_APPEND`. Lines up
1532
1697
  * to `PIPE_BUF` bytes (Linux 4096 / macOS 512) are written atomically by the
1533
1698
  * kernel; longer lines may interleave with concurrent writers and are not
@@ -1541,6 +1706,23 @@ declare function renderDecisions(input: DecisionsRendererInput): Promise<Decisio
1541
1706
  * @param event unknown payload to validate and append
1542
1707
  */
1543
1708
  declare function appendEvent(sessionDir: string, event: unknown): Promise<void>;
1709
+ /** Options for {@link writeEventsBulk}. */
1710
+ type WriteEventsBulkOptions = {
1711
+ /**
1712
+ * Thread a per-line `prev_hash` hash chain through the batch and return the
1713
+ * head anchor inputs. Used ONLY by the import writers (fresh import and
1714
+ * in-place re-import); defaults to false so the live / ad-hoc writers keep
1715
+ * producing plain unchained lines.
1716
+ */
1717
+ chain?: boolean;
1718
+ };
1719
+ /** Head anchor inputs returned by a chained {@link writeEventsBulk}. */
1720
+ type BulkChainResult = {
1721
+ /** Hex sha-256 of the last written line (excluding the trailing `\n`). */
1722
+ headHash: string;
1723
+ /** Number of chained lines written. */
1724
+ count: number;
1725
+ };
1544
1726
  /**
1545
1727
  * Write `events.jsonl` in one atomic tmp+rename pass via {@link atomicReplace},
1546
1728
  * validating every event against {@link EventSchema} before any disk I/O so
@@ -1551,12 +1733,100 @@ declare function appendEvent(sessionDir: string, event: unknown): Promise<void>;
1551
1733
  * of events must land together or not at all. Zero events produces a
1552
1734
  * zero-byte file so the session_yaml `events_log` pointer remains valid.
1553
1735
  *
1736
+ * With `options.chain` set, each line is written with a `prev_hash`
1737
+ * back-pointer (any incoming `prev_hash` is discarded and recomputed; the
1738
+ * chain's genesis is bound to `basename(sessionDir)` = the session id) and
1739
+ * the head anchor inputs are returned so the caller can persist
1740
+ * `session.yaml.integrity`. An empty chained batch writes a zero-byte file
1741
+ * and returns null — no anchor. Without `chain` the return value is null and
1742
+ * the written bytes are identical to the previous unchained format.
1743
+ *
1554
1744
  * Throws `"Invalid Basou event payload"` (same fixed message as
1555
1745
  * {@link appendEvent}) on validation failure, or `"Failed to write
1556
1746
  * events.jsonl"` on a disk I/O failure. The original native error is attached
1557
1747
  * as `cause`.
1558
1748
  */
1559
- declare function writeEventsBulk(sessionDir: string, events: Event[]): Promise<void>;
1749
+ declare function writeEventsBulk(sessionDir: string, events: Event[], options?: WriteEventsBulkOptions): Promise<BulkChainResult | null>;
1750
+
1751
+ /**
1752
+ * Verification outcome for one session's `events.jsonl`.
1753
+ *
1754
+ * - `unchained` — no event line carries `prev_hash` (live / ad-hoc / legacy
1755
+ * session) and `session.yaml` carries no integrity anchor. Informational.
1756
+ * - `empty` — zero events and no integrity anchor. Informational.
1757
+ * - `incomplete` — the log is chained but `session.yaml` is ENTIRELY absent
1758
+ * (an import crashed between the events write and the yaml write, or the
1759
+ * yaml was deleted out of band). Benign: a re-import / `--force` repairs it.
1760
+ * - `tampered` — a real integrity break (see {@link ChainBreakReason}).
1761
+ * - `verified` — every back-pointer, genesis, session-id and line-discipline
1762
+ * check passed AND the head anchor matches the on-disk log.
1763
+ */
1764
+ type ChainVerdictStatus = "verified" | "unchained" | "empty" | "incomplete" | "tampered";
1765
+ /** Machine-readable detail for a `tampered` (or `incomplete`) verdict. */
1766
+ type ChainBreakReason =
1767
+ /** The file does not end with `\n`; chained writers always terminate the last line. */
1768
+ "torn_tail"
1769
+ /** A blank line inside a chained log; chained writers never emit one. */
1770
+ | "blank_line"
1771
+ /** A line of a chained log failed JSON parsing; writers only emit valid JSON. */
1772
+ | "malformed_line"
1773
+ /** A chained log has a line without `prev_hash`; chained writers chain every line. */
1774
+ | "missing_prev_hash"
1775
+ /** Line 1's `prev_hash` is not this session's genesis hash (edit or cross-session copy). */
1776
+ | "genesis_mismatch"
1777
+ /** A line's `prev_hash` does not hash-match the previous line (edit / insert / delete / reorder). */
1778
+ | "broken_link"
1779
+ /** A line's `session_id` is not this session's id (cross-session copied line). */
1780
+ | "session_id_mismatch"
1781
+ /** `session.yaml` exists but its `integrity` anchor is missing (anchor stripped). */
1782
+ | "anchor_missing"
1783
+ /** The anchor's `head_hash` / `event_count` disagree with the on-disk log (edit or truncation). */
1784
+ | "anchor_mismatch"
1785
+ /** An integrity anchor exists but the log is unchained, empty, or missing (chain stripped). */
1786
+ | "anchor_without_chain"
1787
+ /** `session.yaml` exists but could not be parsed / validated, so the anchor is unreadable. */
1788
+ | "yaml_unreadable"
1789
+ /** `incomplete` only: `session.yaml` is entirely absent. */
1790
+ | "yaml_missing";
1791
+ /** Result of {@link verifyEventsChain}. */
1792
+ type ChainVerdict = {
1793
+ status: ChainVerdictStatus;
1794
+ /** Complete (newline-terminated) event lines found on disk. */
1795
+ eventCount: number;
1796
+ /** Detail for `tampered` / `incomplete`; absent otherwise. */
1797
+ reason?: ChainBreakReason;
1798
+ /** 1-based line number of the first break, when one specific line broke. */
1799
+ line?: number;
1800
+ };
1801
+ /**
1802
+ * Verify the tamper-evidence hash chain of `<sessions>/<sessionId>/events.jsonl`
1803
+ * against the head anchor in `session.yaml.integrity`. READ-ONLY.
1804
+ *
1805
+ * The verifier reads the RAW line BYTES (not the schema-filtering replay
1806
+ * reader, which silently drops bad lines; and not a decoded string, which
1807
+ * would collapse invalid UTF-8 sequences into U+FFFD and let a byte-level
1808
+ * substitution survive re-hashing) and hashes exactly the bytes it read.
1809
+ * The verdict is decided on the events first, then the anchor:
1810
+ *
1811
+ * - No line carries `prev_hash` (or there are zero lines / no file): the log
1812
+ * is unchained. If `session.yaml` nevertheless carries an integrity anchor,
1813
+ * the chain was stripped out of band => `tampered` (`anchor_without_chain`);
1814
+ * otherwise `unchained` / `empty`.
1815
+ * - At least one line carries `prev_hash`: the log claims to be chained, and
1816
+ * every check applies — line discipline (terminating `\n`, no blank lines,
1817
+ * valid JSON), genesis binding, per-line back-pointers, per-line session id,
1818
+ * and finally the head anchor (`incomplete` when `session.yaml` is entirely
1819
+ * absent; `tampered` when it is present without a matching anchor).
1820
+ *
1821
+ * NON-CRYPTOGRAPHIC: the anchor lives in `session.yaml`, which is itself
1822
+ * editable; an attacker rewriting BOTH files consistently is not detected.
1823
+ * Signing is a follow-up.
1824
+ *
1825
+ * Throws `Error("Failed to read events.jsonl")` only for non-ENOENT I/O
1826
+ * failures (EACCES etc.) — an unreadable file is an environment problem, not
1827
+ * a verdict.
1828
+ */
1829
+ declare function verifyEventsChain(paths: BasouPaths, sessionId: string): Promise<ChainVerdict>;
1560
1830
 
1561
1831
  /**
1562
1832
  * Status classification used by the `file_changed` event schema. Limited to
@@ -3120,6 +3390,9 @@ type LockHandle = {
3120
3390
  *
3121
3391
  * Acquisition strategy:
3122
3392
  * 1. {@link atomicCreate} the lockfile (POSIX link(2) + EEXIST).
3393
+ * On ENOENT (a workspace from before `.basou/locks/` existed), create
3394
+ * the directory and retry once; a retry failure throws the pathless
3395
+ * `"Failed to acquire lock"`.
3123
3396
  * 2. On EEXIST, probe the existing lockfile via {@link isStaleLock}.
3124
3397
  * - If stale (= holder pid is dead or lock is older than
3125
3398
  * {@link STALE_LOCK_MAX_AGE_MS}), `unlink` the stale file and retry
@@ -3306,6 +3579,80 @@ type ImportSessionResult = {
3306
3579
  * for `--verbose` rendering.
3307
3580
  */
3308
3581
  declare function importSessionFromJson(paths: BasouPaths, manifest: Manifest, payload: SessionImportPayload, options: ImportSessionOptions): Promise<ImportSessionResult>;
3582
+ /** Whether `source` is one of the known import-derived event sources. */
3583
+ declare function isImportDerivedSource(source: string): boolean;
3584
+ /** Options for {@link reimportPreservingId}. */
3585
+ type ReimportOptions = {
3586
+ /** Compute the re-import and return its preview without writing to disk. */
3587
+ dryRun?: boolean;
3588
+ };
3589
+ /** Result of {@link reimportPreservingId}. */
3590
+ type ReimportResult = {
3591
+ status: "reimported";
3592
+ sessionId: PrefixedId<"ses">;
3593
+ /** Total events written to the merged `events.jsonl`. */
3594
+ eventCount: number;
3595
+ /** Non-derived events (human / unknown source) carried over unchanged. */
3596
+ preservedCount: number;
3597
+ /** Derived events whose prior id (and decision_id) was reused. */
3598
+ reusedIdCount: number;
3599
+ } | {
3600
+ status: "skipped";
3601
+ reason: "prior_events_unreadable" | "prior_derived_dropped" | "prior_chain_broken";
3602
+ };
3603
+ /**
3604
+ * Re-import a source whose native log GREW into the SAME Basou session,
3605
+ * preserving its id and any non-derived events, instead of skipping it (default
3606
+ * dedup) or deleting + recreating it (`--force`). The caller has already
3607
+ * validated `freshPayload` and confirmed (by source byte size) that the source
3608
+ * changed; this function re-derives the adapter's events, reuses prior derived
3609
+ * event ids for unchanged derivations (so `linked_events` references survive),
3610
+ * preserves human / unknown-source events, and rewrites `events.jsonl` +
3611
+ * `session.yaml` atomically under the session lock.
3612
+ *
3613
+ * The whole read-modify-write runs under {@link acquireLock} so a concurrent
3614
+ * writer cannot interleave; `dryRun` computes the result and writes nothing
3615
+ * (and takes no lock). If the prior `events.jsonl` has any line that cannot be
3616
+ * preserved (malformed / schema-invalid / half-written), the re-import is
3617
+ * ABORTED (`status: "skipped"`) rather than risk dropping data on the rewrite.
3618
+ */
3619
+ declare function reimportPreservingId(paths: BasouPaths, manifest: Manifest, priorSessionId: string, freshPayload: SessionImportPayload, options?: ReimportOptions): Promise<ReimportResult>;
3620
+ /** Options for {@link rechainSessionInPlace}. */
3621
+ type RechainOptions = {
3622
+ /**
3623
+ * Compute the outcome and write nothing. The session lock is STILL taken:
3624
+ * an unlocked read could observe a concurrent in-place re-import's
3625
+ * two-file write window (events rewritten, yaml not yet) and report a
3626
+ * state a locked run would never see.
3627
+ */
3628
+ dryRun?: boolean;
3629
+ };
3630
+ /** Result of {@link rechainSessionInPlace}. */
3631
+ type RechainResult = {
3632
+ status: "rechained";
3633
+ eventCount: number;
3634
+ } | {
3635
+ status: "skipped";
3636
+ reason: "already_chained" | "empty" | "not_imported" | "tampered" | "events_unreadable" | "session_id_mismatch" | "yaml_missing" | "yaml_unreadable";
3637
+ };
3638
+ /**
3639
+ * Add the tamper-evidence hash chain, IN PLACE, to an imported session that
3640
+ * was written before chaining existed (or whose chain was legitimately never
3641
+ * computed). Event ids, order, field sets, values and key order are all
3642
+ * preserved exactly — each original line is re-emitted with only `prev_hash`
3643
+ * appended (see {@link chainRawJsonLines}); `session.yaml` is rewritten as
3644
+ * read with only `integrity` added. Nothing else changes, so cross-session
3645
+ * references (`linked_events`) survive, unlike a `--force` re-import.
3646
+ *
3647
+ * Rechaining asserts tamper-evidence FROM NOW ON; it does not retroactively
3648
+ * prove the pre-existing content was never modified before the migration.
3649
+ *
3650
+ * Refuses anything it cannot preserve exactly or that is not the closed
3651
+ * imported corpus — see {@link RechainResult} reasons. Throws (rather than
3652
+ * returning a skip) on environment-level I/O failures, mirroring
3653
+ * `verifyEventsChain`.
3654
+ */
3655
+ declare function rechainSessionInPlace(paths: BasouPaths, sessionId: string, options?: RechainOptions): Promise<RechainResult>;
3309
3656
 
3310
3657
  /**
3311
3658
  * Walk the cause chain (up to `depth` levels) looking for an Error whose
@@ -3407,4 +3754,4 @@ declare function overwriteYamlFile(filePath: string, value: unknown): Promise<vo
3407
3754
  */
3408
3755
  declare const BASOU_CORE_VERSION = "0.1.0";
3409
3756
 
3410
- export { ACTIVE_GAP_CAP_MS, type ActiveTimeBasis, type AdapterOutputEvent, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, ChildProcessRunner, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, FailedToFinalizeError, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type MeasureAvailability, type NoteAddedEvent, type PrefixedId, type ProcessRunner, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReplayOptions, type ReplayWarning, type RiskLevel, RiskLevelSchema, type RunOptions, type RunResult, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type SuspectReason, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, findErrorCode, getDiff, getSnapshot, importSessionFromJson, isLazyExpired, isValidPrefixedId, linkYamlFile, loadApproval, loadSessionEntries, loadTaskEntries, overwriteYamlFile, parseDuration, parseMarkers, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, reconcileAllTasks, reconcileTask, refreshTaskLinkedSessions, renderDecisions, renderHandoff, renderWithMarkers, replayEvents, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, tryRemoteUrl, ulid, updateTaskStatusWithEvent, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
3757
+ export { ACTIVE_GAP_CAP_MS, type ActiveTimeBasis, type AdapterOutputEvent, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, type BulkChainResult, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, type ChainBreakReason, type ChainVerdict, type ChainVerdictStatus, type ChainedEvents, ChildProcessRunner, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, FailedToFinalizeError, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type MeasureAvailability, type NoteAddedEvent, type PrefixedId, type ProcessRunner, type RechainOptions, type RechainResult, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReimportOptions, type ReimportResult, type ReplayOptions, type ReplayWarning, type RiskLevel, RiskLevelSchema, type RunOptions, type RunResult, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionIntegrity, SessionIntegritySchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type SuspectReason, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WriteEventsBulkOptions, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, chainEvents, chainRawJsonLines, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, findErrorCode, genesisHash, getDiff, getSnapshot, importSessionFromJson, isImportDerivedSource, isLazyExpired, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadSessionEntries, loadTaskEntries, overwriteYamlFile, parseDuration, parseMarkers, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, renderDecisions, renderHandoff, renderWithMarkers, replayEvents, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, tryRemoteUrl, ulid, updateTaskStatusWithEvent, verifyEventsChain, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };