@effect-agent/storage-cloudflare 0.1.0-beta.42 → 0.1.0-beta.45

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/src/do-ledger.ts CHANGED
@@ -290,9 +290,11 @@ const decodeSuspensionSnapshot = Schema.decodeUnknownEffect(SuspensionSnapshot);
290
290
  const decodeApprovalDecisionIntent = Schema.decodeUnknownEffect(ApprovalDecisionIntent);
291
291
  const decodeUnknownResolutionIntent = Schema.decodeUnknownEffect(UnknownResolutionIntent);
292
292
  const decodeParentLinkage = Schema.decodeUnknownEffect(ParentLinkage);
293
+
293
294
  const decodeChildReservationSnapshotUnknown = Schema.decodeUnknownEffect(
294
295
  ChildBudgetReservationSnapshot,
295
296
  );
297
+
296
298
  const decodeChildAttachmentSnapshot = Schema.decodeUnknownEffect(ChildAttachmentSnapshot);
297
299
  const equivalentPersistedJson = Schema.toEquivalence(PersistedJson);
298
300
  const equivalentUnknownResolution = Schema.toEquivalence(UnknownResolution);
@@ -394,7 +396,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
394
396
  FROM effect_agent_submissions
395
397
  WHERE submission_id = ${submissionId}
396
398
  `.pipe(Effect.mapError(sqlFailure(operation)));
399
+
397
400
  const decoded = yield* decodeSubmissionRows(operation, submissionId, rows);
401
+
398
402
  if (decoded.length > 1) {
399
403
  return yield* corruptionFailure(
400
404
  operation,
@@ -403,6 +407,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
403
407
  "A submission primary key returned more than one row.",
404
408
  );
405
409
  }
410
+
406
411
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
407
412
  });
408
413
 
@@ -411,12 +416,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
411
416
  submissionId: string,
412
417
  ): Effect.fn.Return<SubmissionRow, LedgerError> {
413
418
  const submission = yield* readSubmission(operation, submissionId);
419
+
414
420
  if (Option.isNone(submission)) {
415
421
  return yield* LedgerError.make({
416
422
  operation,
417
423
  message: `Unknown submission ${submissionId}.`,
418
424
  });
419
425
  }
426
+
420
427
  return submission.value;
421
428
  });
422
429
 
@@ -435,12 +442,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
435
442
  FROM effect_agent_submission_ownership
436
443
  WHERE submission_id = ${submissionId}
437
444
  `.pipe(Effect.mapError(sqlFailure(operation)));
445
+
438
446
  const decoded = yield* decodeRows(
439
447
  Schema.Array(OwnershipRow),
440
448
  "effect_agent_submission_ownership",
441
449
  submissionId,
442
450
  rows,
443
451
  ).pipe(Effect.mapError(internalFailure(operation)));
452
+
444
453
  if (decoded.length > 1) {
445
454
  return yield* corruptionFailure(
446
455
  operation,
@@ -449,6 +458,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
449
458
  "An ownership primary key returned more than one row.",
450
459
  );
451
460
  }
461
+
452
462
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
453
463
  });
454
464
 
@@ -459,6 +469,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
459
469
  const threads = yield* journal
460
470
  .getThread(threadId)
461
471
  .pipe(Effect.mapError(internalFailure(operation)));
472
+
462
473
  return threads.length === 0 ? EPOCH_ZERO : threads[0].producer_epoch;
463
474
  });
464
475
 
@@ -473,13 +484,17 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
473
484
  ownershipToken: string,
474
485
  ): Effect.fn.Return<OwnershipRow, OwnershipLost | LedgerError> {
475
486
  const ownership = yield* readOwnership(operation, submission.submission_id);
487
+
476
488
  if (Option.isNone(ownership) || ownership.value.ownership_token !== ownershipToken) {
477
489
  const actualEpoch = yield* threadEpoch(operation, submission.thread_id);
490
+
478
491
  const submissionId = yield* Schema.decodeUnknownEffect(
479
492
  SubmissionSnapshot.fields.submissionId,
480
493
  )(submission.submission_id).pipe(Effect.mapError(internalFailure(operation)));
494
+
481
495
  return yield* OwnershipLost.make({ submissionId, actualEpoch });
482
496
  }
497
+
483
498
  return ownership.value;
484
499
  });
485
500
 
@@ -498,6 +513,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
498
513
  ),
499
514
  ),
500
515
  );
516
+
501
517
  const inputPayload = yield* parseStoredJsonText(row.input_json).pipe(
502
518
  Effect.mapError((error) =>
503
519
  corruptionFailure(
@@ -508,6 +524,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
508
524
  ),
509
525
  ),
510
526
  );
527
+
511
528
  if ((row.parent_submission_id === null) !== (row.parent_tool_call_id === null)) {
512
529
  return yield* corruptionFailure(
513
530
  operation,
@@ -516,6 +533,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
516
533
  "A parent linkage must record both the parent Submission and the parent Tool Call.",
517
534
  );
518
535
  }
536
+
519
537
  return yield* decodeSubmissionSnapshotUnknown({
520
538
  submissionId: row.submission_id,
521
539
  threadId: row.thread_id,
@@ -570,12 +588,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
570
588
  FROM effect_agent_settlement_reservations
571
589
  WHERE submission_id = ${submissionId}
572
590
  `.pipe(Effect.mapError(sqlFailure(operation)));
591
+
573
592
  const decoded = yield* decodeRows(
574
593
  Schema.Array(ReservationRow),
575
594
  "effect_agent_settlement_reservations",
576
595
  submissionId,
577
596
  rows,
578
597
  ).pipe(Effect.mapError(internalFailure(operation)));
598
+
579
599
  if (decoded.length > 1) {
580
600
  return yield* corruptionFailure(
581
601
  operation,
@@ -584,6 +604,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
584
604
  "A settlement reservation primary key returned more than one row.",
585
605
  );
586
606
  }
607
+
587
608
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
588
609
  });
589
610
 
@@ -601,12 +622,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
601
622
  FROM effect_agent_abort_intents
602
623
  WHERE submission_id = ${submissionId}
603
624
  `.pipe(Effect.mapError(sqlFailure(operation)));
625
+
604
626
  const decoded = yield* decodeRows(
605
627
  Schema.Array(AbortIntentRow),
606
628
  "effect_agent_abort_intents",
607
629
  submissionId,
608
630
  rows,
609
631
  ).pipe(Effect.mapError(internalFailure(operation)));
632
+
610
633
  if (decoded.length > 1) {
611
634
  return yield* corruptionFailure(
612
635
  operation,
@@ -615,6 +638,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
615
638
  "An abort intent primary key returned more than one row.",
616
639
  );
617
640
  }
641
+
618
642
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
619
643
  });
620
644
 
@@ -638,6 +662,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
638
662
  WHERE parent_submission_id = ${parentSubmissionId}
639
663
  ORDER BY child_submission_id ASC
640
664
  `.pipe(Effect.mapError(sqlFailure(operation)));
665
+
641
666
  return yield* decodeRows(
642
667
  Schema.Array(ChildSettlementMarkerRow),
643
668
  "effect_agent_child_settlements",
@@ -660,6 +685,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
660
685
  ): Effect.fn.Return<boolean, LedgerError> {
661
686
  if (markerChildren.has(childSubmissionId)) return true;
662
687
  const childRow = yield* readSubmission(operation, childSubmissionId);
688
+
663
689
  return Option.isSome(childRow) && childRow.value.state === "settled";
664
690
  });
665
691
 
@@ -680,7 +706,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
680
706
  FROM effect_agent_child_reservations
681
707
  WHERE reservation_id = ${reservationId}
682
708
  `.pipe(Effect.mapError(sqlFailure(operation)));
709
+
683
710
  const decoded = yield* decodeChildReservationRows(operation, reservationId, rows);
711
+
684
712
  if (decoded.length > 1) {
685
713
  return yield* corruptionFailure(
686
714
  operation,
@@ -689,6 +717,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
689
717
  "A child reservation primary key returned more than one row.",
690
718
  );
691
719
  }
720
+
692
721
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
693
722
  });
694
723
 
@@ -704,11 +733,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
704
733
  WHERE parent_submission_id = ${parentSubmissionId}
705
734
  AND parent_tool_call_id = ${parentToolCallId}
706
735
  `.pipe(Effect.mapError(sqlFailure(operation)));
736
+
707
737
  const decoded = yield* decodeChildReservationRows(
708
738
  operation,
709
739
  `${parentSubmissionId}/${parentToolCallId}`,
710
740
  rows,
711
741
  );
742
+
712
743
  if (decoded.length > 1) {
713
744
  return yield* corruptionFailure(
714
745
  operation,
@@ -717,6 +748,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
717
748
  "A parent Tool Call returned more than one child reservation.",
718
749
  );
719
750
  }
751
+
720
752
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
721
753
  },
722
754
  );
@@ -734,13 +766,16 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
734
766
  row.reservation_id,
735
767
  error.message,
736
768
  );
769
+
737
770
  const allocation = yield* parseStoredJsonText(row.allocation_json).pipe(
738
771
  Effect.mapError(rowFailure),
739
772
  );
773
+
740
774
  const accounting =
741
775
  row.accounting_json === null
742
776
  ? undefined
743
777
  : yield* parseStoredJsonText(row.accounting_json).pipe(Effect.mapError(rowFailure));
778
+
744
779
  return yield* decodeChildReservationSnapshotUnknown({
745
780
  reservationId: row.reservation_id,
746
781
  parentSubmissionId: row.parent_submission_id,
@@ -772,6 +807,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
772
807
  WHERE submission_id = ${submissionId}
773
808
  ORDER BY tool_call_id ASC
774
809
  `.pipe(Effect.mapError(sqlFailure(operation)));
810
+
775
811
  return yield* decodeRows(
776
812
  Schema.Array(ApprovalDecisionRow),
777
813
  "effect_agent_approval_decisions",
@@ -819,6 +855,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
819
855
  WHERE submission_id = ${submissionId}
820
856
  ORDER BY tool_call_id ASC
821
857
  `.pipe(Effect.mapError(sqlFailure(operation)));
858
+
822
859
  return yield* decodeRows(
823
860
  Schema.Array(UnknownResolutionRow),
824
861
  "effect_agent_unknown_resolutions",
@@ -843,6 +880,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
843
880
  ),
844
881
  ),
845
882
  );
883
+
846
884
  return yield* decodeUnknownResolutionIntent({
847
885
  submissionId: row.submission_id,
848
886
  toolCallId: row.tool_call_id,
@@ -869,6 +907,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
869
907
  submission: SubmissionRow,
870
908
  ): Effect.fn.Return<ReadonlyArray<typeof ToolCallIdSchema.Type>, LedgerError> {
871
909
  if (submission.unknown_tool_call_ids_json === null) return [];
910
+
872
911
  return yield* decodeToolCallIdsText(submission.unknown_tool_call_ids_json).pipe(
873
912
  Effect.mapError((error) =>
874
913
  corruptionFailure(
@@ -893,18 +932,21 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
893
932
  submissionId: SubmissionId,
894
933
  ): Effect.fn.Return<string | undefined, LedgerError> {
895
934
  const recordId = submissionAbortRecordId(submissionId);
935
+
896
936
  const rows = yield* sql<Record<string, unknown>>`
897
937
  SELECT record_id
898
938
  FROM effect_agent_canonical_records
899
939
  WHERE thread_id = ${threadId}
900
940
  AND record_id = ${recordId}
901
941
  `.pipe(Effect.mapError(sqlFailure(operation)));
942
+
902
943
  const decoded = yield* decodeRows(
903
944
  Schema.Array(CanonicalRecordIdRow),
904
945
  "effect_agent_canonical_records",
905
946
  `${threadId}/${recordId}`,
906
947
  rows,
907
948
  ).pipe(Effect.mapError(internalFailure(operation)));
949
+
908
950
  return decoded.length === 0 ? undefined : recordId;
909
951
  });
910
952
 
@@ -919,6 +961,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
919
961
  submission.thread_id,
920
962
  submissionId,
921
963
  );
964
+
922
965
  return yield* decodeAbortIntent({
923
966
  submissionId: row.submission_id,
924
967
  author: row.author,
@@ -947,25 +990,31 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
947
990
  const admit: SubmissionLedger["Service"]["admit"] = Effect.fn("DoSubmissionLedger.admit")(
948
991
  function* (request: AdmissionRequest) {
949
992
  const operation = "ledger admit";
993
+
950
994
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(AdmissionRequest))(
951
995
  request,
952
996
  ).pipe(Effect.mapError(internalFailure(operation)));
997
+
953
998
  const inputJson = yield* encodePersistedJsonText(validated.inputPayload).pipe(
954
999
  Effect.mapError(internalFailure(operation)),
955
1000
  );
1001
+
956
1002
  // The platform's ~2 MB per-value bound, refused typed BEFORE any durable mutation
957
1003
  // (resource-limits gate; oversized payloads are the designed R2 overflow path).
958
1004
  yield* journal
959
1005
  .checkValueBound(operation, inputJson)
960
1006
  .pipe(Effect.mapError(internalFailure(operation)));
1007
+
961
1008
  const agentDigestsJson = yield* encodeDefinitionDigestsText(validated.agentDigests).pipe(
962
1009
  Effect.mapError(internalFailure(operation)),
963
1010
  );
1011
+
964
1012
  // Routable Submission identity (D-P6-5): `{uuidv7}:{threadId}`. The cross-DO
965
1013
  // routing layer parses ITS OWN minted format (split at the first ":") to address
966
1014
  // submissionId-only operations to the owning Thread Object; the id stays opaque
967
1015
  // to every other component, exactly like DN's `submission-{uuid}` prefix.
968
1016
  const mintedSubmissionId = `${yield* mintUuid(operation)}:${validated.threadId}`;
1017
+
969
1018
  if (mintedSubmissionId.length > MAX_IDENTIFIER_LENGTH) {
970
1019
  return yield* LedgerError.make({
971
1020
  operation,
@@ -975,11 +1024,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
975
1024
  });
976
1025
  }
977
1026
  const mintedReceiptId = `receipt-${yield* mintUuid(operation)}`;
1027
+
978
1028
  yield* hitFailpoint("ledger:admit:before", operation);
1029
+
979
1030
  const result = yield* inWriteTransaction(
980
1031
  operation,
981
1032
  Effect.gen(function* () {
982
1033
  const keyRowKey = `${validated.threadId}/${validated.principal}/${validated.idempotencyKey}`;
1034
+
983
1035
  const existingRows = yield* sql<Record<string, unknown>>`
984
1036
  SELECT ${sql.literal(SUBMISSION_COLUMNS)}
985
1037
  FROM effect_agent_submissions
@@ -987,7 +1039,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
987
1039
  AND principal = ${validated.principal}
988
1040
  AND idempotency_key = ${validated.idempotencyKey}
989
1041
  `.pipe(Effect.mapError(sqlFailure(operation)));
1042
+
990
1043
  const existing = yield* decodeSubmissionRows(operation, keyRowKey, existingRows);
1044
+
991
1045
  if (existing.length > 1) {
992
1046
  return yield* corruptionFailure(
993
1047
  operation,
@@ -1005,6 +1059,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1005
1059
  existing[0].parent_tool_call_id === null
1006
1060
  : existing[0].parent_submission_id === validated.parentLinkage.parentSubmissionId &&
1007
1061
  existing[0].parent_tool_call_id === validated.parentLinkage.parentToolCallId;
1062
+
1008
1063
  if (existing[0].input_digest !== validated.inputDigest || !sameLinkage) {
1009
1064
  return yield* AdmissionConflict.make({
1010
1065
  threadId: validated.threadId,
@@ -1014,6 +1069,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1014
1069
  attemptedInputDigest: validated.inputDigest,
1015
1070
  });
1016
1071
  }
1072
+
1017
1073
  return yield* decodeAdmissionResult({
1018
1074
  submissionId: existing[0].submission_id,
1019
1075
  receiptId: existing[0].receipt_id,
@@ -1028,15 +1084,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1028
1084
  FROM effect_agent_submissions
1029
1085
  WHERE thread_id = ${validated.threadId}
1030
1086
  `.pipe(Effect.mapError(sqlFailure(operation)));
1087
+
1031
1088
  const decodedMax = yield* decodeRows(
1032
1089
  Schema.Array(MaxQueueSequenceRow),
1033
1090
  "effect_agent_submissions",
1034
1091
  validated.threadId,
1035
1092
  maxRows,
1036
1093
  ).pipe(Effect.mapError(internalFailure(operation)));
1094
+
1037
1095
  const queueSequence = yield* decodeQueueSequence(
1038
1096
  (decodedMax[0]?.max_queue_sequence ?? 0) + 1,
1039
1097
  ).pipe(Effect.mapError(internalFailure(operation)));
1098
+
1040
1099
  const now = yield* currentInstant;
1041
1100
 
1042
1101
  yield* sql`
@@ -1084,7 +1143,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1084
1143
  }).pipe(Effect.mapError(internalFailure(operation)));
1085
1144
  }),
1086
1145
  );
1146
+
1087
1147
  yield* hitFailpoint("ledger:admit:after", operation);
1148
+
1088
1149
  return result;
1089
1150
  },
1090
1151
  );
@@ -1093,16 +1154,20 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1093
1154
  "DoSubmissionLedger.markReady",
1094
1155
  )(function* (request: MarkReadyRequest) {
1095
1156
  const operation = "ledger mark ready";
1157
+
1096
1158
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(MarkReadyRequest))(
1097
1159
  request,
1098
1160
  ).pipe(Effect.mapError(internalFailure(operation)));
1161
+
1099
1162
  yield* hitFailpoint("ledger:mark-ready:before", operation);
1100
1163
  yield* inWriteTransaction(
1101
1164
  operation,
1102
1165
  Effect.gen(function* () {
1103
1166
  const submission = yield* requireSubmission(operation, validated.submissionId);
1167
+
1104
1168
  if (submission.state !== "admitted") return;
1105
1169
  const now = yield* currentInstant;
1170
+
1106
1171
  yield* sql`
1107
1172
  UPDATE effect_agent_submissions
1108
1173
  SET state = 'ready', ready_at = ${now.iso}
@@ -1116,14 +1181,19 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1116
1181
  const lookup: SubmissionLedger["Service"]["lookup"] = Effect.fn("DoSubmissionLedger.lookup")(
1117
1182
  function* (request: SubmissionLookup) {
1118
1183
  const operation = "ledger lookup";
1184
+
1119
1185
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SubmissionLookup))(
1120
1186
  request,
1121
1187
  ).pipe(Effect.mapError(internalFailure(operation)));
1188
+
1122
1189
  if (validated._tag === "SubmissionLookupById") {
1123
1190
  const row = yield* readSubmission(operation, validated.submissionId);
1191
+
1124
1192
  if (Option.isNone(row)) return Option.none();
1193
+
1125
1194
  return Option.some(yield* decodeSubmissionSnapshot(operation, row.value));
1126
1195
  }
1196
+
1127
1197
  const rows = yield* sql<Record<string, unknown>>`
1128
1198
  SELECT ${sql.literal(SUBMISSION_COLUMNS)}
1129
1199
  FROM effect_agent_submissions
@@ -1131,11 +1201,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1131
1201
  AND principal = ${validated.principal}
1132
1202
  AND idempotency_key = ${validated.idempotencyKey}
1133
1203
  `.pipe(Effect.mapError(sqlFailure(operation)));
1204
+
1134
1205
  const decoded = yield* decodeSubmissionRows(
1135
1206
  operation,
1136
1207
  `${validated.threadId}/${validated.principal}/${validated.idempotencyKey}`,
1137
1208
  rows,
1138
1209
  );
1210
+
1139
1211
  if (decoded.length > 1) {
1140
1212
  return yield* corruptionFailure(
1141
1213
  operation,
@@ -1145,6 +1217,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1145
1217
  );
1146
1218
  }
1147
1219
  if (decoded.length === 0) return Option.none();
1220
+
1148
1221
  return Option.some(yield* decodeSubmissionSnapshot(operation, decoded[0]));
1149
1222
  },
1150
1223
  );
@@ -1157,9 +1230,11 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1157
1230
  "DoSubmissionLedger.resolveAdmission",
1158
1231
  )(function* (request: SubmissionLookupByKey) {
1159
1232
  const operation = "ledger resolve admission";
1233
+
1160
1234
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SubmissionLookupByKey))(
1161
1235
  request,
1162
1236
  ).pipe(Effect.mapError(internalFailure(operation)));
1237
+
1163
1238
  const rows = yield* sql<Record<string, unknown>>`
1164
1239
  SELECT ${sql.literal(SUBMISSION_COLUMNS)}
1165
1240
  FROM effect_agent_submissions
@@ -1167,11 +1242,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1167
1242
  AND principal = ${validated.principal}
1168
1243
  AND idempotency_key = ${validated.idempotencyKey}
1169
1244
  `.pipe(Effect.mapError(sqlFailure(operation)));
1245
+
1170
1246
  const decoded = yield* decodeSubmissionRows(
1171
1247
  operation,
1172
1248
  `${validated.threadId}/${validated.principal}/${validated.idempotencyKey}`,
1173
1249
  rows,
1174
1250
  );
1251
+
1175
1252
  if (decoded.length > 1) {
1176
1253
  return yield* corruptionFailure(
1177
1254
  operation,
@@ -1181,6 +1258,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1181
1258
  );
1182
1259
  }
1183
1260
  if (decoded.length === 0) return AdmissionNotAdmitted.make();
1261
+
1184
1262
  return AdmissionAdmitted.make({
1185
1263
  submission: yield* decodeSubmissionSnapshot(operation, decoded[0]),
1186
1264
  });
@@ -1189,12 +1267,16 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1189
1267
  const claim: SubmissionLedger["Service"]["claim"] = Effect.fn("DoSubmissionLedger.claim")(
1190
1268
  function* (request: ClaimRequest) {
1191
1269
  const operation = "ledger claim";
1270
+
1192
1271
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ClaimRequest))(
1193
1272
  request,
1194
1273
  ).pipe(Effect.mapError(internalFailure(operation)));
1274
+
1195
1275
  const attemptId = `attempt-${yield* mintUuid(operation)}`;
1196
1276
  const ownershipToken = `owner-${yield* mintUuid(operation)}`;
1277
+
1197
1278
  yield* hitFailpoint("ledger:claim:before", operation);
1279
+
1198
1280
  const claimed = yield* inWriteTransaction(
1199
1281
  operation,
1200
1282
  Effect.gen(function* () {
@@ -1206,7 +1288,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1206
1288
  ORDER BY queue_sequence ASC
1207
1289
  LIMIT 1
1208
1290
  `.pipe(Effect.mapError(sqlFailure(operation)));
1291
+
1209
1292
  const heads = yield* decodeSubmissionRows(operation, validated.threadId, headRows);
1293
+
1210
1294
  if (heads.length === 0) return Option.none<Claim>();
1211
1295
  const head = heads[0];
1212
1296
 
@@ -1225,11 +1309,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1225
1309
 
1226
1310
  const now = yield* currentInstant;
1227
1311
  const ownership = yield* readOwnership(operation, head.submission_id);
1312
+
1228
1313
  if (Option.isSome(ownership)) {
1229
1314
  const expiresAt = yield* timestampMillis(
1230
1315
  operation,
1231
1316
  head.submission_id,
1232
1317
  )(ownership.value.lease_expires_at);
1318
+
1233
1319
  // A live lease blocks every new claim; expiry alone only revokes the liveness
1234
1320
  // assumption — correctness stays with producer-epoch fencing (D5). In DC a live
1235
1321
  // lease under another token can only come from an evicted incarnation.
@@ -1243,7 +1329,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1243
1329
  const threads = yield* journal
1244
1330
  .getThread(head.thread_id)
1245
1331
  .pipe(Effect.mapError(internalFailure(operation)));
1332
+
1246
1333
  let producerEpoch: number;
1334
+
1247
1335
  if (threads.length === 0) {
1248
1336
  producerEpoch = 1;
1249
1337
  yield* sql`
@@ -1271,6 +1359,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1271
1359
  }
1272
1360
 
1273
1361
  const leaseExpiresAt = new Date(now.millis + config.ownershipLeaseDuration).toISOString();
1362
+
1274
1363
  yield* sql`
1275
1364
  INSERT INTO effect_agent_submission_ownership (
1276
1365
  submission_id,
@@ -1331,6 +1420,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1331
1420
  ),
1332
1421
  ),
1333
1422
  );
1423
+
1334
1424
  return Option.some(
1335
1425
  yield* decodeClaim({
1336
1426
  submissionId: head.submission_id,
@@ -1343,7 +1433,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1343
1433
  );
1344
1434
  }),
1345
1435
  );
1436
+
1346
1437
  yield* hitFailpoint("ledger:claim:after", operation);
1438
+
1347
1439
  return claimed;
1348
1440
  },
1349
1441
  );
@@ -1352,29 +1444,37 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1352
1444
  "DoSubmissionLedger.renewOwnership",
1353
1445
  )(function* (request: RenewOwnershipRequest) {
1354
1446
  const operation = "ledger renew ownership";
1447
+
1355
1448
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(RenewOwnershipRequest))(
1356
1449
  request,
1357
1450
  ).pipe(Effect.mapError(internalFailure(operation)));
1451
+
1358
1452
  yield* hitFailpoint("ledger:renew:before", operation);
1453
+
1359
1454
  const renewal = yield* inWriteTransaction(
1360
1455
  operation,
1361
1456
  Effect.gen(function* () {
1362
1457
  const submission = yield* requireSubmission(operation, validated.submissionId);
1458
+
1363
1459
  yield* requireOwnership(operation, submission, validated.ownershipToken);
1364
1460
  const now = yield* currentInstant;
1365
1461
  const leaseExpiresAt = new Date(now.millis + config.ownershipLeaseDuration).toISOString();
1462
+
1366
1463
  yield* sql`
1367
1464
  UPDATE effect_agent_submission_ownership
1368
1465
  SET lease_expires_at = ${leaseExpiresAt}
1369
1466
  WHERE submission_id = ${validated.submissionId}
1370
1467
  `.pipe(Effect.mapError(sqlFailure(operation)));
1468
+
1371
1469
  return yield* decodeOwnershipRenewal({
1372
1470
  ownershipToken: validated.ownershipToken,
1373
1471
  leaseExpiresAt,
1374
1472
  }).pipe(Effect.mapError(internalFailure(operation)));
1375
1473
  }),
1376
1474
  );
1475
+
1377
1476
  yield* hitFailpoint("ledger:renew:after", operation);
1477
+
1378
1478
  return renewal;
1379
1479
  });
1380
1480
 
@@ -1382,14 +1482,17 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1382
1482
  "DoSubmissionLedger.releaseOwnership",
1383
1483
  )(function* (request: ReleaseOwnershipRequest) {
1384
1484
  const operation = "ledger release ownership";
1485
+
1385
1486
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ReleaseOwnershipRequest))(
1386
1487
  request,
1387
1488
  ).pipe(Effect.mapError(internalFailure(operation)));
1489
+
1388
1490
  yield* hitFailpoint("ledger:release:before", operation);
1389
1491
  yield* inWriteTransaction(
1390
1492
  operation,
1391
1493
  Effect.gen(function* () {
1392
1494
  const submission = yield* requireSubmission(operation, validated.submissionId);
1495
+
1393
1496
  yield* requireOwnership(operation, submission, validated.ownershipToken);
1394
1497
  yield* sql`
1395
1498
  DELETE FROM effect_agent_submission_ownership
@@ -1411,14 +1514,17 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1411
1514
  "DoSubmissionLedger.markInputApplied",
1412
1515
  )(function* (request: MarkInputAppliedRequest) {
1413
1516
  const operation = "ledger mark input applied";
1517
+
1414
1518
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(MarkInputAppliedRequest))(
1415
1519
  request,
1416
1520
  ).pipe(Effect.mapError(internalFailure(operation)));
1521
+
1417
1522
  yield* hitFailpoint("ledger:mark-input-applied:before", operation);
1418
1523
  yield* inWriteTransaction(
1419
1524
  operation,
1420
1525
  Effect.gen(function* () {
1421
1526
  const submission = yield* requireSubmission(operation, validated.submissionId);
1527
+
1422
1528
  yield* requireOwnership(operation, submission, validated.ownershipToken);
1423
1529
  if (submission.input_applied_record_id !== null) {
1424
1530
  if (
@@ -1427,6 +1533,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1427
1533
  ) {
1428
1534
  return;
1429
1535
  }
1536
+
1430
1537
  return yield* corruptionFailure(
1431
1538
  operation,
1432
1539
  "effect_agent_submissions",
@@ -1454,34 +1561,41 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1454
1561
  "DoSubmissionLedger.reserveSettlement",
1455
1562
  )(function* (request: SettlementReservation) {
1456
1563
  const operation = "ledger reserve settlement";
1564
+
1457
1565
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SettlementReservation))(
1458
1566
  request,
1459
1567
  ).pipe(Effect.mapError(internalFailure(operation)));
1568
+
1460
1569
  const recordJson = yield* encodeRecordEnvelopeText(validated.record).pipe(
1461
1570
  Effect.mapError(internalFailure(operation)),
1462
1571
  );
1572
+
1463
1573
  // The reserved record is appended canonically later; refuse over-bound payloads typed
1464
1574
  // before the reservation row exists.
1465
1575
  yield* journal
1466
1576
  .checkValueBound(operation, recordJson)
1467
1577
  .pipe(Effect.mapError(internalFailure(operation)));
1468
1578
  yield* hitFailpoint("ledger:reserve-settlement:before", operation);
1579
+
1469
1580
  const reserved = yield* inWriteTransaction(
1470
1581
  operation,
1471
1582
  Effect.gen(function* () {
1472
1583
  const existing = yield* readReservation(operation, validated.submissionId);
1584
+
1473
1585
  if (Option.isSome(existing)) {
1474
1586
  const identical =
1475
1587
  existing.value.settlement_id === validated.settlementId &&
1476
1588
  existing.value.outcome === validated.outcome &&
1477
1589
  existing.value.record_digest === validated.recordDigest &&
1478
1590
  existing.value.record_json === recordJson;
1591
+
1479
1592
  if (!identical) {
1480
1593
  return yield* SettlementConflict.make({
1481
1594
  submissionId: validated.submissionId,
1482
1595
  existingOutcome: existing.value.outcome,
1483
1596
  });
1484
1597
  }
1598
+
1485
1599
  const record = yield* decodeRecordEnvelopeText(existing.value.record_json).pipe(
1486
1600
  Effect.mapError((error) =>
1487
1601
  corruptionFailure(
@@ -1492,6 +1606,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1492
1606
  ),
1493
1607
  ),
1494
1608
  );
1609
+
1495
1610
  return ReservedSettlement.make({
1496
1611
  submissionId: validated.submissionId,
1497
1612
  settlementId: validated.settlementId,
@@ -1503,6 +1618,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1503
1618
  }
1504
1619
 
1505
1620
  const submission = yield* requireSubmission(operation, validated.submissionId);
1621
+
1506
1622
  if (submission.state === "settled") {
1507
1623
  if (submission.settled_outcome === null) {
1508
1624
  return yield* corruptionFailure(
@@ -1512,6 +1628,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1512
1628
  "A settled Submission carries no terminal outcome.",
1513
1629
  );
1514
1630
  }
1631
+
1515
1632
  return yield* SettlementConflict.make({
1516
1633
  submissionId: validated.submissionId,
1517
1634
  existingOutcome: submission.settled_outcome,
@@ -1526,13 +1643,16 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1526
1643
  // ABORTED settlement (`terminalizing` is the same pass's crash replay). Every other
1527
1644
  // reservation stays fenced by the target lane's live ownership.
1528
1645
  let queuedAbortSettlement = false;
1646
+
1529
1647
  if (
1530
1648
  validated.outcome === "aborted" &&
1531
1649
  (submission.state === "ready" || submission.state === "terminalizing")
1532
1650
  ) {
1533
1651
  const abortIntent = yield* readAbortIntent(operation, validated.submissionId);
1652
+
1534
1653
  if (Option.isSome(abortIntent)) {
1535
1654
  const ownership = yield* readOwnership(operation, validated.submissionId);
1655
+
1536
1656
  queuedAbortSettlement = Option.isNone(ownership);
1537
1657
  }
1538
1658
  }
@@ -1541,6 +1661,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1541
1661
  }
1542
1662
  }
1543
1663
  const now = yield* currentInstant;
1664
+
1544
1665
  yield* sql`
1545
1666
  INSERT INTO effect_agent_settlement_reservations (
1546
1667
  submission_id,
@@ -1565,6 +1686,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1565
1686
  SET state = 'terminalizing'
1566
1687
  WHERE submission_id = ${validated.submissionId}
1567
1688
  `.pipe(Effect.mapError(sqlFailure(operation)));
1689
+
1568
1690
  return ReservedSettlement.make({
1569
1691
  submissionId: validated.submissionId,
1570
1692
  settlementId: validated.settlementId,
@@ -1575,7 +1697,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1575
1697
  });
1576
1698
  }),
1577
1699
  );
1700
+
1578
1701
  yield* hitFailpoint("ledger:reserve-settlement:after", operation);
1702
+
1579
1703
  return reserved;
1580
1704
  });
1581
1705
 
@@ -1583,14 +1707,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1583
1707
  "DoSubmissionLedger.finalizeSettlement",
1584
1708
  )(function* (request: SettlementFinalization) {
1585
1709
  const operation = "ledger finalize settlement";
1710
+
1586
1711
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SettlementFinalization))(
1587
1712
  request,
1588
1713
  ).pipe(Effect.mapError(internalFailure(operation)));
1714
+
1589
1715
  yield* hitFailpoint("ledger:finalize-settlement:before", operation);
1716
+
1590
1717
  const settlement = yield* inWriteTransaction(
1591
1718
  operation,
1592
1719
  Effect.gen(function* () {
1593
1720
  const reservation = yield* readReservation(operation, validated.submissionId);
1721
+
1594
1722
  if (Option.isNone(reservation)) {
1595
1723
  return yield* LedgerError.make({
1596
1724
  operation,
@@ -1603,6 +1731,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1603
1731
  existingOutcome: reservation.value.outcome,
1604
1732
  });
1605
1733
  }
1734
+
1606
1735
  const reservationRecord = yield* decodeRecordEnvelopeText(
1607
1736
  reservation.value.record_json,
1608
1737
  ).pipe(
@@ -1615,7 +1744,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1615
1744
  ),
1616
1745
  ),
1617
1746
  );
1747
+
1618
1748
  const settlementFailure = settlementFailureFromRecord(reservationRecord);
1749
+
1619
1750
  if ((reservation.value.outcome === "failed") !== (settlementFailure !== undefined)) {
1620
1751
  return yield* corruptionFailure(
1621
1752
  operation,
@@ -1625,6 +1756,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1625
1756
  );
1626
1757
  }
1627
1758
  const submission = yield* requireSubmission(operation, validated.submissionId);
1759
+
1628
1760
  if (submission.state === "settled") {
1629
1761
  if (reservation.value.finalized_at === null) {
1630
1762
  return yield* corruptionFailure(
@@ -1634,6 +1766,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1634
1766
  "A settled Submission's reservation carries no finalization timestamp.",
1635
1767
  );
1636
1768
  }
1769
+
1637
1770
  return yield* decodeSettlement({
1638
1771
  submissionId: validated.submissionId,
1639
1772
  settlementId: validated.settlementId,
@@ -1644,6 +1777,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1644
1777
  }).pipe(Effect.mapError(internalFailure(operation)));
1645
1778
  }
1646
1779
  const now = yield* currentInstant;
1780
+
1647
1781
  yield* sql`
1648
1782
  UPDATE effect_agent_submissions
1649
1783
  SET state = 'settled', settled_outcome = ${reservation.value.outcome}
@@ -1658,6 +1792,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1658
1792
  DELETE FROM effect_agent_submission_ownership
1659
1793
  WHERE submission_id = ${validated.submissionId}
1660
1794
  `.pipe(Effect.mapError(sqlFailure(operation)));
1795
+
1661
1796
  return yield* decodeSettlement({
1662
1797
  submissionId: validated.submissionId,
1663
1798
  settlementId: validated.settlementId,
@@ -1668,7 +1803,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1668
1803
  }).pipe(Effect.mapError(internalFailure(operation)));
1669
1804
  }),
1670
1805
  );
1806
+
1671
1807
  yield* hitFailpoint("ledger:finalize-settlement:after", operation);
1808
+
1672
1809
  return settlement;
1673
1810
  });
1674
1811
 
@@ -1676,14 +1813,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1676
1813
  "DoSubmissionLedger.requestAbort",
1677
1814
  )(function* (request: AbortCommand) {
1678
1815
  const operation = "ledger request abort";
1816
+
1679
1817
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(AbortCommand))(request).pipe(
1680
1818
  Effect.mapError(internalFailure(operation)),
1681
1819
  );
1820
+
1682
1821
  yield* hitFailpoint("ledger:request-abort:before", operation);
1822
+
1683
1823
  const intent = yield* inWriteTransaction(
1684
1824
  operation,
1685
1825
  Effect.gen(function* () {
1686
1826
  const submission = yield* requireSubmission(operation, validated.submissionId);
1827
+
1687
1828
  if (submission.state === "settled") {
1688
1829
  if (submission.settled_outcome === null) {
1689
1830
  return yield* corruptionFailure(
@@ -1693,6 +1834,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1693
1834
  "A settled Submission carries no terminal outcome.",
1694
1835
  );
1695
1836
  }
1837
+
1696
1838
  return yield* SettlementConflict.make({
1697
1839
  submissionId: validated.submissionId,
1698
1840
  existingOutcome: submission.settled_outcome,
@@ -1710,15 +1852,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1710
1852
  "A joined Submission carries no host linkage.",
1711
1853
  );
1712
1854
  }
1855
+
1713
1856
  const hostSubmissionId = yield* decodeSubmissionId(
1714
1857
  submission.joined_host_submission_id,
1715
1858
  ).pipe(Effect.mapError(internalFailure(operation)));
1859
+
1716
1860
  return yield* JoinedToHost.make({
1717
1861
  submissionId: validated.submissionId,
1718
1862
  hostSubmissionId,
1719
1863
  });
1720
1864
  }
1721
1865
  const existing = yield* readAbortIntent(operation, validated.submissionId);
1866
+
1722
1867
  if (Option.isSome(existing)) {
1723
1868
  return yield* abortIntentFromRow(
1724
1869
  operation,
@@ -1728,6 +1873,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1728
1873
  );
1729
1874
  }
1730
1875
  const now = yield* currentInstant;
1876
+
1731
1877
  yield* sql`
1732
1878
  INSERT INTO effect_agent_abort_intents (
1733
1879
  submission_id,
@@ -1741,11 +1887,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1741
1887
  ${now.iso}
1742
1888
  )
1743
1889
  `.pipe(Effect.mapError(sqlFailure(operation)));
1890
+
1744
1891
  const canonicalRecordId = yield* canonicalAbortRecordId(
1745
1892
  operation,
1746
1893
  submission.thread_id,
1747
1894
  validated.submissionId,
1748
1895
  );
1896
+
1749
1897
  return yield* decodeAbortIntent({
1750
1898
  submissionId: validated.submissionId,
1751
1899
  author: validated.author,
@@ -1755,7 +1903,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1755
1903
  }).pipe(Effect.mapError(internalFailure(operation)));
1756
1904
  }),
1757
1905
  );
1906
+
1758
1907
  yield* hitFailpoint("ledger:request-abort:after", operation);
1908
+
1759
1909
  return intent;
1760
1910
  });
1761
1911
 
@@ -1763,14 +1913,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1763
1913
  "DoSubmissionLedger.claimJoining",
1764
1914
  )(function* (request: ClaimJoiningRequest) {
1765
1915
  const operation = "ledger claim joining";
1916
+
1766
1917
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ClaimJoiningRequest))(
1767
1918
  request,
1768
1919
  ).pipe(Effect.mapError(internalFailure(operation)));
1920
+
1769
1921
  yield* hitFailpoint("ledger:claim-joining:before", operation);
1922
+
1770
1923
  const claims = yield* inWriteTransaction(
1771
1924
  operation,
1772
1925
  Effect.gen(function* () {
1773
1926
  const host = yield* requireSubmission(operation, validated.hostSubmissionId);
1927
+
1774
1928
  if (host.thread_id !== validated.threadId) {
1775
1929
  return yield* LedgerError.make({
1776
1930
  operation,
@@ -1779,6 +1933,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1779
1933
  }
1780
1934
  // The host Attempt already owns the lane; no epoch bump happens here (plan §2.5).
1781
1935
  yield* requireOwnership(operation, host, validated.ownershipToken);
1936
+
1782
1937
  const laterRows = yield* sql<Record<string, unknown>>`
1783
1938
  SELECT ${sql.literal(SUBMISSION_COLUMNS)}
1784
1939
  FROM effect_agent_submissions
@@ -1786,8 +1941,10 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1786
1941
  AND queue_sequence > ${host.queue_sequence}
1787
1942
  ORDER BY queue_sequence ASC
1788
1943
  `.pipe(Effect.mapError(sqlFailure(operation)));
1944
+
1789
1945
  const later = yield* decodeSubmissionRows(operation, validated.threadId, laterRows);
1790
1946
  const claimed: Array<JoiningClaim> = [];
1947
+
1791
1948
  for (const row of later) {
1792
1949
  if (claimed.length >= validated.maxCount) break;
1793
1950
  // Rows already claimed by THIS host extend its contiguous prefix and are skipped;
@@ -1810,6 +1967,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1810
1967
  SET state = 'joining', joined_host_submission_id = ${validated.hostSubmissionId}
1811
1968
  WHERE submission_id = ${row.submission_id}
1812
1969
  `.pipe(Effect.mapError(sqlFailure(operation)));
1970
+
1813
1971
  const inputPayload = yield* parseStoredJsonText(row.input_json).pipe(
1814
1972
  Effect.mapError((error) =>
1815
1973
  corruptionFailure(
@@ -1820,6 +1978,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1820
1978
  ),
1821
1979
  ),
1822
1980
  );
1981
+
1823
1982
  claimed.push(
1824
1983
  yield* decodeJoiningClaim({
1825
1984
  submissionId: row.submission_id,
@@ -1828,10 +1987,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1828
1987
  }).pipe(Effect.mapError(internalFailure(operation))),
1829
1988
  );
1830
1989
  }
1990
+
1831
1991
  return claimed;
1832
1992
  }),
1833
1993
  );
1994
+
1834
1995
  yield* hitFailpoint("ledger:claim-joining:after", operation);
1996
+
1835
1997
  return claims;
1836
1998
  });
1837
1999
 
@@ -1839,14 +2001,17 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1839
2001
  "DoSubmissionLedger.markJoined",
1840
2002
  )(function* (request: MarkJoinedRequest) {
1841
2003
  const operation = "ledger mark joined";
2004
+
1842
2005
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(MarkJoinedRequest))(
1843
2006
  request,
1844
2007
  ).pipe(Effect.mapError(internalFailure(operation)));
2008
+
1845
2009
  yield* hitFailpoint("ledger:mark-joined:before", operation);
1846
2010
  yield* inWriteTransaction(
1847
2011
  operation,
1848
2012
  Effect.gen(function* () {
1849
2013
  const submission = yield* requireSubmission(operation, validated.submissionId);
2014
+
1850
2015
  if (submission.joined_host_submission_id === null) {
1851
2016
  return yield* LedgerError.make({
1852
2017
  operation,
@@ -1854,6 +2019,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1854
2019
  });
1855
2020
  }
1856
2021
  const host = yield* requireSubmission(operation, submission.joined_host_submission_id);
2022
+
1857
2023
  // The lane is host-owned: the presented token must own the HOST's ownership period,
1858
2024
  // which also lets a later host Attempt repair a lost marker from history (DUR-016).
1859
2025
  yield* requireOwnership(operation, host, validated.ownershipToken);
@@ -1864,6 +2030,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1864
2030
  ) {
1865
2031
  return;
1866
2032
  }
2033
+
1867
2034
  return yield* corruptionFailure(
1868
2035
  operation,
1869
2036
  "effect_agent_submissions",
@@ -1894,14 +2061,17 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1894
2061
  "DoSubmissionLedger.revertJoining",
1895
2062
  )(function* (request: RevertJoiningRequest) {
1896
2063
  const operation = "ledger revert joining";
2064
+
1897
2065
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(RevertJoiningRequest))(
1898
2066
  request,
1899
2067
  ).pipe(Effect.mapError(internalFailure(operation)));
2068
+
1900
2069
  yield* hitFailpoint("ledger:revert-joining:before", operation);
1901
2070
  yield* inWriteTransaction(
1902
2071
  operation,
1903
2072
  Effect.gen(function* () {
1904
2073
  const submission = yield* requireSubmission(operation, validated.submissionId);
2074
+
1905
2075
  // Idempotent and recovery-only: only a still-`joining` Submission reverts; an
1906
2076
  // already-joined (or already-reverted) Submission is a no-op (DUR-016).
1907
2077
  if (submission.state !== "joining") return;
@@ -1918,17 +2088,22 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1918
2088
  const suspend: SubmissionLedger["Service"]["suspend"] = Effect.fn("DoSubmissionLedger.suspend")(
1919
2089
  function* (request: SuspendRequest) {
1920
2090
  const operation = "ledger suspend";
2091
+
1921
2092
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SuspendRequest))(
1922
2093
  request,
1923
2094
  ).pipe(Effect.mapError(internalFailure(operation)));
2095
+
1924
2096
  const reasonJson = yield* encodeSuspensionReasonText(validated.reason).pipe(
1925
2097
  Effect.mapError(internalFailure(operation)),
1926
2098
  );
2099
+
1927
2100
  yield* hitFailpoint("ledger:suspend:before", operation);
2101
+
1928
2102
  const outcome = yield* inWriteTransaction(
1929
2103
  operation,
1930
2104
  Effect.gen(function* () {
1931
2105
  const submission = yield* requireSubmission(operation, validated.submissionId);
2106
+
1932
2107
  if (submission.state === "settled") {
1933
2108
  if (submission.settled_outcome === null) {
1934
2109
  return yield* corruptionFailure(
@@ -1938,6 +2113,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1938
2113
  "A settled Submission carries no terminal outcome.",
1939
2114
  );
1940
2115
  }
2116
+
1941
2117
  return yield* SettlementConflict.make({
1942
2118
  submissionId: validated.submissionId,
1943
2119
  existingOutcome: submission.settled_outcome,
@@ -1946,6 +2122,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1946
2122
  // An exact terminal outcome is already reserved (DUR-011); suspension would
1947
2123
  // contradict it, so the reservation wins.
1948
2124
  const reservation = yield* readReservation(operation, validated.submissionId);
2125
+
1949
2126
  if (Option.isSome(reservation)) {
1950
2127
  return yield* SettlementConflict.make({
1951
2128
  submissionId: validated.submissionId,
@@ -1962,6 +2139,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1962
2139
  if (validated.reason._tag === "ApprovalPending") {
1963
2140
  const decisions = yield* readApprovalDecisions(operation, validated.submissionId);
1964
2141
  const decided = new Set(decisions.map((row) => row.tool_call_id));
2142
+
1965
2143
  if (validated.reason.toolCallIds.every((toolCallId) => decided.has(toolCallId))) {
1966
2144
  return RESUME_IMMEDIATELY;
1967
2145
  }
@@ -1969,12 +2147,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1969
2147
  const markers = yield* readChildSettlementMarkers(operation, validated.submissionId);
1970
2148
  const markerChildren = new Set(markers.map((row) => row.child_submission_id));
1971
2149
  let allSettled = true;
2150
+
1972
2151
  for (const child of validated.reason.children) {
1973
2152
  const settled = yield* childProvablySettled(
1974
2153
  operation,
1975
2154
  markerChildren,
1976
2155
  child.childSubmissionId,
1977
2156
  );
2157
+
1978
2158
  if (!settled) {
1979
2159
  allSettled = false;
1980
2160
  break;
@@ -1985,6 +2165,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1985
2165
  }
1986
2166
  }
1987
2167
  const now = yield* currentInstant;
2168
+
1988
2169
  yield* sql`
1989
2170
  UPDATE effect_agent_submissions
1990
2171
  SET
@@ -1999,10 +2180,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
1999
2180
  DELETE FROM effect_agent_submission_ownership
2000
2181
  WHERE submission_id = ${validated.submissionId}
2001
2182
  `.pipe(Effect.mapError(sqlFailure(operation)));
2183
+
2002
2184
  return SUSPENDED;
2003
2185
  }),
2004
2186
  );
2187
+
2005
2188
  yield* hitFailpoint("ledger:suspend:after", operation);
2189
+
2006
2190
  return outcome;
2007
2191
  },
2008
2192
  );
@@ -2018,6 +2202,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2018
2202
  submission: SubmissionRow,
2019
2203
  ): Effect.fn.Return<void, LedgerError> {
2020
2204
  if (submission.state !== "suspended" || submission.suspended_reason_json === null) return;
2205
+
2021
2206
  const reason = yield* Schema.decodeEffect(Schema.fromJsonString(SuspensionReason))(
2022
2207
  submission.suspended_reason_json,
2023
2208
  ).pipe(
@@ -2030,9 +2215,11 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2030
2215
  ),
2031
2216
  ),
2032
2217
  );
2218
+
2033
2219
  if (reason._tag !== "ApprovalPending") return;
2034
2220
  const decisions = yield* readApprovalDecisions(operation, submission.submission_id);
2035
2221
  const decided = new Set(decisions.map((row) => row.tool_call_id));
2222
+
2036
2223
  if (!reason.toolCallIds.every((toolCallId) => decided.has(toolCallId))) return;
2037
2224
  yield* sql`
2038
2225
  UPDATE effect_agent_submissions
@@ -2048,14 +2235,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2048
2235
  "DoSubmissionLedger.recordApprovalDecision",
2049
2236
  )(function* (command: ApprovalDecisionCommand) {
2050
2237
  const operation = "ledger record approval decision";
2238
+
2051
2239
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ApprovalDecisionCommand))(
2052
2240
  command,
2053
2241
  ).pipe(Effect.mapError(internalFailure(operation)));
2242
+
2054
2243
  yield* hitFailpoint("ledger:approval-decision:before", operation);
2244
+
2055
2245
  const intent = yield* inWriteTransaction(
2056
2246
  operation,
2057
2247
  Effect.gen(function* () {
2058
2248
  const submission = yield* requireSubmission(operation, validated.submissionId);
2249
+
2059
2250
  if (submission.state === "settled") {
2060
2251
  if (submission.settled_outcome === null) {
2061
2252
  return yield* corruptionFailure(
@@ -2065,6 +2256,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2065
2256
  "A settled Submission carries no terminal outcome.",
2066
2257
  );
2067
2258
  }
2259
+
2068
2260
  return yield* SettlementConflict.make({
2069
2261
  submissionId: validated.submissionId,
2070
2262
  existingOutcome: submission.settled_outcome,
@@ -2072,6 +2264,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2072
2264
  }
2073
2265
  const decisions = yield* readApprovalDecisions(operation, validated.submissionId);
2074
2266
  const existing = decisions.find((row) => row.tool_call_id === validated.toolCallId);
2267
+
2075
2268
  if (existing !== undefined) {
2076
2269
  // Idempotent per (submissionId, toolCallId): repeating the SAME decision replays
2077
2270
  // the recorded intent unchanged; a divergent re-decision conflicts.
@@ -2082,9 +2275,11 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2082
2275
  existingDecision: existing.decision,
2083
2276
  });
2084
2277
  }
2278
+
2085
2279
  return yield* approvalIntentFromRow(operation, existing);
2086
2280
  }
2087
2281
  const now = yield* currentInstant;
2282
+
2088
2283
  yield* sql`
2089
2284
  INSERT INTO effect_agent_approval_decisions (
2090
2285
  submission_id,
@@ -2103,6 +2298,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2103
2298
  )
2104
2299
  `.pipe(Effect.mapError(sqlFailure(operation)));
2105
2300
  yield* wakeSuspendedIfCovered(operation, submission);
2301
+
2106
2302
  return yield* decodeApprovalDecisionIntent({
2107
2303
  submissionId: validated.submissionId,
2108
2304
  toolCallId: validated.toolCallId,
@@ -2113,7 +2309,9 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2113
2309
  }).pipe(Effect.mapError(internalFailure(operation)));
2114
2310
  }),
2115
2311
  );
2312
+
2116
2313
  yield* hitFailpoint("ledger:approval-decision:after", operation);
2314
+
2117
2315
  return intent;
2118
2316
  });
2119
2317
 
@@ -2121,14 +2319,17 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2121
2319
  "DoSubmissionLedger.markUnknown",
2122
2320
  )(function* (request: MarkUnknownRequest) {
2123
2321
  const operation = "ledger mark unknown";
2322
+
2124
2323
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(MarkUnknownRequest))(
2125
2324
  request,
2126
2325
  ).pipe(Effect.mapError(internalFailure(operation)));
2326
+
2127
2327
  yield* hitFailpoint("ledger:mark-unknown:before", operation);
2128
2328
  yield* inWriteTransaction(
2129
2329
  operation,
2130
2330
  Effect.gen(function* () {
2131
2331
  const submission = yield* requireSubmission(operation, validated.submissionId);
2332
+
2132
2333
  if (submission.state === "settled") {
2133
2334
  if (submission.settled_outcome === null) {
2134
2335
  return yield* corruptionFailure(
@@ -2138,6 +2339,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2138
2339
  "A settled Submission carries no terminal outcome.",
2139
2340
  );
2140
2341
  }
2342
+
2141
2343
  return yield* SettlementConflict.make({
2142
2344
  submissionId: validated.submissionId,
2143
2345
  existingOutcome: submission.settled_outcome,
@@ -2146,6 +2348,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2146
2348
  // A reserved exact outcome wins over a late Unknown marking (DUR-011); the recovery
2147
2349
  // classifier orders reservation ahead of MarkUnknown for the same reason.
2148
2350
  const reservation = yield* readReservation(operation, validated.submissionId);
2351
+
2149
2352
  if (Option.isSome(reservation)) {
2150
2353
  return yield* SettlementConflict.make({
2151
2354
  submissionId: validated.submissionId,
@@ -2156,13 +2359,16 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2156
2359
  // set while the first recorded reason is kept.
2157
2360
  const existingIds = yield* storedUnknownToolCallIds(operation, submission);
2158
2361
  const known = new Set(existingIds);
2362
+
2159
2363
  const merged = [
2160
2364
  ...existingIds,
2161
2365
  ...validated.toolCallIds.filter((toolCallId) => !known.has(toolCallId)),
2162
2366
  ];
2367
+
2163
2368
  const idsJson = yield* encodeToolCallIdsText(merged).pipe(
2164
2369
  Effect.mapError(internalFailure(operation)),
2165
2370
  );
2371
+
2166
2372
  yield* sql`
2167
2373
  UPDATE effect_agent_submissions
2168
2374
  SET
@@ -2180,17 +2386,22 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2180
2386
  "DoSubmissionLedger.recordUnknownResolution",
2181
2387
  )(function* (command: UnknownResolutionCommand) {
2182
2388
  const operation = "ledger record unknown resolution";
2389
+
2183
2390
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(UnknownResolutionCommand))(
2184
2391
  command,
2185
2392
  ).pipe(Effect.mapError(internalFailure(operation)));
2393
+
2186
2394
  const resolutionJson = yield* encodeUnknownResolutionText(validated.resolution).pipe(
2187
2395
  Effect.mapError(internalFailure(operation)),
2188
2396
  );
2397
+
2189
2398
  yield* hitFailpoint("ledger:unknown-resolution:before", operation);
2399
+
2190
2400
  const intent = yield* inWriteTransaction(
2191
2401
  operation,
2192
2402
  Effect.gen(function* () {
2193
2403
  const submission = yield* requireSubmission(operation, validated.submissionId);
2404
+
2194
2405
  if (submission.state === "settled") {
2195
2406
  if (submission.settled_outcome === null) {
2196
2407
  return yield* corruptionFailure(
@@ -2200,6 +2411,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2200
2411
  "A settled Submission carries no terminal outcome.",
2201
2412
  );
2202
2413
  }
2414
+
2203
2415
  return yield* SettlementConflict.make({
2204
2416
  submissionId: validated.submissionId,
2205
2417
  existingOutcome: submission.settled_outcome,
@@ -2207,10 +2419,12 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2207
2419
  }
2208
2420
  const resolutions = yield* readUnknownResolutions(operation, validated.submissionId);
2209
2421
  const existing = resolutions.find((row) => row.tool_call_id === validated.toolCallId);
2422
+
2210
2423
  const existingIntent =
2211
2424
  existing === undefined
2212
2425
  ? undefined
2213
2426
  : yield* unknownResolutionIntentFromRow(operation, existing);
2427
+
2214
2428
  if (
2215
2429
  existingIntent !== undefined &&
2216
2430
  !equivalentUnknownResolution(existingIntent.resolution, validated.resolution)
@@ -2221,12 +2435,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2221
2435
  });
2222
2436
  }
2223
2437
  let resolved: UnknownResolutionIntent;
2438
+
2224
2439
  if (existingIntent !== undefined) {
2225
2440
  // Idempotent replay of the recorded intent (author/reason may differ; the stored
2226
2441
  // audit fields win, exactly like requestAbort).
2227
2442
  resolved = existingIntent;
2228
2443
  } else {
2229
2444
  const now = yield* currentInstant;
2445
+
2230
2446
  yield* sql`
2231
2447
  INSERT INTO effect_agent_unknown_resolutions (
2232
2448
  submission_id,
@@ -2244,9 +2460,11 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2244
2460
  ${now.iso}
2245
2461
  )
2246
2462
  `.pipe(Effect.mapError(sqlFailure(operation)));
2463
+
2247
2464
  const resolution = yield* parseStoredJsonText(resolutionJson).pipe(
2248
2465
  Effect.mapError(internalFailure(operation)),
2249
2466
  );
2467
+
2250
2468
  resolved = yield* decodeUnknownResolutionIntent({
2251
2469
  submissionId: validated.submissionId,
2252
2470
  toolCallId: validated.toolCallId,
@@ -2263,6 +2481,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2263
2481
  const markedIds = yield* storedUnknownToolCallIds(operation, submission);
2264
2482
  const covering = yield* readUnknownResolutions(operation, validated.submissionId);
2265
2483
  const coveredIds = new Set(covering.map((row) => row.tool_call_id));
2484
+
2266
2485
  if (markedIds.every((toolCallId) => coveredIds.has(toolCallId))) {
2267
2486
  yield* sql`
2268
2487
  UPDATE effect_agent_submissions
@@ -2274,10 +2493,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2274
2493
  `.pipe(Effect.mapError(sqlFailure(operation)));
2275
2494
  }
2276
2495
  }
2496
+
2277
2497
  return resolved;
2278
2498
  }),
2279
2499
  );
2500
+
2280
2501
  yield* hitFailpoint("ledger:unknown-resolution:after", operation);
2502
+
2281
2503
  return intent;
2282
2504
  });
2283
2505
 
@@ -2285,10 +2507,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2285
2507
  "DoSubmissionLedger.recordChildSettled",
2286
2508
  )(function* (request: ChildSettledNotification) {
2287
2509
  const operation = "ledger record child settled";
2510
+
2288
2511
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ChildSettledNotification))(
2289
2512
  request,
2290
2513
  ).pipe(Effect.mapError(internalFailure(operation)));
2514
+
2291
2515
  yield* hitFailpoint("ledger:child-settled:before", operation);
2516
+
2292
2517
  const outcome = yield* inWriteTransaction(
2293
2518
  operation,
2294
2519
  Effect.gen(function* () {
@@ -2301,6 +2526,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2301
2526
  // child's owning Durable Object is the settlement evidence this store records durably.
2302
2527
  const child = yield* readSubmission(operation, validated.childSubmissionId);
2303
2528
  const childReservation = yield* readReservation(operation, validated.childSubmissionId);
2529
+
2304
2530
  if (
2305
2531
  Option.isSome(child) &&
2306
2532
  child.value.state !== "settled" &&
@@ -2316,6 +2542,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2316
2542
  // before the parent's suspend transaction is observed by that suspend's covering
2317
2543
  // check, even when the parent is not (or not yet) suspended.
2318
2544
  const now = yield* currentInstant;
2545
+
2319
2546
  yield* sql`
2320
2547
  INSERT INTO effect_agent_child_settlements (
2321
2548
  parent_submission_id,
@@ -2340,6 +2567,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2340
2567
  if (parent.state !== "suspended" || parent.suspended_reason_json === null) {
2341
2568
  return NOT_WAITING;
2342
2569
  }
2570
+
2343
2571
  const reason = yield* Schema.decodeEffect(Schema.fromJsonString(SuspensionReason))(
2344
2572
  parent.suspended_reason_json,
2345
2573
  ).pipe(
@@ -2352,6 +2580,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2352
2580
  ),
2353
2581
  ),
2354
2582
  );
2583
+
2355
2584
  if (reason._tag !== "WaitingForChild") {
2356
2585
  return NOT_WAITING;
2357
2586
  }
@@ -2365,12 +2594,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2365
2594
  // check so a recovering caller wakes the lane idempotently.
2366
2595
  const markers = yield* readChildSettlementMarkers(operation, validated.parentSubmissionId);
2367
2596
  const markerChildren = new Set(markers.map((row) => row.child_submission_id));
2597
+
2368
2598
  for (const entry of reason.children) {
2369
2599
  const settled = yield* childProvablySettled(
2370
2600
  operation,
2371
2601
  markerChildren,
2372
2602
  entry.childSubmissionId,
2373
2603
  );
2604
+
2374
2605
  if (!settled) {
2375
2606
  return STILL_WAITING;
2376
2607
  }
@@ -2383,10 +2614,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2383
2614
  suspended_at = NULL
2384
2615
  WHERE submission_id = ${validated.parentSubmissionId}
2385
2616
  `.pipe(Effect.mapError(sqlFailure(operation)));
2617
+
2386
2618
  return WOKEN;
2387
2619
  }),
2388
2620
  );
2621
+
2389
2622
  yield* hitFailpoint("ledger:child-settled:after", operation);
2623
+
2390
2624
  return outcome;
2391
2625
  });
2392
2626
 
@@ -2394,22 +2628,28 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2394
2628
  "DoSubmissionLedger.reserveChildBudget",
2395
2629
  )(function* (request: ChildBudgetReservationRequest) {
2396
2630
  const operation = "ledger reserve child budget";
2631
+
2397
2632
  const validated = yield* Schema.decodeUnknownEffect(
2398
2633
  Schema.toType(ChildBudgetReservationRequest),
2399
2634
  )(request).pipe(Effect.mapError(internalFailure(operation)));
2635
+
2400
2636
  const allocationJson = yield* encodePersistedJsonText(validated.allocation).pipe(
2401
2637
  Effect.mapError(internalFailure(operation)),
2402
2638
  );
2639
+
2403
2640
  yield* hitFailpoint("ledger:child-reservation:before", operation);
2641
+
2404
2642
  const reserved = yield* inWriteTransaction(
2405
2643
  operation,
2406
2644
  Effect.gen(function* () {
2407
2645
  const existing = yield* readChildReservation(operation, validated.reservationId);
2646
+
2408
2647
  if (Option.isSome(existing)) {
2409
2648
  const existingSnapshot = yield* childReservationSnapshotFromRow(
2410
2649
  operation,
2411
2650
  existing.value,
2412
2651
  );
2652
+
2413
2653
  // Identical replays short-circuit before the fence, mirroring reserveSettlement: a
2414
2654
  // replay creates nothing, so a recovering caller resumes rather than duplicates.
2415
2655
  const identical =
@@ -2417,6 +2657,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2417
2657
  existing.value.parent_tool_call_id === validated.parentToolCallId &&
2418
2658
  existing.value.allocation_digest === validated.allocationDigest &&
2419
2659
  equivalentPersistedJson(existingSnapshot.allocation, validated.allocation);
2660
+
2420
2661
  if (!identical) {
2421
2662
  return yield* ChildReservationConflict.make({
2422
2663
  reservationId: validated.reservationId,
@@ -2425,16 +2666,19 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2425
2666
  "A reservation with this identity exists with a different parent Tool Call or allocation.",
2426
2667
  });
2427
2668
  }
2669
+
2428
2670
  return ReservedChildBudget.make({
2429
2671
  reservation: existingSnapshot,
2430
2672
  replayed: true,
2431
2673
  });
2432
2674
  }
2675
+
2433
2676
  const collision = yield* readChildReservationForCall(
2434
2677
  operation,
2435
2678
  validated.parentSubmissionId,
2436
2679
  validated.parentToolCallId,
2437
2680
  );
2681
+
2438
2682
  if (Option.isSome(collision)) {
2439
2683
  return yield* ChildReservationConflict.make({
2440
2684
  reservationId: validated.reservationId,
@@ -2443,10 +2687,12 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2443
2687
  });
2444
2688
  }
2445
2689
  const parent = yield* requireSubmission(operation, validated.parentSubmissionId);
2690
+
2446
2691
  // Creation is fenced by the parent lane's live ownership (spec §12 step 2): a stale
2447
2692
  // parent Attempt can never create new reservation state.
2448
2693
  yield* requireOwnership(operation, parent, validated.ownershipToken);
2449
2694
  const now = yield* currentInstant;
2695
+
2450
2696
  yield* sql`
2451
2697
  INSERT INTO effect_agent_child_reservations (
2452
2698
  reservation_id,
@@ -2467,6 +2713,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2467
2713
  )
2468
2714
  `.pipe(Effect.mapError(sqlFailure(operation)));
2469
2715
  const inserted = yield* readChildReservation(operation, validated.reservationId);
2716
+
2470
2717
  if (Option.isNone(inserted)) {
2471
2718
  return yield* corruptionFailure(
2472
2719
  operation,
@@ -2475,13 +2722,16 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2475
2722
  "An inserted child reservation row is missing inside its own transaction.",
2476
2723
  );
2477
2724
  }
2725
+
2478
2726
  return ReservedChildBudget.make({
2479
2727
  reservation: yield* childReservationSnapshotFromRow(operation, inserted.value),
2480
2728
  replayed: false,
2481
2729
  });
2482
2730
  }),
2483
2731
  );
2732
+
2484
2733
  yield* hitFailpoint("ledger:child-reservation:after", operation);
2734
+
2485
2735
  return reserved;
2486
2736
  });
2487
2737
 
@@ -2490,14 +2740,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2490
2740
  request: AttachChildToReservationRequest,
2491
2741
  ) {
2492
2742
  const operation = "ledger attach child to reservation";
2743
+
2493
2744
  const validated = yield* Schema.decodeUnknownEffect(
2494
2745
  Schema.toType(AttachChildToReservationRequest),
2495
2746
  )(request).pipe(Effect.mapError(internalFailure(operation)));
2747
+
2496
2748
  yield* hitFailpoint("ledger:child-attach:before", operation);
2749
+
2497
2750
  const attached = yield* inWriteTransaction(
2498
2751
  operation,
2499
2752
  Effect.gen(function* () {
2500
2753
  const existing = yield* readChildReservation(operation, validated.reservationId);
2754
+
2501
2755
  if (Option.isNone(existing)) {
2502
2756
  return yield* LedgerError.make({
2503
2757
  operation,
@@ -2509,6 +2763,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2509
2763
  if (existing.value.child_submission_id === validated.childSubmissionId) {
2510
2764
  return yield* childReservationSnapshotFromRow(operation, existing.value);
2511
2765
  }
2766
+
2512
2767
  return yield* ChildReservationConflict.make({
2513
2768
  reservationId: validated.reservationId,
2514
2769
  status: existing.value.status,
@@ -2516,6 +2771,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2516
2771
  });
2517
2772
  }
2518
2773
  const parent = yield* requireSubmission(operation, existing.value.parent_submission_id);
2774
+
2519
2775
  yield* requireOwnership(operation, parent, validated.ownershipToken);
2520
2776
  if (existing.value.status !== "reserved") {
2521
2777
  return yield* ChildReservationConflict.make({
@@ -2534,6 +2790,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2534
2790
  WHERE reservation_id = ${validated.reservationId}
2535
2791
  `.pipe(Effect.mapError(sqlFailure(operation)));
2536
2792
  const updated = yield* readChildReservation(operation, validated.reservationId);
2793
+
2537
2794
  if (Option.isNone(updated)) {
2538
2795
  return yield* corruptionFailure(
2539
2796
  operation,
@@ -2542,10 +2799,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2542
2799
  "An updated child reservation row is missing inside its own transaction.",
2543
2800
  );
2544
2801
  }
2802
+
2545
2803
  return yield* childReservationSnapshotFromRow(operation, updated.value);
2546
2804
  }),
2547
2805
  );
2806
+
2548
2807
  yield* hitFailpoint("ledger:child-attach:after", operation);
2808
+
2549
2809
  return attached;
2550
2810
  });
2551
2811
 
@@ -2553,17 +2813,22 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2553
2813
  "DoSubmissionLedger.beginChildBudgetRelease",
2554
2814
  )(function* (request: BeginChildBudgetReleaseRequest) {
2555
2815
  const operation = "ledger begin child budget release";
2816
+
2556
2817
  const validated = yield* Schema.decodeUnknownEffect(
2557
2818
  Schema.toType(BeginChildBudgetReleaseRequest),
2558
2819
  )(request).pipe(Effect.mapError(internalFailure(operation)));
2820
+
2559
2821
  const accountingJson = yield* encodePersistedJsonText(validated.accounting).pipe(
2560
2822
  Effect.mapError(internalFailure(operation)),
2561
2823
  );
2824
+
2562
2825
  yield* hitFailpoint("ledger:child-release-pending:before", operation);
2826
+
2563
2827
  const frozen = yield* inWriteTransaction(
2564
2828
  operation,
2565
2829
  Effect.gen(function* () {
2566
2830
  const existing = yield* readChildReservation(operation, validated.reservationId);
2831
+
2567
2832
  if (Option.isNone(existing)) {
2568
2833
  return yield* LedgerError.make({
2569
2834
  operation,
@@ -2575,6 +2840,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2575
2840
  operation,
2576
2841
  existing.value,
2577
2842
  );
2843
+
2578
2844
  // The accounting decision was already frozen exactly once; an identical replay is a
2579
2845
  // no-op and a divergent decision conflicts (spec §12 join step 6).
2580
2846
  if (
@@ -2583,6 +2849,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2583
2849
  ) {
2584
2850
  return existingSnapshot;
2585
2851
  }
2852
+
2586
2853
  return yield* ChildReservationConflict.make({
2587
2854
  reservationId: validated.reservationId,
2588
2855
  status: existing.value.status,
@@ -2590,6 +2857,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2590
2857
  });
2591
2858
  }
2592
2859
  const now = yield* currentInstant;
2860
+
2593
2861
  yield* sql`
2594
2862
  UPDATE effect_agent_child_reservations
2595
2863
  SET
@@ -2599,6 +2867,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2599
2867
  WHERE reservation_id = ${validated.reservationId}
2600
2868
  `.pipe(Effect.mapError(sqlFailure(operation)));
2601
2869
  const updated = yield* readChildReservation(operation, validated.reservationId);
2870
+
2602
2871
  if (Option.isNone(updated)) {
2603
2872
  return yield* corruptionFailure(
2604
2873
  operation,
@@ -2607,10 +2876,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2607
2876
  "An updated child reservation row is missing inside its own transaction.",
2608
2877
  );
2609
2878
  }
2879
+
2610
2880
  return yield* childReservationSnapshotFromRow(operation, updated.value);
2611
2881
  }),
2612
2882
  );
2883
+
2613
2884
  yield* hitFailpoint("ledger:child-release-pending:after", operation);
2885
+
2614
2886
  return frozen;
2615
2887
  });
2616
2888
 
@@ -2618,14 +2890,18 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2618
2890
  "DoSubmissionLedger.releaseChildBudget",
2619
2891
  )(function* (request: ReleaseChildBudgetRequest) {
2620
2892
  const operation = "ledger release child budget";
2893
+
2621
2894
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ReleaseChildBudgetRequest))(
2622
2895
  request,
2623
2896
  ).pipe(Effect.mapError(internalFailure(operation)));
2897
+
2624
2898
  yield* hitFailpoint("ledger:child-release:before", operation);
2899
+
2625
2900
  const released = yield* inWriteTransaction(
2626
2901
  operation,
2627
2902
  Effect.gen(function* () {
2628
2903
  const existing = yield* readChildReservation(operation, validated.reservationId);
2904
+
2629
2905
  if (Option.isNone(existing)) {
2630
2906
  return yield* LedgerError.make({
2631
2907
  operation,
@@ -2645,12 +2921,14 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2645
2921
  });
2646
2922
  }
2647
2923
  const now = yield* currentInstant;
2924
+
2648
2925
  yield* sql`
2649
2926
  UPDATE effect_agent_child_reservations
2650
2927
  SET status = 'released', released_at = ${now.iso}
2651
2928
  WHERE reservation_id = ${validated.reservationId}
2652
2929
  `.pipe(Effect.mapError(sqlFailure(operation)));
2653
2930
  const updated = yield* readChildReservation(operation, validated.reservationId);
2931
+
2654
2932
  if (Option.isNone(updated)) {
2655
2933
  return yield* corruptionFailure(
2656
2934
  operation,
@@ -2659,10 +2937,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2659
2937
  "An updated child reservation row is missing inside its own transaction.",
2660
2938
  );
2661
2939
  }
2940
+
2662
2941
  return yield* childReservationSnapshotFromRow(operation, updated.value);
2663
2942
  }),
2664
2943
  );
2944
+
2665
2945
  yield* hitFailpoint("ledger:child-release:after", operation);
2946
+
2666
2947
  return released;
2667
2948
  });
2668
2949
 
@@ -2678,6 +2959,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2678
2959
  LedgerError
2679
2960
  > {
2680
2961
  const operation = "ledger scan nonterminal";
2962
+
2681
2963
  const rows = yield* (
2682
2964
  cursor === undefined
2683
2965
  ? sql<Record<string, unknown>>`
@@ -2702,11 +2984,15 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2702
2984
  LIMIT ${SCAN_PAGE_SIZE}
2703
2985
  `
2704
2986
  ).pipe(Effect.mapError(sqlFailure(operation)));
2987
+
2705
2988
  const decoded = yield* decodeSubmissionRows(operation, "nonterminal_scan", rows);
2989
+
2706
2990
  const snapshots = yield* Effect.forEach(decoded, (row) =>
2707
2991
  decodeSubmissionSnapshot(operation, row),
2708
2992
  );
2993
+
2709
2994
  const last = decoded[decoded.length - 1];
2995
+
2710
2996
  const next: Option.Option<ScanCursor | undefined> =
2711
2997
  last === undefined || decoded.length < SCAN_PAGE_SIZE
2712
2998
  ? Option.none()
@@ -2714,6 +3000,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2714
3000
  threadId: last.thread_id,
2715
3001
  queueSequence: last.queue_sequence,
2716
3002
  });
3003
+
2717
3004
  return [snapshots, next] as const;
2718
3005
  });
2719
3006
 
@@ -2727,9 +3014,11 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2727
3014
  "DoSubmissionLedger.loadRecoverySnapshot",
2728
3015
  )(function* (request: RecoverySnapshotRequest) {
2729
3016
  const operation = "ledger load recovery snapshot";
3017
+
2730
3018
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(RecoverySnapshotRequest))(
2731
3019
  request,
2732
3020
  ).pipe(Effect.mapError(internalFailure(operation)));
3021
+
2733
3022
  return yield* sql
2734
3023
  .withTransaction(
2735
3024
  Effect.gen(function* () {
@@ -2738,6 +3027,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2738
3027
 
2739
3028
  let ownership: OwnershipSnapshot | undefined;
2740
3029
  const ownershipRow = yield* readOwnership(operation, validated.submissionId);
3030
+
2741
3031
  if (Option.isSome(ownershipRow)) {
2742
3032
  ownership = yield* decodeOwnershipSnapshot({
2743
3033
  attemptId: ownershipRow.value.attempt_id,
@@ -2748,6 +3038,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2748
3038
  }
2749
3039
 
2750
3040
  let inputApplied: InputAppliedMarker | undefined;
3041
+
2751
3042
  if (
2752
3043
  submissionRow.input_applied_record_id !== null &&
2753
3044
  submissionRow.input_applied_sequence !== null
@@ -2760,6 +3051,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2760
3051
 
2761
3052
  let reservation: SettlementReservationSnapshot | undefined;
2762
3053
  const reservationRow = yield* readReservation(operation, validated.submissionId);
3054
+
2763
3055
  if (Option.isSome(reservationRow)) {
2764
3056
  const record = yield* decodeRecordEnvelopeText(reservationRow.value.record_json).pipe(
2765
3057
  Effect.mapError((error) =>
@@ -2771,9 +3063,11 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2771
3063
  ),
2772
3064
  ),
2773
3065
  );
3066
+
2774
3067
  const settlementId = yield* Schema.decodeUnknownEffect(
2775
3068
  SettlementReservationSnapshot.fields.settlementId,
2776
3069
  )(reservationRow.value.settlement_id).pipe(Effect.mapError(internalFailure(operation)));
3070
+
2777
3071
  reservation = SettlementReservationSnapshot.make({
2778
3072
  settlementId,
2779
3073
  outcome: reservationRow.value.outcome,
@@ -2785,6 +3079,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2785
3079
 
2786
3080
  let abortIntent: AbortIntent | undefined;
2787
3081
  const abortRow = yield* readAbortIntent(operation, validated.submissionId);
3082
+
2788
3083
  if (Option.isSome(abortRow)) {
2789
3084
  abortIntent = yield* abortIntentFromRow(
2790
3085
  operation,
@@ -2802,11 +3097,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2802
3097
  WHERE joined_host_submission_id = ${validated.submissionId}
2803
3098
  ORDER BY queue_sequence ASC
2804
3099
  `.pipe(Effect.mapError(sqlFailure(operation)));
3100
+
2805
3101
  const joinSubmissions = yield* decodeSubmissionRows(
2806
3102
  operation,
2807
3103
  validated.submissionId,
2808
3104
  joinRows,
2809
3105
  );
3106
+
2810
3107
  const joins = yield* Effect.forEach(joinSubmissions, (row) =>
2811
3108
  decodeJoinSnapshot({
2812
3109
  submissionId: row.submission_id,
@@ -2816,6 +3113,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2816
3113
  );
2817
3114
 
2818
3115
  let hostSubmissionId: RecoverySnapshot["hostSubmissionId"];
3116
+
2819
3117
  if (submissionRow.joined_host_submission_id !== null) {
2820
3118
  hostSubmissionId = yield* decodeSubmissionId(
2821
3119
  submissionRow.joined_host_submission_id,
@@ -2823,6 +3121,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2823
3121
  }
2824
3122
 
2825
3123
  let suspension: SuspensionSnapshot | undefined;
3124
+
2826
3125
  if (submissionRow.suspended_reason_json !== null && submissionRow.suspended_at !== null) {
2827
3126
  const reason = yield* parseStoredJsonText(submissionRow.suspended_reason_json).pipe(
2828
3127
  Effect.mapError((error) =>
@@ -2834,6 +3133,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2834
3133
  ),
2835
3134
  ),
2836
3135
  );
3136
+
2837
3137
  suspension = yield* decodeSuspensionSnapshot({
2838
3138
  reason,
2839
3139
  suspendedAt: submissionRow.suspended_at,
@@ -2850,11 +3150,13 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2850
3150
  }
2851
3151
 
2852
3152
  const decisionRows = yield* readApprovalDecisions(operation, validated.submissionId);
3153
+
2853
3154
  const approvalDecisions = yield* Effect.forEach(decisionRows, (row) =>
2854
3155
  approvalIntentFromRow(operation, row),
2855
3156
  );
2856
3157
 
2857
3158
  const resolutionRows = yield* readUnknownResolutions(operation, validated.submissionId);
3159
+
2858
3160
  const unknownResolutions = yield* Effect.forEach(resolutionRows, (row) =>
2859
3161
  unknownResolutionIntentFromRow(operation, row),
2860
3162
  );
@@ -2871,20 +3173,25 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2871
3173
  WHERE parent_submission_id = ${validated.submissionId}
2872
3174
  ORDER BY parent_tool_call_id ASC
2873
3175
  `.pipe(Effect.mapError(sqlFailure(operation)));
3176
+
2874
3177
  const decodedChildReservations = yield* decodeChildReservationRows(
2875
3178
  operation,
2876
3179
  validated.submissionId,
2877
3180
  childReservationRows,
2878
3181
  );
3182
+
2879
3183
  const childReservations = yield* Effect.forEach(decodedChildReservations, (row) =>
2880
3184
  childReservationSnapshotFromRow(operation, row),
2881
3185
  );
3186
+
2882
3187
  const markers = yield* readChildSettlementMarkers(operation, validated.submissionId);
2883
3188
  const markersByChild = new Map(markers.map((row) => [row.child_submission_id, row]));
2884
3189
  const childAttachments: Array<ChildAttachmentSnapshot> = [];
3190
+
2885
3191
  for (const row of decodedChildReservations) {
2886
3192
  if (row.child_submission_id === null) continue;
2887
3193
  const child = yield* readSubmission(operation, row.child_submission_id);
3194
+
2888
3195
  if (Option.isSome(child)) {
2889
3196
  childAttachments.push(
2890
3197
  yield* decodeChildAttachmentSnapshot({
@@ -2899,6 +3206,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2899
3206
  continue;
2900
3207
  }
2901
3208
  const marker = markersByChild.get(row.child_submission_id);
3209
+
2902
3210
  if (marker === undefined) continue;
2903
3211
  childAttachments.push(
2904
3212
  yield* decodeChildAttachmentSnapshot({
@@ -2911,6 +3219,7 @@ const makeServices = Effect.fn("DoSubmissionLedger.makeServices")(function* () {
2911
3219
  }
2912
3220
 
2913
3221
  let parentLinkage: ParentLinkage | undefined;
3222
+
2914
3223
  if (
2915
3224
  submissionRow.parent_submission_id !== null &&
2916
3225
  submissionRow.parent_tool_call_id !== null