opencode-swarm 7.143.6 → 7.144.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/agents/architect.d.ts +64 -0
  2. package/dist/background/delegation-health.d.ts +213 -0
  3. package/dist/background/pending-delegations.d.ts +122 -15
  4. package/dist/cli/{config-doctor-72zp0k4x.js → config-doctor-5hj26phk.js} +2 -2
  5. package/dist/cli/{core-aj0wmbg8.js → core-aqtegsag.js} +1 -1
  6. package/dist/cli/{curator-llm-factory-x1vjhrnc.js → curator-llm-factory-1rg62kzr.js} +18 -18
  7. package/dist/cli/{curator-2gt2835v.js → curator-vcrcht4h.js} +18 -18
  8. package/dist/cli/{evidence-summary-service-yjr0662r.js → evidence-summary-service-fsh6jfhm.js} +6 -6
  9. package/dist/cli/{gate-evidence-r3c7eqpz.js → gate-evidence-9w2eehnj.js} +2 -2
  10. package/dist/cli/{guardrail-explain-f3zysesy.js → guardrail-explain-6mxn4bj8.js} +19 -19
  11. package/dist/cli/{guardrail-log-eat71fnh.js → guardrail-log-81c5b018.js} +3 -3
  12. package/dist/cli/{hive-promoter-fyb40am9.js → hive-promoter-rxkykddk.js} +18 -18
  13. package/dist/cli/{index-w1q9yy1e.js → index-1faydhv8.js} +3 -3
  14. package/dist/cli/{index-s7nb33pc.js → index-2ht8c7ew.js} +1 -1
  15. package/dist/cli/{index-92bm9ys3.js → index-2pmaxbvj.js} +1 -1
  16. package/dist/cli/{index-gzxz0s50.js → index-315tnsve.js} +1 -1
  17. package/dist/cli/{index-6vmazy9f.js → index-4fda8kkw.js} +1050 -88
  18. package/dist/cli/{index-fn0k0vsa.js → index-4s5htbgq.js} +1 -1
  19. package/dist/cli/{index-kc2x117y.js → index-8gs34d2q.js} +3 -3
  20. package/dist/cli/{index-peqmw3wr.js → index-8jrn4rwp.js} +2 -2
  21. package/dist/cli/{index-hjy4txgr.js → index-bgdr1ww3.js} +1 -1
  22. package/dist/cli/{index-wjk00vwk.js → index-c3zag2cw.js} +4 -4
  23. package/dist/cli/{index-02nm8qhk.js → index-dq26vbfp.js} +3 -3
  24. package/dist/cli/{index-5d8ydxae.js → index-e9w1tfmm.js} +129 -50
  25. package/dist/cli/{index-z4cv77tq.js → index-f79hf8dr.js} +2 -2
  26. package/dist/cli/{index-scj2asek.js → index-g0vr2a4m.js} +5 -5
  27. package/dist/cli/{index-dtf2va28.js → index-hc25qawy.js} +20 -20
  28. package/dist/cli/{index-nd1j9wkw.js → index-j2eb0x44.js} +1 -1
  29. package/dist/cli/{index-7bs015gm.js → index-j3byg0a9.js} +1 -1
  30. package/dist/cli/{index-whyrhjsk.js → index-mz1zwz96.js} +1 -1
  31. package/dist/cli/{index-72zhsqgy.js → index-n11zkp9g.js} +2 -2
  32. package/dist/cli/{index-36vry26a.js → index-rdb3nr6d.js} +1 -1
  33. package/dist/cli/{index-0adcjpyx.js → index-rr2fjfsd.js} +3 -3
  34. package/dist/cli/{index-bbv64s17.js → index-sqp6349j.js} +1 -1
  35. package/dist/cli/index.js +18 -18
  36. package/dist/cli/{knowledge-escalator-ejpyrby0.js → knowledge-escalator-hg4jzbrx.js} +6 -6
  37. package/dist/cli/{knowledge-events-yw2kydyy.js → knowledge-events-wgy7gbct.js} +4 -4
  38. package/dist/cli/{knowledge-store-j6gkk62e.js → knowledge-store-nd0f0e86.js} +1 -1
  39. package/dist/cli/{knowledge-validator-xervpe5k.js → knowledge-validator-0ar015bf.js} +2 -2
  40. package/dist/cli/{pending-delegations-19wg9j08.js → pending-delegations-thy8g30k.js} +23 -1
  41. package/dist/cli/{scan-cursor-x7a99wmq.js → scan-cursor-pqp3bsqv.js} +2 -2
  42. package/dist/cli/{schema-z141arx9.js → schema-4ew49zrv.js} +1 -1
  43. package/dist/cli/{scope-persistence-js90c1f4.js → scope-persistence-geth2hb1.js} +4 -4
  44. package/dist/cli/{skill-generator-t202jza0.js → skill-generator-8azm6p2y.js} +7 -7
  45. package/dist/cli/{worktree-collision-ownership-42bb3gcb.js → worktree-collision-ownership-j6d33p49.js} +1 -1
  46. package/dist/cli/{worktree-isolation-fbfvxw9a.js → worktree-isolation-cqxgdk2p.js} +18 -18
  47. package/dist/evaluation/contracts.d.ts +4 -4
  48. package/dist/evaluation/gate-ground-truth.d.ts +1 -1
  49. package/dist/hooks/init-orphan-recovery.d.ts +2 -0
  50. package/dist/index.js +439 -436
  51. package/dist/services/status-service.d.ts +9 -0
  52. package/package.json +1 -1
@@ -20,20 +20,225 @@ import {
20
20
  // src/background/pending-delegations.ts
21
21
  init_zod();
22
22
  import { createHash } from "crypto";
23
- import * as fs from "fs";
24
- import * as path from "path";
23
+ import * as fs2 from "fs";
24
+ import * as path2 from "path";
25
25
  import { isDeepStrictEqual } from "util";
26
26
  init_logger();
27
+
28
+ // src/background/delegation-health.ts
29
+ init_zod();
30
+ import * as fs from "fs";
31
+ import * as path from "path";
32
+ var BACKGROUND_DELEGATIONS_HEALTH_FILE = "background-delegations-health.json";
33
+ var MAX_RECOVERY_LEDGER_BYTES = 4 * 1024 * 1024;
34
+ var DelegationCheckpointAuditSchema = exports_external.object({
35
+ dispatchCount: exports_external.number().int().nonnegative(),
36
+ terminalsByStatus: exports_external.object({
37
+ completed: exports_external.number().int().nonnegative(),
38
+ error: exports_external.number().int().nonnegative(),
39
+ cancelled: exports_external.number().int().nonnegative(),
40
+ stale: exports_external.number().int().nonnegative()
41
+ }).strict(),
42
+ settledCount: exports_external.number().int().nonnegative(),
43
+ preservedCount: exports_external.number().int().nonnegative(),
44
+ lateTerminalCount: exports_external.number().int().nonnegative(),
45
+ compactedTransitionCount: exports_external.number().int().nonnegative(),
46
+ compactedRecordCount: exports_external.number().int().nonnegative(),
47
+ firstDispatchAt: exports_external.number().int().nonnegative().nullable(),
48
+ lastTerminalAt: exports_external.number().int().nonnegative().nullable(),
49
+ lastCompactionAt: exports_external.number().int().nonnegative()
50
+ }).strict();
51
+ var CheckpointSectionSchema = exports_external.object({
52
+ sequence: exports_external.number().int().positive(),
53
+ createdAt: exports_external.number().int().nonnegative(),
54
+ liveRecords: exports_external.number().int().nonnegative(),
55
+ closedSummaries: exports_external.number().int().nonnegative(),
56
+ bytes: exports_external.number().int().nonnegative(),
57
+ audit: DelegationCheckpointAuditSchema
58
+ }).strict();
59
+ var RecoverySectionSchema = exports_external.object({
60
+ source: exports_external.enum([
61
+ "checkpoint+tail",
62
+ "checkpoint+ledger-suffix",
63
+ "legacy-ledger",
64
+ "unknown"
65
+ ]),
66
+ at: exports_external.number().int().nonnegative(),
67
+ ok: exports_external.boolean(),
68
+ reason: exports_external.string().min(1).max(2000).optional(),
69
+ repairHint: exports_external.string().min(1).max(2000).optional()
70
+ }).strict();
71
+ var UncertaintySectionSchema = exports_external.object({
72
+ reason: exports_external.string().min(1).max(2000),
73
+ at: exports_external.number().int().nonnegative(),
74
+ source: exports_external.string().min(1).max(256),
75
+ repairHint: exports_external.string().min(1).max(2000).optional()
76
+ }).strict();
77
+ var DelegationLedgerHealthSchema = exports_external.object({
78
+ schemaVersion: exports_external.literal(1),
79
+ updatedAt: exports_external.number().int().nonnegative(),
80
+ ledger: exports_external.object({
81
+ bytes: exports_external.number().int().nonnegative(),
82
+ limitBytes: exports_external.number().int().positive(),
83
+ pressurePct: exports_external.number().min(0).max(100),
84
+ band: exports_external.enum(["ok", "nominal", "compact-overdue", "fail-closed"])
85
+ }).strict(),
86
+ checkpoint: CheckpointSectionSchema.nullable(),
87
+ recovery: RecoverySectionSchema.nullable(),
88
+ lastUncertainty: UncertaintySectionSchema.nullable(),
89
+ counts: exports_external.object({
90
+ activeOwners: exports_external.number().int().nonnegative(),
91
+ pendingAdvisories: exports_external.number().int().nonnegative(),
92
+ lateTerminals: exports_external.number().int().nonnegative(),
93
+ orphanWorktreeOwners: exports_external.number().int().nonnegative()
94
+ }).strict()
95
+ }).strict();
96
+ function sleepSync(ms) {
97
+ try {
98
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
99
+ } catch {
100
+ const start = Date.now();
101
+ while (Date.now() - start < ms) {}
102
+ }
103
+ }
104
+ var _healthInternals = {
105
+ renameOnce: (from, to) => {
106
+ fs.renameSync(from, to);
107
+ }
108
+ };
109
+ function healthArtifactPath(directory) {
110
+ return validateSwarmPath(directory, BACKGROUND_DELEGATIONS_HEALTH_FILE);
111
+ }
112
+ function readDelegationHealthArtifact(directory) {
113
+ let raw;
114
+ try {
115
+ raw = fs.readFileSync(healthArtifactPath(directory), "utf-8");
116
+ } catch {
117
+ return null;
118
+ }
119
+ try {
120
+ const parsed = DelegationLedgerHealthSchema.safeParse(JSON.parse(raw));
121
+ return parsed.success ? parsed.data : null;
122
+ } catch {
123
+ return null;
124
+ }
125
+ }
126
+ function writeDelegationHealthArtifact(directory, update) {
127
+ const existing = readDelegationHealthArtifact(directory);
128
+ const base = existing ?? {
129
+ schemaVersion: 1,
130
+ updatedAt: 0,
131
+ ledger: {
132
+ bytes: 0,
133
+ limitBytes: MAX_RECOVERY_LEDGER_BYTES,
134
+ pressurePct: 0,
135
+ band: "ok"
136
+ },
137
+ checkpoint: null,
138
+ recovery: null,
139
+ lastUncertainty: null,
140
+ counts: {
141
+ activeOwners: 0,
142
+ pendingAdvisories: 0,
143
+ lateTerminals: 0,
144
+ orphanWorktreeOwners: 0
145
+ }
146
+ };
147
+ const next = {
148
+ schemaVersion: 1,
149
+ updatedAt: Date.now(),
150
+ ledger: update.ledger ?? base.ledger,
151
+ checkpoint: update.checkpoint === undefined ? base.checkpoint : update.checkpoint,
152
+ recovery: update.recovery === undefined ? base.recovery : update.recovery,
153
+ lastUncertainty: update.lastUncertainty ?? base.lastUncertainty,
154
+ counts: update.counts ?? base.counts
155
+ };
156
+ if (update.uncertainty) {
157
+ next.lastUncertainty = update.uncertainty;
158
+ }
159
+ const parsed = DelegationLedgerHealthSchema.safeParse(next);
160
+ if (!parsed.success)
161
+ return null;
162
+ try {
163
+ fs.mkdirSync(path.resolve(directory, ".swarm"), { recursive: true });
164
+ const target = healthArtifactPath(directory);
165
+ const tmp = `${target}.tmp-${process.pid}-${Math.random().toString(36).slice(2, 10)}`;
166
+ fs.writeFileSync(tmp, `${JSON.stringify(parsed.data)}
167
+ `, "utf-8");
168
+ let lastError;
169
+ for (let attempt = 0;attempt < 5; attempt++) {
170
+ try {
171
+ _healthInternals.renameOnce(tmp, target);
172
+ lastError = undefined;
173
+ break;
174
+ } catch (err) {
175
+ lastError = err;
176
+ const code = err.code;
177
+ if (code !== "EEXIST" && code !== "EBUSY" && code !== "EPERM") {
178
+ break;
179
+ }
180
+ if (attempt < 4)
181
+ sleepSync(15);
182
+ }
183
+ }
184
+ if (lastError !== undefined) {
185
+ try {
186
+ fs.rmSync(tmp, { force: true });
187
+ } catch {}
188
+ return null;
189
+ }
190
+ return parsed.data;
191
+ } catch {
192
+ return null;
193
+ }
194
+ }
195
+ function collectDelegationLedgerHealth(directory, options) {
196
+ const artifact = readDelegationHealthArtifact(directory);
197
+ let ledgerBytes = 0;
198
+ let ledgerExists = false;
199
+ try {
200
+ ledgerBytes = fs.statSync(validateSwarmPath(directory, "background-delegations.jsonl")).size;
201
+ ledgerExists = true;
202
+ } catch {
203
+ ledgerExists = false;
204
+ }
205
+ if (!artifact && !ledgerExists)
206
+ return null;
207
+ const limitBytes = options.ledgerLimitBytes;
208
+ const pressurePct = Math.min(100, Math.round(ledgerBytes / limitBytes * 1000) / 10);
209
+ const band = ledgerBytes > limitBytes ? "fail-closed" : ledgerBytes > options.highWaterBytes ? "compact-overdue" : ledgerBytes > options.lowWaterBytes ? "nominal" : "ok";
210
+ return {
211
+ schemaVersion: 1,
212
+ updatedAt: artifact?.updatedAt ?? 0,
213
+ ledger: { bytes: ledgerBytes, limitBytes, pressurePct, band },
214
+ checkpoint: artifact?.checkpoint ?? null,
215
+ recovery: artifact?.recovery ?? null,
216
+ lastUncertainty: artifact?.lastUncertainty ?? null,
217
+ counts: artifact?.counts ?? {
218
+ activeOwners: 0,
219
+ pendingAdvisories: 0,
220
+ lateTerminals: 0,
221
+ orphanWorktreeOwners: 0
222
+ }
223
+ };
224
+ }
225
+ // src/background/pending-delegations.ts
27
226
  var BACKGROUND_DELEGATIONS_FILE = "background-delegations.jsonl";
28
227
  var BACKGROUND_DELEGATION_FALLBACK_DIR = "background-delegation-fallback";
29
228
  var BACKGROUND_CODER_RESERVATIONS_FILE = "background-coder-reservations.json";
229
+ var BACKGROUND_DELEGATIONS_CHECKPOINT_FILE = "background-delegations.checkpoint.json";
230
+ var BACKGROUND_DELEGATIONS_MANIFEST_FILE = "background-delegations.manifest.json";
30
231
  var MAX_LIVE_BACKGROUND_FALLBACKS = 256;
31
232
  var MAX_LIVE_BACKGROUND_CODER_RESERVATIONS = 256;
32
233
  var MAX_BACKGROUND_OBSERVED_FILES = 5000;
33
234
  var MAX_BACKGROUND_ADVISORY_CHARS = 4000;
34
235
  var MAX_BACKGROUND_DELEGATION_GENERATION = 1e6;
35
- var MAX_RECOVERY_LEDGER_BYTES = 4 * 1024 * 1024;
36
236
  var MAX_RECOVERY_FALLBACK_BYTES = 1024 * 1024;
237
+ var DELEGATION_COMPACTION_LOW_WATER_BYTES = 256 * 1024;
238
+ var DELEGATION_COMPACTION_HIGH_WATER_BYTES = 1024 * 1024;
239
+ var MAX_CHECKPOINT_BYTES = 2 * 1024 * 1024;
240
+ var MAX_CHECKPOINT_RECORDS = 2048;
241
+ var TOMBSTONE_MIN_AGE_MS = 72 * 60 * 60 * 1000;
37
242
  var STORE_LOCK_AGENT = "background";
38
243
  var STORE_LOCK_TASK = "background-delegations";
39
244
  var FALLBACK_LOCK_TASK = "background-delegation-fallback";
@@ -291,43 +496,359 @@ var FallbackArtifactSchema = exports_external.object({
291
496
  function storePath(directory) {
292
497
  return validateSwarmPath(directory, BACKGROUND_DELEGATIONS_FILE);
293
498
  }
294
- function ensureSwarmDir(directory) {
295
- fs.mkdirSync(path.resolve(directory, ".swarm"), { recursive: true });
499
+ function checkpointPath(directory) {
500
+ return validateSwarmPath(directory, BACKGROUND_DELEGATIONS_CHECKPOINT_FILE);
296
501
  }
297
- function readDelegations(directory) {
502
+ function manifestPath(directory) {
503
+ return validateSwarmPath(directory, BACKGROUND_DELEGATIONS_MANIFEST_FILE);
504
+ }
505
+ var SHA256_HEX = /^[0-9a-f]{64}$/;
506
+ var CheckpointSchema = exports_external.object({
507
+ schemaVersion: exports_external.literal(1),
508
+ sequence: exports_external.number().int().positive(),
509
+ writerId: exports_external.string().min(1).max(128),
510
+ rootPath: exports_external.string().min(1).max(4096),
511
+ createdAt: exports_external.number().int().nonnegative(),
512
+ cutLedgerBytes: exports_external.number().int().nonnegative(),
513
+ cutLedgerDigest: exports_external.string().regex(SHA256_HEX),
514
+ records: exports_external.array(RecordSchema).max(MAX_CHECKPOINT_RECORDS),
515
+ closed: exports_external.array(RecordSchema),
516
+ audit: DelegationCheckpointAuditSchema,
517
+ payloadChecksum: exports_external.string().regex(SHA256_HEX)
518
+ }).strict();
519
+ var ManifestSchema = exports_external.object({
520
+ schemaVersion: exports_external.literal(1),
521
+ sequence: exports_external.number().int().positive(),
522
+ checkpointChecksum: exports_external.string().regex(SHA256_HEX),
523
+ writerId: exports_external.string().min(1).max(128),
524
+ rootPath: exports_external.string().min(1).max(4096),
525
+ updatedAt: exports_external.number().int().nonnegative()
526
+ }).strict();
527
+ var WRITER_ID = `w-${process.pid}-${Math.random().toString(36).slice(2, 10)}`;
528
+ var _checkpointInternals = {
529
+ renameWithRetry: (from, to) => {
530
+ let lastError;
531
+ for (let attempt = 0;attempt < 5; attempt++) {
532
+ try {
533
+ _checkpointInternals.renameOnce(from, to);
534
+ return;
535
+ } catch (err) {
536
+ lastError = err;
537
+ const code = err.code;
538
+ if (code !== "EEXIST" && code !== "EBUSY" && code !== "EPERM") {
539
+ throw err;
540
+ }
541
+ _checkpointInternals.syncSleep(15);
542
+ }
543
+ }
544
+ throw lastError;
545
+ },
546
+ renameOnce: (from, to) => {
547
+ fs2.renameSync(from, to);
548
+ },
549
+ syncSleep: (ms) => {
550
+ try {
551
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
552
+ } catch {
553
+ const start = Date.now();
554
+ while (Date.now() - start < ms) {}
555
+ }
556
+ }
557
+ };
558
+ function writeDurableFileSync(target, contents) {
559
+ const tmp = `${target}.tmp-${process.pid}-${Math.random().toString(36).slice(2, 10)}`;
560
+ try {
561
+ const fd = fs2.openSync(tmp, "w");
562
+ try {
563
+ if (typeof contents === "string") {
564
+ fs2.writeSync(fd, contents);
565
+ } else {
566
+ fs2.writeSync(fd, contents, 0, contents.length);
567
+ }
568
+ fs2.fsyncSync(fd);
569
+ } finally {
570
+ fs2.closeSync(fd);
571
+ }
572
+ _checkpointInternals.renameWithRetry(tmp, target);
573
+ } catch (err) {
574
+ try {
575
+ fs2.rmSync(tmp, { force: true });
576
+ } catch {}
577
+ throw err;
578
+ }
579
+ try {
580
+ const dfd = fs2.openSync(path2.dirname(target), "r");
581
+ try {
582
+ fs2.fsyncSync(dfd);
583
+ } finally {
584
+ fs2.closeSync(dfd);
585
+ }
586
+ } catch {}
587
+ }
588
+ function readJsonFileWithRetry(target) {
298
589
  let raw;
299
590
  try {
300
- raw = fs.readFileSync(storePath(directory), "utf-8");
591
+ raw = fs2.readFileSync(target, "utf-8");
301
592
  } catch (err) {
302
- if (err.code === "ENOENT")
303
- return [];
304
- warn(`[background] readDelegations failed: ${err instanceof Error ? err.message : String(err)}`);
305
- return [];
593
+ const code = err.code;
594
+ if (code === "ENOENT")
595
+ return { status: "absent" };
596
+ return {
597
+ status: "invalid",
598
+ reason: `unreadable (${code ?? "unknown error"})`
599
+ };
600
+ }
601
+ try {
602
+ return { status: "ok", value: JSON.parse(raw) };
603
+ } catch (err) {
604
+ return {
605
+ status: "invalid",
606
+ reason: `malformed JSON (${err instanceof Error ? err.message : String(err)})`
607
+ };
608
+ }
609
+ }
610
+ function readDelegationManifest(directory) {
611
+ const read = readJsonFileWithRetry(manifestPath(directory));
612
+ if (read.status === "absent")
613
+ return { kind: "absent" };
614
+ if (read.status === "invalid")
615
+ return { kind: "invalid", reason: read.reason };
616
+ const parsed = ManifestSchema.safeParse(read.value);
617
+ if (!parsed.success) {
618
+ return { kind: "invalid", reason: "manifest fails schema validation" };
619
+ }
620
+ return { kind: "ok", manifest: parsed.data };
621
+ }
622
+ function readDelegationCheckpoint(directory) {
623
+ let bytes = 0;
624
+ try {
625
+ bytes = fs2.statSync(checkpointPath(directory)).size;
626
+ } catch {}
627
+ if (bytes > MAX_CHECKPOINT_BYTES) {
628
+ return {
629
+ kind: "invalid",
630
+ reason: `checkpoint exceeds the ${MAX_CHECKPOINT_BYTES}-byte bound`
631
+ };
632
+ }
633
+ const read = readJsonFileWithRetry(checkpointPath(directory));
634
+ if (read.status === "absent")
635
+ return { kind: "absent" };
636
+ if (read.status === "invalid")
637
+ return { kind: "invalid", reason: read.reason };
638
+ const parsed = CheckpointSchema.safeParse(read.value);
639
+ if (!parsed.success) {
640
+ return { kind: "invalid", reason: "checkpoint fails schema validation" };
641
+ }
642
+ return { kind: "ok", checkpoint: parsed.data, bytes };
643
+ }
644
+ function sha256Hex(data) {
645
+ return createHash("sha256").update(data).digest("hex");
646
+ }
647
+ function checkpointPayloadChecksum(checkpoint) {
648
+ return sha256Hex(JSON.stringify([
649
+ checkpoint.schemaVersion,
650
+ checkpoint.sequence,
651
+ checkpoint.writerId,
652
+ checkpoint.rootPath,
653
+ checkpoint.createdAt,
654
+ checkpoint.cutLedgerBytes,
655
+ checkpoint.cutLedgerDigest,
656
+ checkpoint.records,
657
+ checkpoint.closed,
658
+ checkpoint.audit
659
+ ]));
660
+ }
661
+ var CHECKPOINT_REBIND_HINT = "remove .swarm/background-delegations.manifest.json (manifest only) after verifying no in-flight background delegations; recovery then falls back to the full-ledger read. Only if you also want to discard pre-cut closed summaries and audit history \u2014 which for a compacted (rolled) ledger exist ONLY in .swarm/background-delegations.checkpoint.json \u2014 remove the checkpoint too or use the full reset below";
662
+ var CHECKPOINT_RESET_HINT = "the rolled tail no longer carries pre-checkpoint state: stop swarm processes, verify no in-flight background delegations, and remove .swarm/background-delegations.manifest.json, .swarm/background-delegations.checkpoint.json, and .swarm/background-delegations.jsonl to reset the store (or restore them from backup)";
663
+ function loadFoldedState(directory, options) {
664
+ const manifestRead = readDelegationManifest(directory);
665
+ if (manifestRead.kind === "invalid") {
666
+ return {
667
+ status: "uncertain",
668
+ reason: `background delegation manifest is invalid: ${manifestRead.reason}`,
669
+ repairHint: CHECKPOINT_RESET_HINT
670
+ };
671
+ }
672
+ if (manifestRead.kind === "absent") {
673
+ return loadLegacyLedger(directory, options.strict);
674
+ }
675
+ const manifest = manifestRead.manifest;
676
+ if (manifest.rootPath !== path2.resolve(directory)) {
677
+ return {
678
+ status: "uncertain",
679
+ reason: "background delegation checkpoint is bound to a different project root",
680
+ repairHint: CHECKPOINT_REBIND_HINT
681
+ };
682
+ }
683
+ const checkpointRead = readDelegationCheckpoint(directory);
684
+ if (checkpointRead.kind === "invalid" || checkpointRead.kind === "absent") {
685
+ const detail = checkpointRead.kind === "invalid" ? `: ${checkpointRead.reason}` : " (file missing)";
686
+ return {
687
+ status: "uncertain",
688
+ reason: `background delegation checkpoint is invalid${detail} while a manifest is published`,
689
+ repairHint: CHECKPOINT_RESET_HINT
690
+ };
691
+ }
692
+ const checkpoint = checkpointRead.checkpoint;
693
+ if (checkpoint.sequence !== manifest.sequence && checkpoint.sequence !== manifest.sequence + 1) {
694
+ return {
695
+ status: "uncertain",
696
+ reason: `background delegation checkpoint/manifest sequence mismatch (checkpoint ${checkpoint.sequence}, manifest ${manifest.sequence})`,
697
+ repairHint: CHECKPOINT_RESET_HINT
698
+ };
699
+ }
700
+ if (checkpoint.sequence === manifest.sequence && manifest.checkpointChecksum !== checkpoint.payloadChecksum) {
701
+ return {
702
+ status: "uncertain",
703
+ reason: "background delegation manifest checksum does not match its checkpoint",
704
+ repairHint: CHECKPOINT_RESET_HINT
705
+ };
706
+ }
707
+ if (checkpointPayloadChecksum(checkpoint) !== checkpoint.payloadChecksum) {
708
+ return {
709
+ status: "uncertain",
710
+ reason: "background delegation checkpoint payload checksum mismatch",
711
+ repairHint: CHECKPOINT_RESET_HINT
712
+ };
713
+ }
714
+ let stat;
715
+ try {
716
+ stat = fs2.statSync(storePath(directory));
717
+ } catch (error) {
718
+ return {
719
+ status: "uncertain",
720
+ reason: `background delegation ledger metadata is unreadable: ${error instanceof Error ? error.message : String(error)}`
721
+ };
722
+ }
723
+ let tail;
724
+ let mode;
725
+ if (stat.size >= checkpoint.cutLedgerBytes && checkpoint.cutLedgerBytes > 0) {
726
+ const prefix = readLedgerRegion(directory, 0, checkpoint.cutLedgerBytes);
727
+ if (sha256Hex(prefix) === checkpoint.cutLedgerDigest) {
728
+ const suffixBytes = stat.size - checkpoint.cutLedgerBytes;
729
+ if (suffixBytes > MAX_RECOVERY_LEDGER_BYTES) {
730
+ return {
731
+ status: "uncertain",
732
+ reason: `background delegation ledger changed beyond the ${MAX_RECOVERY_LEDGER_BYTES}-byte recovery bound`
733
+ };
734
+ }
735
+ tail = suffixBytes === 0 ? Buffer.alloc(0) : readLedgerRegion(directory, checkpoint.cutLedgerBytes, suffixBytes);
736
+ mode = "checkpoint+ledger-suffix";
737
+ } else {
738
+ tail = readBoundedRecentLedgerWindow(directory, stat.size);
739
+ mode = "checkpoint+tail";
740
+ }
741
+ } else {
742
+ tail = readBoundedRecentLedgerWindow(directory, stat.size);
743
+ mode = "checkpoint+tail";
744
+ }
745
+ const records = new Map;
746
+ for (const record of checkpoint.records) {
747
+ records.set(record.correlationId, record);
748
+ }
749
+ for (const summary of checkpoint.closed) {
750
+ records.set(summary.correlationId, summary);
751
+ }
752
+ const foldError = foldLedgerTail(records, tail, options.strict, checkpoint);
753
+ if (foldError)
754
+ return { status: "uncertain", reason: foldError };
755
+ return {
756
+ status: "ok",
757
+ mode,
758
+ records,
759
+ manifest,
760
+ checkpoint
761
+ };
762
+ }
763
+ function readLedgerRegion(directory, offset, length) {
764
+ const fd = fs2.openSync(storePath(directory), "r");
765
+ try {
766
+ const buffer = Buffer.alloc(length);
767
+ let read = 0;
768
+ while (read < length) {
769
+ const n = fs2.readSync(fd, buffer, read, length - read, offset + read);
770
+ if (n <= 0)
771
+ break;
772
+ read += n;
773
+ }
774
+ return read === length ? buffer : buffer.subarray(0, read);
775
+ } finally {
776
+ fs2.closeSync(fd);
777
+ }
778
+ }
779
+ function readBoundedRecentLedgerWindow(directory, size) {
780
+ if (size === 0)
781
+ return Buffer.alloc(0);
782
+ if (size <= MAX_RECOVERY_LEDGER_BYTES) {
783
+ return readLedgerRegion(directory, 0, size);
306
784
  }
307
- const folded = new Map;
308
- for (const line of raw.split(`
785
+ const window = readLedgerRegion(directory, size - MAX_RECOVERY_LEDGER_BYTES, MAX_RECOVERY_LEDGER_BYTES);
786
+ const firstNewline = window.indexOf(10);
787
+ return firstNewline === -1 ? Buffer.alloc(0) : window.subarray(firstNewline + 1);
788
+ }
789
+ function foldLedgerTail(records, tail, strict, checkpoint) {
790
+ let lineNumber = 0;
791
+ for (const line of tail.toString("utf-8").split(`
309
792
  `)) {
793
+ lineNumber += 1;
310
794
  const trimmed = line.trim();
311
- if (trimmed.length === 0)
795
+ if (!trimmed)
312
796
  continue;
313
797
  let parsedJson;
314
798
  try {
315
799
  parsedJson = JSON.parse(trimmed);
316
800
  } catch {
801
+ if (strict) {
802
+ return `background delegation ledger has malformed JSON at line ${lineNumber}`;
803
+ }
804
+ continue;
805
+ }
806
+ const parsed = RecordSchema.safeParse(parsedJson);
807
+ if (!parsed.success) {
808
+ if (strict) {
809
+ return `background delegation ledger has an invalid record at line ${lineNumber}`;
810
+ }
317
811
  continue;
318
812
  }
319
- const result = RecordSchema.safeParse(parsedJson);
320
- if (!result.success)
813
+ const existing = checkpoint ? records.get(parsed.data.correlationId) : undefined;
814
+ if (checkpoint && existing && !(parsed.data.updatedAt > existing.updatedAt) && !(parsed.data.updatedAt === existing.updatedAt && parsed.data.updatedAt > checkpoint.createdAt)) {
321
815
  continue;
322
- folded.set(result.data.correlationId, result.data);
816
+ }
817
+ records.set(parsed.data.correlationId, parsed.data);
323
818
  }
324
- return [...folded.values()];
819
+ return null;
325
820
  }
326
- function scanDelegationsForRecovery(directory) {
821
+ function loadLegacyLedger(directory, strict) {
822
+ if (!strict) {
823
+ let raw2;
824
+ try {
825
+ raw2 = fs2.readFileSync(storePath(directory), "utf-8");
826
+ } catch (err) {
827
+ if (err.code !== "ENOENT") {
828
+ warn(`[background] readDelegations failed: ${err instanceof Error ? err.message : String(err)}`);
829
+ }
830
+ return {
831
+ status: "ok",
832
+ mode: "legacy",
833
+ records: new Map,
834
+ manifest: null,
835
+ checkpoint: null
836
+ };
837
+ }
838
+ const records2 = new Map;
839
+ const foldError2 = foldLedgerTail(records2, Buffer.from(raw2, "utf-8"), false);
840
+ return {
841
+ status: "ok",
842
+ mode: "legacy",
843
+ records: records2,
844
+ manifest: null,
845
+ checkpoint: null
846
+ };
847
+ }
327
848
  let absolutePath;
328
849
  try {
329
850
  absolutePath = storePath(directory);
330
- const stat = fs.statSync(absolutePath);
851
+ const stat = fs2.statSync(absolutePath);
331
852
  if (stat.size > MAX_RECOVERY_LEDGER_BYTES) {
332
853
  return {
333
854
  status: "uncertain",
@@ -336,7 +857,13 @@ function scanDelegationsForRecovery(directory) {
336
857
  }
337
858
  } catch (error) {
338
859
  if (error.code === "ENOENT") {
339
- return { status: "ok", owners: [] };
860
+ return {
861
+ status: "ok",
862
+ mode: "legacy",
863
+ records: new Map,
864
+ manifest: null,
865
+ checkpoint: null
866
+ };
340
867
  }
341
868
  return {
342
869
  status: "uncertain",
@@ -345,7 +872,7 @@ function scanDelegationsForRecovery(directory) {
345
872
  }
346
873
  let raw;
347
874
  try {
348
- raw = fs.readFileSync(absolutePath, "utf-8");
875
+ raw = fs2.readFileSync(absolutePath, "utf-8");
349
876
  } catch (error) {
350
877
  return {
351
878
  status: "uncertain",
@@ -358,33 +885,392 @@ function scanDelegationsForRecovery(directory) {
358
885
  reason: `background delegation ledger changed beyond the ${MAX_RECOVERY_LEDGER_BYTES}-byte recovery bound`
359
886
  };
360
887
  }
361
- const folded = new Map;
362
- let lineNumber = 0;
363
- for (const line of raw.split(`
364
- `)) {
365
- lineNumber += 1;
366
- const trimmed = line.trim();
367
- if (!trimmed)
888
+ const records = new Map;
889
+ const foldError = foldLedgerTail(records, Buffer.from(raw, "utf-8"), true);
890
+ if (foldError)
891
+ return { status: "uncertain", reason: foldError };
892
+ return {
893
+ status: "ok",
894
+ mode: "legacy",
895
+ records,
896
+ manifest: null,
897
+ checkpoint: null
898
+ };
899
+ }
900
+ function loadRecordsForWrite(directory) {
901
+ const load = loadFoldedState(directory, { strict: false });
902
+ if (load.status === "uncertain") {
903
+ recordLedgerUncertainty(directory, load.reason, "mutation", load.repairHint);
904
+ return null;
905
+ }
906
+ return [...load.records.values()];
907
+ }
908
+ function findRecordForWrite(records, correlationId) {
909
+ if (!records)
910
+ return null;
911
+ for (const record of records) {
912
+ if (record.correlationId === correlationId)
913
+ return record;
914
+ }
915
+ return null;
916
+ }
917
+ function recordLedgerUncertainty(directory, reason, source, repairHint) {
918
+ try {
919
+ writeDelegationHealthArtifact(directory, {
920
+ uncertainty: {
921
+ reason,
922
+ at: Date.now(),
923
+ source,
924
+ ...repairHint ? { repairHint } : {}
925
+ }
926
+ });
927
+ } catch {}
928
+ }
929
+ function isUnsettledWorktreeOwner(record) {
930
+ return Boolean(record.worktree) && !(record.coderSettlement?.state === "settled" && record.coderSettlement.outcome?.kind === "standard-worktree" && (record.coderSettlement.outcome.result === "merged" || record.coderSettlement.outcome.result === "unchanged"));
931
+ }
932
+ function isCheckpointLiveRecord(record) {
933
+ if (!isTerminal(record.status))
934
+ return true;
935
+ if (record.advisoryInbox?.state === "pending")
936
+ return true;
937
+ const settlement = record.coderSettlement;
938
+ if (settlement && settlement.state !== "settled")
939
+ return true;
940
+ if (settlement?.state === "settled" && isUnsettledWorktreeOwner(record)) {
941
+ return true;
942
+ }
943
+ if (isActiveCoderOwner(record))
944
+ return true;
945
+ return false;
946
+ }
947
+ function buildClosedSummary(record) {
948
+ const summary = { ...record };
949
+ delete summary.prompt;
950
+ delete summary.taskChangeContext;
951
+ if (summary.result) {
952
+ summary.result = stripResultBody(summary.result);
953
+ }
954
+ if (summary.terminalResult) {
955
+ summary.terminalResult = {
956
+ ...summary.terminalResult,
957
+ result: stripResultBody(summary.terminalResult.result)
958
+ };
959
+ }
960
+ const parsed = RecordSchema.safeParse(summary);
961
+ return parsed.success ? parsed.data : null;
962
+ }
963
+ function stripResultBody(result) {
964
+ const { text: _text, error: _error, ...rest } = result;
965
+ return rest;
966
+ }
967
+ function emptyAudit() {
968
+ return {
969
+ dispatchCount: 0,
970
+ terminalsByStatus: { completed: 0, error: 0, cancelled: 0, stale: 0 },
971
+ settledCount: 0,
972
+ preservedCount: 0,
973
+ lateTerminalCount: 0,
974
+ compactedTransitionCount: 0,
975
+ compactedRecordCount: 0,
976
+ firstDispatchAt: null,
977
+ lastTerminalAt: null,
978
+ lastCompactionAt: 0
979
+ };
980
+ }
981
+ function terminalEventStatusOf(record) {
982
+ if (record.terminalResult) {
983
+ return record.terminalResult.status;
984
+ }
985
+ if (record.status === "completed" || record.status === "error" || record.status === "cancelled" || record.status === "stale") {
986
+ return record.status;
987
+ }
988
+ return null;
989
+ }
990
+ function mergeCheckpointAudit(previous, previousCheckpoint, folded, healthLateTerminals, retiredLineCount, newlySummarizedCount, now) {
991
+ const prev = previous ?? emptyAudit();
992
+ const prevById = new Map;
993
+ if (previousCheckpoint) {
994
+ for (const record of previousCheckpoint.records) {
995
+ prevById.set(record.correlationId, record);
996
+ }
997
+ for (const summary of previousCheckpoint.closed) {
998
+ prevById.set(summary.correlationId, summary);
999
+ }
1000
+ }
1001
+ const audit = {
1002
+ dispatchCount: prev.dispatchCount,
1003
+ terminalsByStatus: { ...prev.terminalsByStatus },
1004
+ settledCount: prev.settledCount,
1005
+ preservedCount: prev.preservedCount,
1006
+ lateTerminalCount: Math.max(prev.lateTerminalCount, healthLateTerminals),
1007
+ compactedTransitionCount: capCounter(prev.compactedTransitionCount, retiredLineCount),
1008
+ compactedRecordCount: capCounter(prev.compactedRecordCount, newlySummarizedCount),
1009
+ firstDispatchAt: prev.firstDispatchAt,
1010
+ lastTerminalAt: prev.lastTerminalAt,
1011
+ lastCompactionAt: now
1012
+ };
1013
+ let minCreated = Number.POSITIVE_INFINITY;
1014
+ let maxTerminal = 0;
1015
+ for (const record of folded) {
1016
+ const prevRecord = prevById.get(record.correlationId);
1017
+ if (!prevRecord) {
1018
+ audit.dispatchCount += 1;
1019
+ }
1020
+ const terminalStatus = terminalEventStatusOf(record);
1021
+ if (terminalStatus) {
1022
+ const prevStatus = prevRecord ? terminalEventStatusOf(prevRecord) : null;
1023
+ if (prevStatus !== terminalStatus) {
1024
+ audit.terminalsByStatus[terminalStatus] += 1;
1025
+ }
1026
+ maxTerminal = Math.max(maxTerminal, record.terminalResult?.recordedAt ?? record.completedAt ?? 0);
1027
+ }
1028
+ if (record.coderSettlement?.state === "settled" && prevRecord?.coderSettlement?.state !== "settled") {
1029
+ audit.settledCount += 1;
1030
+ }
1031
+ if (record.coderSettlement?.state === "preserved" && prevRecord?.coderSettlement?.state !== "preserved") {
1032
+ audit.preservedCount += 1;
1033
+ }
1034
+ minCreated = Math.min(minCreated, record.createdAt);
1035
+ }
1036
+ audit.firstDispatchAt = Number.isFinite(minCreated) ? Math.min(prev.firstDispatchAt ?? Number.POSITIVE_INFINITY, minCreated) : prev.firstDispatchAt;
1037
+ audit.lastTerminalAt = Math.max(prev.lastTerminalAt ?? 0, maxTerminal) || null;
1038
+ return audit;
1039
+ }
1040
+ function capCounter(previous, delta) {
1041
+ return Number.isSafeInteger(previous + delta) ? previous + delta : Number.MAX_SAFE_INTEGER;
1042
+ }
1043
+ async function compactBackgroundDelegations(directory, options = {}) {
1044
+ try {
1045
+ let outcome = {
1046
+ status: "skipped",
1047
+ reason: "not attempted"
1048
+ };
1049
+ await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
1050
+ outcome = compactDelegationsLocked(directory, options);
1051
+ });
1052
+ return outcome;
1053
+ } catch (err) {
1054
+ const message = err instanceof Error ? err.message : String(err);
1055
+ warn(`[background] compactBackgroundDelegations failed: ${message}`);
1056
+ return { status: "uncertain", reason: message };
1057
+ }
1058
+ }
1059
+ function compactDelegationsLocked(directory, options) {
1060
+ const load = loadFoldedState(directory, { strict: false });
1061
+ if (load.status === "uncertain") {
1062
+ recordLedgerUncertainty(directory, load.reason, "compaction", load.repairHint);
1063
+ return { status: "uncertain", reason: load.reason };
1064
+ }
1065
+ let ledgerBytes;
1066
+ try {
1067
+ ledgerBytes = fs2.readFileSync(storePath(directory));
1068
+ } catch (err) {
1069
+ if (err.code === "ENOENT") {
1070
+ return { status: "skipped", reason: "no ledger to compact" };
1071
+ }
1072
+ return {
1073
+ status: "uncertain",
1074
+ reason: err instanceof Error ? err.message : String(err)
1075
+ };
1076
+ }
1077
+ if (ledgerBytes.length <= DELEGATION_COMPACTION_HIGH_WATER_BYTES && !options.force) {
1078
+ return {
1079
+ status: "skipped",
1080
+ reason: "ledger below the compaction high-water mark"
1081
+ };
1082
+ }
1083
+ const cutLedgerBytes = ledgerBytes.length;
1084
+ const retiredLineCount = countCompleteLines(ledgerBytes);
1085
+ const now = Date.now();
1086
+ const folded = [...load.records.values()];
1087
+ const live = [];
1088
+ const closedCandidates = [];
1089
+ for (const record of folded) {
1090
+ if (isCheckpointLiveRecord(record)) {
1091
+ live.push(record);
1092
+ } else {
1093
+ closedCandidates.push(buildClosedSummary(record) ?? record);
1094
+ }
1095
+ }
1096
+ if (live.length > MAX_CHECKPOINT_RECORDS) {
1097
+ recordLedgerUncertainty(directory, `checkpoint live-record budget exceeded (${live.length} > ${MAX_CHECKPOINT_RECORDS}); compaction skipped`, "compaction");
1098
+ return {
1099
+ status: "skipped",
1100
+ reason: `live record count ${live.length} exceeds the checkpoint budget ${MAX_CHECKPOINT_RECORDS}`
1101
+ };
1102
+ }
1103
+ closedCandidates.sort((a, b) => b.updatedAt - a.updatedAt);
1104
+ const baseOverhead = Buffer.byteLength(JSON.stringify({
1105
+ schemaVersion: 1,
1106
+ sequence: 1,
1107
+ writerId: WRITER_ID,
1108
+ rootPath: path2.resolve(directory),
1109
+ createdAt: now,
1110
+ cutLedgerBytes,
1111
+ cutLedgerDigest: sha256Hex(ledgerBytes),
1112
+ records: live,
1113
+ closed: [],
1114
+ audit: emptyAudit(),
1115
+ payloadChecksum: "0".repeat(64)
1116
+ }), "utf-8");
1117
+ let used = baseOverhead;
1118
+ const keptClosed = [];
1119
+ let evicted = 0;
1120
+ for (const entry of closedCandidates) {
1121
+ const cost = Buffer.byteLength(JSON.stringify(entry), "utf-8") + 1;
1122
+ if (used + cost > MAX_CHECKPOINT_BYTES) {
1123
+ if (now - entry.updatedAt < TOMBSTONE_MIN_AGE_MS) {
1124
+ recordLedgerUncertainty(directory, "checkpoint byte budget would evict a young closed summary; compaction skipped", "compaction");
1125
+ return {
1126
+ status: "skipped",
1127
+ reason: "checkpoint byte budget would evict a young closed summary"
1128
+ };
1129
+ }
1130
+ evicted += 1;
368
1131
  continue;
369
- let parsedJson;
370
- try {
371
- parsedJson = JSON.parse(trimmed);
372
- } catch {
373
- return {
374
- status: "uncertain",
375
- reason: `background delegation ledger has malformed JSON at line ${lineNumber}`
376
- };
377
1132
  }
378
- const parsed = RecordSchema.safeParse(parsedJson);
379
- if (!parsed.success) {
380
- return {
381
- status: "uncertain",
382
- reason: `background delegation ledger has an invalid record at line ${lineNumber}`
383
- };
1133
+ used += cost;
1134
+ keptClosed.push(entry);
1135
+ }
1136
+ const sequence = Math.max(load.manifest?.sequence ?? 0, load.checkpoint?.sequence ?? 0, 0) + 1;
1137
+ let healthLateTerminals = 0;
1138
+ try {
1139
+ const artifact = readDelegationHealthArtifact(directory);
1140
+ healthLateTerminals = artifact?.counts.lateTerminals ?? 0;
1141
+ } catch {
1142
+ healthLateTerminals = 0;
1143
+ }
1144
+ const previousClosedIds = new Set((load.checkpoint?.closed ?? []).map((entry) => entry.correlationId));
1145
+ const newlySummarized = keptClosed.filter((entry) => !previousClosedIds.has(entry.correlationId)).length;
1146
+ const audit = mergeCheckpointAudit(load.checkpoint?.audit ?? null, load.checkpoint, folded, healthLateTerminals, retiredLineCount, newlySummarized + evicted, now);
1147
+ const checkpoint = {
1148
+ schemaVersion: 1,
1149
+ sequence,
1150
+ writerId: WRITER_ID,
1151
+ rootPath: path2.resolve(directory),
1152
+ createdAt: now,
1153
+ cutLedgerBytes,
1154
+ cutLedgerDigest: sha256Hex(ledgerBytes),
1155
+ records: live,
1156
+ closed: keptClosed,
1157
+ audit,
1158
+ payloadChecksum: ""
1159
+ };
1160
+ checkpoint.payloadChecksum = checkpointPayloadChecksum(checkpoint);
1161
+ const checkpointJson = `${JSON.stringify(checkpoint)}
1162
+ `;
1163
+ if (Buffer.byteLength(checkpointJson, "utf-8") > MAX_CHECKPOINT_BYTES) {
1164
+ recordLedgerUncertainty(directory, "serialized checkpoint exceeds the byte budget; compaction skipped", "compaction");
1165
+ return {
1166
+ status: "skipped",
1167
+ reason: "serialized checkpoint exceeds the byte budget"
1168
+ };
1169
+ }
1170
+ writeDurableFileSync(checkpointPath(directory), checkpointJson);
1171
+ writeDurableFileSync(manifestPath(directory), `${JSON.stringify({
1172
+ schemaVersion: 1,
1173
+ sequence,
1174
+ checkpointChecksum: checkpoint.payloadChecksum,
1175
+ writerId: WRITER_ID,
1176
+ rootPath: checkpoint.rootPath,
1177
+ updatedAt: now
1178
+ })}
1179
+ `);
1180
+ let currentSize;
1181
+ try {
1182
+ currentSize = fs2.statSync(storePath(directory)).size;
1183
+ } catch (err) {
1184
+ return {
1185
+ status: "uncertain",
1186
+ reason: `ledger vanished during compaction: ${err instanceof Error ? err.message : String(err)}`
1187
+ };
1188
+ }
1189
+ if (currentSize < cutLedgerBytes) {
1190
+ return {
1191
+ status: "skipped",
1192
+ reason: "ledger shrank during compaction; checkpoint published unrolled"
1193
+ };
1194
+ }
1195
+ const tailContent = currentSize > cutLedgerBytes ? readLedgerRegion(directory, cutLedgerBytes, currentSize - cutLedgerBytes) : Buffer.alloc(0);
1196
+ writeDurableFileSync(storePath(directory), tailContent);
1197
+ try {
1198
+ const pressurePct = Math.min(100, Math.round(tailContent.length / MAX_RECOVERY_LEDGER_BYTES * 1000) / 10);
1199
+ writeDelegationHealthArtifact(directory, {
1200
+ ledger: {
1201
+ bytes: tailContent.length,
1202
+ limitBytes: MAX_RECOVERY_LEDGER_BYTES,
1203
+ pressurePct,
1204
+ band: tailContent.length > DELEGATION_COMPACTION_HIGH_WATER_BYTES ? "compact-overdue" : tailContent.length > DELEGATION_COMPACTION_LOW_WATER_BYTES ? "nominal" : "ok"
1205
+ },
1206
+ checkpoint: {
1207
+ sequence,
1208
+ createdAt: now,
1209
+ liveRecords: live.length,
1210
+ closedSummaries: keptClosed.length,
1211
+ bytes: Buffer.byteLength(checkpointJson, "utf-8"),
1212
+ audit
1213
+ },
1214
+ counts: {
1215
+ activeOwners: folded.filter((record) => isActiveCoderOwner(record)).length,
1216
+ pendingAdvisories: folded.filter((record) => record.advisoryInbox?.state === "pending").length,
1217
+ lateTerminals: audit.lateTerminalCount,
1218
+ orphanWorktreeOwners: folded.filter(isUnsettledWorktreeOwner).length
1219
+ }
1220
+ });
1221
+ } catch {}
1222
+ return {
1223
+ status: "compacted",
1224
+ sequence,
1225
+ tailBytes: tailContent.length,
1226
+ checkpointBytes: Buffer.byteLength(checkpointJson, "utf-8")
1227
+ };
1228
+ }
1229
+ function countCompleteLines(buffer) {
1230
+ let count = 0;
1231
+ for (const byte of buffer) {
1232
+ if (byte === 10)
1233
+ count += 1;
1234
+ }
1235
+ return count;
1236
+ }
1237
+ function maybeCompactDelegationsLocked(directory) {
1238
+ try {
1239
+ const stat = fs2.statSync(storePath(directory));
1240
+ if (stat.size <= DELEGATION_COMPACTION_HIGH_WATER_BYTES)
1241
+ return;
1242
+ const outcome = compactDelegationsLocked(directory, {});
1243
+ if (outcome.status === "uncertain") {
1244
+ warn(`[background] post-append compaction skipped: ${outcome.reason}`);
384
1245
  }
385
- folded.set(parsed.data.correlationId, parsed.data);
1246
+ } catch (err) {
1247
+ warn(`[background] post-append compaction check failed: ${err instanceof Error ? err.message : String(err)}`);
1248
+ }
1249
+ }
1250
+ function ensureSwarmDir(directory) {
1251
+ fs2.mkdirSync(path2.resolve(directory, ".swarm"), { recursive: true });
1252
+ }
1253
+ function readDelegations(directory) {
1254
+ const load = loadFoldedState(directory, { strict: false });
1255
+ if (load.status === "uncertain") {
1256
+ warn(`[background] readDelegations: authoritative state uncertain (${load.reason}); returning empty`);
1257
+ return [];
1258
+ }
1259
+ return [...load.records.values()];
1260
+ }
1261
+ function scanDelegationsForRecovery(directory) {
1262
+ const load = loadFoldedState(directory, { strict: true });
1263
+ if (load.status === "uncertain") {
1264
+ const manifestKind = readDelegationManifest(directory).kind;
1265
+ return {
1266
+ status: "uncertain",
1267
+ reason: load.reason,
1268
+ source: manifestKind === "absent" ? "legacy-ledger" : "unknown",
1269
+ ...load.repairHint ? { repairHint: load.repairHint } : {}
1270
+ };
386
1271
  }
387
- return { status: "ok", owners: [...folded.values()] };
1272
+ const source = load.mode === "legacy" ? "legacy-ledger" : load.mode;
1273
+ return { status: "ok", owners: [...load.records.values()], source };
388
1274
  }
389
1275
  function findByCorrelationId(directory, correlationId) {
390
1276
  if (!correlationId)
@@ -397,7 +1283,7 @@ function findByCorrelationId(directory, correlationId) {
397
1283
  }
398
1284
  function appendRecord(directory, record) {
399
1285
  ensureSwarmDir(directory);
400
- fs.appendFileSync(storePath(directory), `${JSON.stringify(record)}
1286
+ fs2.appendFileSync(storePath(directory), `${JSON.stringify(record)}
401
1287
  `, "utf-8");
402
1288
  }
403
1289
  function buildPendingRecord(input, now) {
@@ -430,7 +1316,7 @@ function buildPendingRecord(input, now) {
430
1316
  ...input.generation !== undefined ? { generation: input.generation } : {}
431
1317
  };
432
1318
  }
433
- function pendingLaunchIdentity(record) {
1319
+ function pendingLaunchIdentity(record, summaryAware) {
434
1320
  return {
435
1321
  correlationId: record.correlationId,
436
1322
  jobId: record.jobId,
@@ -448,16 +1334,19 @@ function pendingLaunchIdentity(record) {
448
1334
  ownedWorkflowLanes: record.ownedWorkflowLanes,
449
1335
  promptHash: record.promptHash,
450
1336
  workspace: record.workspace,
451
- taskChangeContext: record.taskChangeContext,
452
- workflowGeneration: record.workflowGeneration,
453
- worktree: record.worktree,
454
- coderReservationId: record.coderReservationId,
455
- prompt: record.prompt,
456
- generation: record.generation ?? 1
1337
+ ...summaryAware ? {} : {
1338
+ taskChangeContext: record.taskChangeContext,
1339
+ workflowGeneration: record.workflowGeneration,
1340
+ worktree: record.worktree,
1341
+ coderReservationId: record.coderReservationId,
1342
+ prompt: record.prompt,
1343
+ generation: record.generation ?? 1
1344
+ }
457
1345
  };
458
1346
  }
459
1347
  function samePendingLaunchIdentity(left, right) {
460
- return isDeepStrictEqual(pendingLaunchIdentity(left), pendingLaunchIdentity(right));
1348
+ const summaryAware = isTerminal(left.status) && left.prompt === undefined && left.taskChangeContext === undefined;
1349
+ return isDeepStrictEqual(pendingLaunchIdentity(left, summaryAware), pendingLaunchIdentity(right, summaryAware));
461
1350
  }
462
1351
  async function recordPendingDelegationDetailed(directory, input, options = {}) {
463
1352
  const now = Date.now();
@@ -476,7 +1365,10 @@ async function recordPendingDelegationDetailed(directory, input, options = {}) {
476
1365
  if (options.staleTimeoutMs && options.staleTimeoutMs > 0) {
477
1366
  sweepStaleLocked(directory, options.staleTimeoutMs, now);
478
1367
  }
479
- const existing = findByCorrelationId(directory, parsedRecord.data.correlationId);
1368
+ const records = loadRecordsForWrite(directory);
1369
+ if (records === null)
1370
+ return;
1371
+ const existing = findRecordForWrite(records, parsedRecord.data.correlationId);
480
1372
  if (existing) {
481
1373
  outcome = {
482
1374
  status: samePendingLaunchIdentity(existing, parsedRecord.data) ? "duplicate" : "conflict",
@@ -485,6 +1377,7 @@ async function recordPendingDelegationDetailed(directory, input, options = {}) {
485
1377
  return;
486
1378
  }
487
1379
  appendRecord(directory, parsedRecord.data);
1380
+ maybeCompactDelegationsLocked(directory);
488
1381
  outcome = { status: "recorded", record: parsedRecord.data };
489
1382
  });
490
1383
  return outcome;
@@ -513,7 +1406,10 @@ async function appendDelegationTransition(directory, correlationId, transition)
513
1406
  try {
514
1407
  let next = null;
515
1408
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
516
- const current = findByCorrelationId(directory, correlationId);
1409
+ const records = loadRecordsForWrite(directory);
1410
+ if (records === null)
1411
+ return;
1412
+ const current = findRecordForWrite(records, correlationId);
517
1413
  if (!current)
518
1414
  return;
519
1415
  if (isTerminal(current.status) && transition.status !== "consumed" && transition.status !== "ingestion_error" && !(current.status === "completed" && transition.status === "stale")) {
@@ -529,6 +1425,7 @@ async function appendDelegationTransition(directory, correlationId, transition)
529
1425
  ...transition.result ? { result: transition.result } : {}
530
1426
  };
531
1427
  appendRecord(directory, next);
1428
+ maybeCompactDelegationsLocked(directory);
532
1429
  });
533
1430
  return next;
534
1431
  } catch (err) {
@@ -549,7 +1446,10 @@ function sameJson(left, right) {
549
1446
  return JSON.stringify(left) === JSON.stringify(right);
550
1447
  }
551
1448
  function sameTerminalEvent(left, right) {
552
- return left.eventId === right.eventId && left.status === right.status && sameJson(left.result, right.result);
1449
+ return left.eventId === right.eventId && left.status === right.status && sameRetainedResult(left.result, right.result);
1450
+ }
1451
+ function sameRetainedResult(left, right) {
1452
+ return left.chars === right.chars && left.truncated === right.truncated && left.digest === right.digest && left.outputRef === right.outputRef && left.outputPreviewChars === right.outputPreviewChars && left.outputDegraded === right.outputDegraded && left.outputArtifactError === right.outputArtifactError && left.transcriptIncomplete === right.transcriptIncomplete && left.messageCount === right.messageCount && sameJson(left.salvagedWorkflowLanes, right.salvagedWorkflowLanes);
553
1453
  }
554
1454
  function settlementProvenanceFor(record) {
555
1455
  const baseline = record.taskChangeContext?.baseline;
@@ -582,12 +1482,16 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
582
1482
  let claim = null;
583
1483
  try {
584
1484
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
585
- const current = findByCorrelationId(directory, correlationId);
1485
+ const records = loadRecordsForWrite(directory);
1486
+ if (records === null)
1487
+ return;
1488
+ const current = findRecordForWrite(records, correlationId);
586
1489
  if (!current)
587
1490
  return;
588
1491
  if (current.terminalResult) {
589
1492
  if (!sameTerminalEvent(current.terminalResult, parsedTerminal.data)) {
590
1493
  warn(`[background] claimTerminalResult: different terminal event for ` + `correlationId=${correlationId}; ` + `existing={status: ${current.terminalResult.status}, eventId: ${current.terminalResult.eventId}} ` + `incoming={status: ${parsedTerminal.data.status}, eventId: ${parsedTerminal.data.eventId}}; ` + `rejected`);
1494
+ incrementLateTerminalCount(directory);
591
1495
  return;
592
1496
  }
593
1497
  claim = {
@@ -611,6 +1515,7 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
611
1515
  };
612
1516
  }
613
1517
  }
1518
+ const foldUpdatedAt = Math.max(parsedTerminal.data.recordedAt, current.updatedAt);
614
1519
  const next = {
615
1520
  ...current,
616
1521
  schemaVersion: 3,
@@ -618,12 +1523,13 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
618
1523
  terminalResult: parsedTerminal.data,
619
1524
  result: parsedTerminal.data.result,
620
1525
  completedAt: parsedTerminal.data.recordedAt,
621
- updatedAt: parsedTerminal.data.recordedAt,
1526
+ updatedAt: foldUpdatedAt,
622
1527
  ...coderSettlement ? { coderSettlement } : {}
623
1528
  };
624
1529
  if (!RecordSchema.safeParse(next).success)
625
1530
  return;
626
1531
  appendRecord(directory, next);
1532
+ maybeCompactDelegationsLocked(directory);
627
1533
  claim = { disposition: "claimed", record: next };
628
1534
  });
629
1535
  return claim;
@@ -632,13 +1538,30 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
632
1538
  return null;
633
1539
  }
634
1540
  }
1541
+ function incrementLateTerminalCount(directory) {
1542
+ try {
1543
+ const artifact = readDelegationHealthArtifact(directory);
1544
+ const current = artifact?.counts.lateTerminals ?? 0;
1545
+ writeDelegationHealthArtifact(directory, {
1546
+ counts: {
1547
+ activeOwners: artifact?.counts.activeOwners ?? 0,
1548
+ pendingAdvisories: artifact?.counts.pendingAdvisories ?? 0,
1549
+ lateTerminals: current + 1,
1550
+ orphanWorktreeOwners: artifact?.counts.orphanWorktreeOwners ?? 0
1551
+ }
1552
+ });
1553
+ } catch {}
1554
+ }
635
1555
  async function claimCoderSettlement(directory, correlationId, operationId, input = {}) {
636
1556
  if (!correlationId || !operationId || operationId.length > 256)
637
1557
  return null;
638
1558
  let claim = null;
639
1559
  try {
640
1560
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
641
- const current = findByCorrelationId(directory, correlationId);
1561
+ const records = loadRecordsForWrite(directory);
1562
+ if (records === null)
1563
+ return;
1564
+ const current = findRecordForWrite(records, correlationId);
642
1565
  if (!current || current.normalizedAgent !== "coder" || current.terminalResult?.status !== "completed") {
643
1566
  return;
644
1567
  }
@@ -684,6 +1607,7 @@ async function claimCoderSettlement(directory, correlationId, operationId, input
684
1607
  if (!RecordSchema.safeParse(next).success)
685
1608
  return;
686
1609
  appendRecord(directory, next);
1610
+ maybeCompactDelegationsLocked(directory);
687
1611
  claim = {
688
1612
  disposition: existing.state === "settling" ? "resume" : "claimed",
689
1613
  record: next
@@ -699,10 +1623,10 @@ function normalizeObservedFile(value) {
699
1623
  if (typeof value !== "string")
700
1624
  return null;
701
1625
  const trimmed = value.trim().replace(/\\/g, "/");
702
- if (trimmed.length === 0 || trimmed.length > 4096 || trimmed.includes("\x00") || path.posix.isAbsolute(trimmed) || /^[A-Za-z]:\//.test(trimmed)) {
1626
+ if (trimmed.length === 0 || trimmed.length > 4096 || trimmed.includes("\x00") || path2.posix.isAbsolute(trimmed) || /^[A-Za-z]:\//.test(trimmed)) {
703
1627
  return null;
704
1628
  }
705
- const normalized = path.posix.normalize(trimmed).replace(/^\.\//, "");
1629
+ const normalized = path2.posix.normalize(trimmed).replace(/^\.\//, "");
706
1630
  if (normalized === "." || normalized === ".." || normalized.startsWith("../") || normalized.endsWith("/")) {
707
1631
  return null;
708
1632
  }
@@ -727,7 +1651,10 @@ async function updateCoderSettlement(directory, correlationId, input) {
727
1651
  let result = null;
728
1652
  try {
729
1653
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
730
- const current = findByCorrelationId(directory, correlationId);
1654
+ const records = loadRecordsForWrite(directory);
1655
+ if (records === null)
1656
+ return;
1657
+ const current = findRecordForWrite(records, correlationId);
731
1658
  const existing = current?.coderSettlement;
732
1659
  if (!current || !existing)
733
1660
  return;
@@ -788,6 +1715,7 @@ async function updateCoderSettlement(directory, correlationId, input) {
788
1715
  if (!RecordSchema.safeParse(next).success)
789
1716
  return;
790
1717
  appendRecord(directory, next);
1718
+ maybeCompactDelegationsLocked(directory);
791
1719
  result = next;
792
1720
  });
793
1721
  return result;
@@ -804,7 +1732,10 @@ async function claimDelegationIngestion(directory, correlationId, options) {
804
1732
  let claim = null;
805
1733
  try {
806
1734
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
807
- const current = findByCorrelationId(directory, correlationId);
1735
+ const records = loadRecordsForWrite(directory);
1736
+ if (records === null)
1737
+ return;
1738
+ const current = findRecordForWrite(records, correlationId);
808
1739
  if (!current?.terminalResult)
809
1740
  return;
810
1741
  if (current.status === "consumed") {
@@ -843,6 +1774,7 @@ async function claimDelegationIngestion(directory, correlationId, options) {
843
1774
  updatedAt: now
844
1775
  };
845
1776
  appendRecord(directory, next);
1777
+ maybeCompactDelegationsLocked(directory);
846
1778
  claim = { disposition, record: next };
847
1779
  });
848
1780
  return claim;
@@ -857,7 +1789,10 @@ async function recordDelegationIngestionResult(directory, correlationId, claimTo
857
1789
  let result = null;
858
1790
  try {
859
1791
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
860
- const current = findByCorrelationId(directory, correlationId);
1792
+ const records = loadRecordsForWrite(directory);
1793
+ if (records === null)
1794
+ return;
1795
+ const current = findRecordForWrite(records, correlationId);
861
1796
  if (!current)
862
1797
  return;
863
1798
  if (success && current.status === "consumed" && current.ingestion?.state === "consumed" && current.ingestion.claimToken === claimToken || !success && current.status === "ingestion_error" && current.ingestion?.state === "retryable" && current.ingestion.claimToken === claimToken) {
@@ -880,6 +1815,7 @@ async function recordDelegationIngestionResult(directory, correlationId, claimTo
880
1815
  updatedAt
881
1816
  };
882
1817
  appendRecord(directory, next);
1818
+ maybeCompactDelegationsLocked(directory);
883
1819
  result = next;
884
1820
  });
885
1821
  return result;
@@ -902,7 +1838,10 @@ async function putPendingBackgroundAdvisory(directory, correlationId, input) {
902
1838
  let result = null;
903
1839
  try {
904
1840
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
905
- const current = findByCorrelationId(directory, correlationId);
1841
+ const records = loadRecordsForWrite(directory);
1842
+ if (records === null)
1843
+ return;
1844
+ const current = findRecordForWrite(records, correlationId);
906
1845
  if (!current?.terminalResult || current.terminalResult.eventId !== parsed.data.eventId || current.parentSessionId !== parsed.data.parentSessionId) {
907
1846
  return;
908
1847
  }
@@ -919,6 +1858,7 @@ async function putPendingBackgroundAdvisory(directory, correlationId, input) {
919
1858
  updatedAt: createdAt
920
1859
  };
921
1860
  appendRecord(directory, next);
1861
+ maybeCompactDelegationsLocked(directory);
922
1862
  result = parsed.data;
923
1863
  });
924
1864
  return result;
@@ -935,7 +1875,10 @@ async function preparePendingBackgroundAdvisories(directory, parentSessionId, op
935
1875
  const prepared = [];
936
1876
  try {
937
1877
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
938
- for (const current of readDelegations(directory)) {
1878
+ const records = loadRecordsForWrite(directory);
1879
+ if (records === null)
1880
+ return;
1881
+ for (const current of records) {
939
1882
  if (prepared.length >= 1)
940
1883
  break;
941
1884
  const advisory = current.advisoryInbox;
@@ -960,6 +1903,7 @@ async function preparePendingBackgroundAdvisories(directory, parentSessionId, op
960
1903
  updatedAt: now
961
1904
  };
962
1905
  appendRecord(directory, next);
1906
+ maybeCompactDelegationsLocked(directory);
963
1907
  prepared.push(nextAdvisory);
964
1908
  }
965
1909
  });
@@ -976,8 +1920,11 @@ async function releaseBackgroundAdvisoryPreparation(directory, parentSessionId,
976
1920
  }
977
1921
  try {
978
1922
  return await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
1923
+ const records = loadRecordsForWrite(directory);
1924
+ if (records === null)
1925
+ return false;
979
1926
  const byEvent = new Map;
980
- for (const current of readDelegations(directory)) {
1927
+ for (const current of records) {
981
1928
  const advisory = current.advisoryInbox;
982
1929
  if (advisory?.parentSessionId === parentSessionId && uniqueEventIds.includes(advisory.eventId)) {
983
1930
  byEvent.set(advisory.eventId, current);
@@ -1005,6 +1952,7 @@ async function releaseBackgroundAdvisoryPreparation(directory, parentSessionId,
1005
1952
  };
1006
1953
  appendRecord(directory, next);
1007
1954
  }
1955
+ maybeCompactDelegationsLocked(directory);
1008
1956
  return true;
1009
1957
  });
1010
1958
  } catch (err) {
@@ -1018,8 +1966,11 @@ async function acknowledgeObservedBackgroundAdvisories(directory, parentSessionI
1018
1966
  let acknowledged = 0;
1019
1967
  try {
1020
1968
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
1969
+ const records = loadRecordsForWrite(directory);
1970
+ if (records === null)
1971
+ return;
1021
1972
  const now = Date.now();
1022
- for (const current of readDelegations(directory)) {
1973
+ for (const current of records) {
1023
1974
  const advisory = current.advisoryInbox;
1024
1975
  if (!advisory || advisory.parentSessionId !== parentSessionId || advisory.state !== "pending" || !observedTexts.some((text) => {
1025
1976
  const advisoryBlock = text.match(/\[ADVISORIES\]([\s\S]*?)\[\/ADVISORIES\]/);
@@ -1046,6 +1997,8 @@ async function acknowledgeObservedBackgroundAdvisories(directory, parentSessionI
1046
1997
  appendRecord(directory, next);
1047
1998
  acknowledged += 1;
1048
1999
  }
2000
+ if (acknowledged > 0)
2001
+ maybeCompactDelegationsLocked(directory);
1049
2002
  });
1050
2003
  return acknowledged;
1051
2004
  } catch (err) {
@@ -1069,7 +2022,10 @@ function isTerminal(status) {
1069
2022
  }
1070
2023
  function sweepStaleLocked(directory, timeoutMs, now, statuses = DEFAULT_SWEEPABLE_DELEGATION_STATUSES) {
1071
2024
  let swept = 0;
1072
- for (const record of readDelegations(directory)) {
2025
+ const records = loadRecordsForWrite(directory);
2026
+ if (records === null)
2027
+ return 0;
2028
+ for (const record of records) {
1073
2029
  if (!statuses.has(record.status))
1074
2030
  continue;
1075
2031
  if (now - record.updatedAt <= timeoutMs)
@@ -1081,6 +2037,8 @@ function sweepStaleLocked(directory, timeoutMs, now, statuses = DEFAULT_SWEEPABL
1081
2037
  });
1082
2038
  swept += 1;
1083
2039
  }
2040
+ if (swept > 0)
2041
+ maybeCompactDelegationsLocked(directory);
1084
2042
  return swept;
1085
2043
  }
1086
2044
  async function sweepStaleDelegations(directory, timeoutMs, options = {}) {
@@ -1096,18 +2054,18 @@ async function sweepStaleDelegations(directory, timeoutMs, options = {}) {
1096
2054
  }
1097
2055
  function fallbackRelativePath(correlationId) {
1098
2056
  const digest = createHash("sha256").update(correlationId).digest("hex");
1099
- return path.join(BACKGROUND_DELEGATION_FALLBACK_DIR, `${digest}.json`);
2057
+ return path2.join(BACKGROUND_DELEGATION_FALLBACK_DIR, `${digest}.json`);
1100
2058
  }
1101
2059
  function fallbackPath(directory, correlationId) {
1102
2060
  return validateSwarmPath(directory, fallbackRelativePath(correlationId));
1103
2061
  }
1104
2062
  function fallbackDirectoryPath(directory) {
1105
- return path.dirname(validateSwarmPath(directory, path.join(BACKGROUND_DELEGATION_FALLBACK_DIR, ".containment-anchor")));
2063
+ return path2.dirname(validateSwarmPath(directory, path2.join(BACKGROUND_DELEGATION_FALLBACK_DIR, ".containment-anchor")));
1106
2064
  }
1107
2065
  async function readFallbackFile(directory, correlationId) {
1108
2066
  for (let attempt = 0;attempt < 5; attempt++) {
1109
2067
  try {
1110
- const raw = await fs.promises.readFile(fallbackPath(directory, correlationId), "utf-8");
2068
+ const raw = await fs2.promises.readFile(fallbackPath(directory, correlationId), "utf-8");
1111
2069
  const parsedJson = JSON.parse(raw);
1112
2070
  const parsed = FallbackArtifactSchema.safeParse(parsedJson);
1113
2071
  if (!parsed.success || parsed.data.correlationId !== correlationId) {
@@ -1117,7 +2075,7 @@ async function readFallbackFile(directory, correlationId) {
1117
2075
  } catch (err) {
1118
2076
  const code = err.code;
1119
2077
  if (code === "ENOENT" && attempt < 4) {
1120
- await new Promise((resolve2) => setTimeout(resolve2, 10));
2078
+ await new Promise((resolve3) => setTimeout(resolve3, 10));
1121
2079
  continue;
1122
2080
  }
1123
2081
  return null;
@@ -1133,7 +2091,7 @@ async function readDelegationFallback(directory, correlationId) {
1133
2091
  async function listDelegationFallbacks(directory) {
1134
2092
  let entries;
1135
2093
  try {
1136
- entries = fs.readdirSync(fallbackDirectoryPath(directory), {
2094
+ entries = fs2.readdirSync(fallbackDirectoryPath(directory), {
1137
2095
  withFileTypes: true
1138
2096
  }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).slice(0, MAX_LIVE_BACKGROUND_FALLBACKS);
1139
2097
  } catch {
@@ -1142,7 +2100,7 @@ async function listDelegationFallbacks(directory) {
1142
2100
  const artifacts = [];
1143
2101
  for (const entry of entries) {
1144
2102
  try {
1145
- const raw = await fs.promises.readFile(path.join(fallbackDirectoryPath(directory), entry.name), "utf-8");
2103
+ const raw = await fs2.promises.readFile(path2.join(fallbackDirectoryPath(directory), entry.name), "utf-8");
1146
2104
  const parsed = FallbackArtifactSchema.safeParse(JSON.parse(raw));
1147
2105
  if (parsed.success)
1148
2106
  artifacts.push(parsed.data);
@@ -1155,7 +2113,7 @@ async function scanDelegationFallbacksForRecovery(directory) {
1155
2113
  let entries;
1156
2114
  try {
1157
2115
  fallbackDir = fallbackDirectoryPath(directory);
1158
- entries = fs.readdirSync(fallbackDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json"));
2116
+ entries = fs2.readdirSync(fallbackDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json"));
1159
2117
  } catch (error) {
1160
2118
  if (error.code === "ENOENT") {
1161
2119
  return { status: "ok", owners: [] };
@@ -1173,17 +2131,17 @@ async function scanDelegationFallbacksForRecovery(directory) {
1173
2131
  }
1174
2132
  const artifacts = [];
1175
2133
  for (const entry of entries) {
1176
- const artifactPath = path.join(fallbackDir, entry.name);
2134
+ const artifactPath = path2.join(fallbackDir, entry.name);
1177
2135
  let raw;
1178
2136
  try {
1179
- const stat = fs.statSync(artifactPath);
2137
+ const stat = fs2.statSync(artifactPath);
1180
2138
  if (stat.size > MAX_RECOVERY_FALLBACK_BYTES) {
1181
2139
  return {
1182
2140
  status: "uncertain",
1183
2141
  reason: `background fallback artifact "${entry.name}" exceeds the recovery size bound`
1184
2142
  };
1185
2143
  }
1186
- raw = await fs.promises.readFile(artifactPath, "utf-8");
2144
+ raw = await fs2.promises.readFile(artifactPath, "utf-8");
1187
2145
  } catch (error) {
1188
2146
  return {
1189
2147
  status: "uncertain",
@@ -1218,7 +2176,7 @@ async function scanDelegationFallbacksForRecovery(directory) {
1218
2176
  }
1219
2177
  function countFallbackFiles(directory) {
1220
2178
  try {
1221
- return fs.readdirSync(fallbackDirectoryPath(directory), {
2179
+ return fs2.readdirSync(fallbackDirectoryPath(directory), {
1222
2180
  withFileTypes: true
1223
2181
  }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).length;
1224
2182
  } catch (err) {
@@ -1253,7 +2211,7 @@ async function writeDelegationFallback(directory, input, options = {}) {
1253
2211
  if (countFallbackFiles(directory) >= maxLive)
1254
2212
  return null;
1255
2213
  const absPath = fallbackPath(directory, input.correlationId);
1256
- fs.mkdirSync(path.dirname(absPath), { recursive: true });
2214
+ fs2.mkdirSync(path2.dirname(absPath), { recursive: true });
1257
2215
  await bunWrite(absPath, `${JSON.stringify(parsed.data)}
1258
2216
  `);
1259
2217
  return parsed.data;
@@ -1269,7 +2227,7 @@ async function removeDelegationFallback(directory, correlationId) {
1269
2227
  try {
1270
2228
  return await withEvidenceLock(directory, BACKGROUND_DELEGATION_FALLBACK_DIR, STORE_LOCK_AGENT, FALLBACK_LOCK_TASK, async () => {
1271
2229
  try {
1272
- await fs.promises.unlink(fallbackPath(directory, correlationId));
2230
+ await fs2.promises.unlink(fallbackPath(directory, correlationId));
1273
2231
  return true;
1274
2232
  } catch (err) {
1275
2233
  return err.code === "ENOENT";
@@ -1317,7 +2275,10 @@ async function promoteDelegationFallback(directory, correlationId) {
1317
2275
  }
1318
2276
  let promoted = null;
1319
2277
  await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
1320
- const current = findByCorrelationId(directory, correlationId);
2278
+ const records = loadRecordsForWrite(directory);
2279
+ if (records === null)
2280
+ return;
2281
+ const current = findRecordForWrite(records, correlationId);
1321
2282
  if (current) {
1322
2283
  if (samePromotionIdentity(current, fallback.record)) {
1323
2284
  promoted = current;
@@ -1325,12 +2286,13 @@ async function promoteDelegationFallback(directory, correlationId) {
1325
2286
  return;
1326
2287
  }
1327
2288
  appendRecord(directory, fallback.record);
2289
+ maybeCompactDelegationsLocked(directory);
1328
2290
  promoted = fallback.record;
1329
2291
  });
1330
2292
  if (!promoted)
1331
2293
  return null;
1332
2294
  try {
1333
- await fs.promises.unlink(fallbackPath(directory, correlationId));
2295
+ await fs2.promises.unlink(fallbackPath(directory, correlationId));
1334
2296
  } catch (err) {
1335
2297
  if (err.code !== "ENOENT") {
1336
2298
  return null;
@@ -1356,14 +2318,14 @@ function scanBackgroundCoderReservationsForAdmission(directory) {
1356
2318
  let raw;
1357
2319
  try {
1358
2320
  absolutePath = reservationStorePath(directory);
1359
- const stat = fs.statSync(absolutePath);
2321
+ const stat = fs2.statSync(absolutePath);
1360
2322
  if (stat.size > MAX_BACKGROUND_CODER_RESERVATION_STORE_BYTES) {
1361
2323
  return {
1362
2324
  status: "uncertain",
1363
2325
  reason: `background coder reservation store exceeds the ${MAX_BACKGROUND_CODER_RESERVATION_STORE_BYTES}-byte safety bound`
1364
2326
  };
1365
2327
  }
1366
- raw = fs.readFileSync(absolutePath, "utf-8");
2328
+ raw = fs2.readFileSync(absolutePath, "utf-8");
1367
2329
  } catch (error) {
1368
2330
  if (error.code === "ENOENT") {
1369
2331
  return { status: "ok", reservations: [] };
@@ -1677,4 +2639,4 @@ async function releaseBackgroundCoderReservation(directory, input) {
1677
2639
  }
1678
2640
  }
1679
2641
 
1680
- export { BACKGROUND_DELEGATIONS_FILE, BACKGROUND_DELEGATION_FALLBACK_DIR, BACKGROUND_CODER_RESERVATIONS_FILE, MAX_LIVE_BACKGROUND_FALLBACKS, MAX_LIVE_BACKGROUND_CODER_RESERVATIONS, MAX_BACKGROUND_OBSERVED_FILES, MAX_BACKGROUND_ADVISORY_CHARS, BACKGROUND_INGESTION_LEASE_MS, DEFAULT_STALE_DELEGATION_TIMEOUT_MS, DEFAULT_SWEEPABLE_DELEGATION_STATUSES, readDelegations, scanDelegationsForRecovery, findByCorrelationId, recordPendingDelegationDetailed, recordPendingDelegation, buildPromptSnapshot, appendDelegationTransition, buildBackgroundCompletionEventId, claimTerminalResult, claimCoderSettlement, normalizeBackgroundObservedFiles, updateCoderSettlement, claimDelegationIngestion, recordDelegationIngestionResult, putPendingBackgroundAdvisory, preparePendingBackgroundAdvisories, acknowledgeObservedBackgroundAdvisories, releasePreparedBackgroundAdvisories, findByBatchId, findOpenAsyncLaneBatches, sweepStaleDelegations, readDelegationFallback, listDelegationFallbacks, scanDelegationFallbacksForRecovery, writeDelegationFallback, removeDelegationFallback, findDelegationForCompletion, promoteDelegationFallback, buildBackgroundCoderReservationId, scanBackgroundCoderReservationsForAdmission, reserveBackgroundCoderSlot, bindBackgroundCoderReservation, releaseBackgroundCoderReservation };
2642
+ export { MAX_RECOVERY_LEDGER_BYTES, collectDelegationLedgerHealth, BACKGROUND_DELEGATIONS_FILE, BACKGROUND_DELEGATION_FALLBACK_DIR, BACKGROUND_CODER_RESERVATIONS_FILE, BACKGROUND_DELEGATIONS_CHECKPOINT_FILE, BACKGROUND_DELEGATIONS_MANIFEST_FILE, MAX_LIVE_BACKGROUND_FALLBACKS, MAX_LIVE_BACKGROUND_CODER_RESERVATIONS, MAX_BACKGROUND_OBSERVED_FILES, MAX_BACKGROUND_ADVISORY_CHARS, DELEGATION_COMPACTION_LOW_WATER_BYTES, DELEGATION_COMPACTION_HIGH_WATER_BYTES, MAX_CHECKPOINT_BYTES, MAX_CHECKPOINT_RECORDS, TOMBSTONE_MIN_AGE_MS, BACKGROUND_INGESTION_LEASE_MS, DEFAULT_STALE_DELEGATION_TIMEOUT_MS, DEFAULT_SWEEPABLE_DELEGATION_STATUSES, _checkpointInternals, isUnsettledWorktreeOwner, compactBackgroundDelegations, readDelegations, scanDelegationsForRecovery, findByCorrelationId, recordPendingDelegationDetailed, recordPendingDelegation, buildPromptSnapshot, appendDelegationTransition, buildBackgroundCompletionEventId, claimTerminalResult, claimCoderSettlement, normalizeBackgroundObservedFiles, updateCoderSettlement, claimDelegationIngestion, recordDelegationIngestionResult, putPendingBackgroundAdvisory, preparePendingBackgroundAdvisories, acknowledgeObservedBackgroundAdvisories, releasePreparedBackgroundAdvisories, findByBatchId, findOpenAsyncLaneBatches, sweepStaleDelegations, readDelegationFallback, listDelegationFallbacks, scanDelegationFallbacksForRecovery, writeDelegationFallback, removeDelegationFallback, findDelegationForCompletion, promoteDelegationFallback, buildBackgroundCoderReservationId, scanBackgroundCoderReservationsForAdmission, reserveBackgroundCoderSlot, bindBackgroundCoderReservation, releaseBackgroundCoderReservation };