@gajae-code/coding-agent 0.12.11 → 0.12.13

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 (140) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/types/cli/marketplace-hint.d.ts +28 -0
  3. package/dist/types/cli/notify-cli.d.ts +42 -1
  4. package/dist/types/cli/update-cli.d.ts +9 -3
  5. package/dist/types/cli.d.ts +10 -0
  6. package/dist/types/commands/notify.d.ts +6 -0
  7. package/dist/types/config/file-lock-gc.d.ts +13 -1
  8. package/dist/types/config/file-lock.d.ts +3 -0
  9. package/dist/types/config/model-registry.d.ts +6 -0
  10. package/dist/types/config/models-config-schema.d.ts +99 -0
  11. package/dist/types/coordinator/contract.d.ts +1 -1
  12. package/dist/types/coordinator-mcp/question-state.d.ts +3 -1
  13. package/dist/types/extensibility/extensions/index.d.ts +1 -0
  14. package/dist/types/extensibility/extensions/ouroboros-ooo-bridge.d.ts +13 -0
  15. package/dist/types/extensibility/extensions/prefix-command-bridge.d.ts +0 -1
  16. package/dist/types/extensibility/extensions/types.d.ts +2 -0
  17. package/dist/types/gjc-runtime/deep-interview-state.d.ts +14 -0
  18. package/dist/types/gjc-runtime/gc-runtime.d.ts +11 -0
  19. package/dist/types/main.d.ts +6 -2
  20. package/dist/types/modes/acp/acp-agent.d.ts +24 -1
  21. package/dist/types/modes/components/session-selector.d.ts +1 -1
  22. package/dist/types/modes/utils/host-status.d.ts +23 -0
  23. package/dist/types/runtime-mcp/types.d.ts +2 -0
  24. package/dist/types/sdk/broker/lifecycle.d.ts +12 -0
  25. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +3 -0
  26. package/dist/types/sdk/bus/chat-daemon-command-channel.d.ts +244 -0
  27. package/dist/types/sdk/bus/chat-daemon-control.d.ts +11 -1
  28. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +7 -0
  29. package/dist/types/sdk/bus/control-plane-frames.d.ts +43 -0
  30. package/dist/types/sdk/bus/conversation-store.d.ts +18 -0
  31. package/dist/types/sdk/bus/existing-thread-readiness.d.ts +71 -0
  32. package/dist/types/sdk/bus/html-format.d.ts +10 -0
  33. package/dist/types/sdk/bus/notification-service.d.ts +10 -0
  34. package/dist/types/sdk/bus/slack-daemon.d.ts +27 -0
  35. package/dist/types/sdk/bus/slack-live-provider.d.ts +11 -0
  36. package/dist/types/sdk/bus/slack-provider.d.ts +14 -0
  37. package/dist/types/sdk/bus/slack-thread-binding.d.ts +140 -0
  38. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +2 -0
  39. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +28 -7
  40. package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -17
  41. package/dist/types/sdk/bus/telegram-reference.d.ts +20 -1
  42. package/dist/types/sdk/bus/topic-registry.d.ts +130 -85
  43. package/dist/types/sdk/host/host.d.ts +52 -0
  44. package/dist/types/sdk/lifecycle-session.d.ts +6 -0
  45. package/dist/types/sdk/session-activation.d.ts +41 -0
  46. package/dist/types/sdk/session.d.ts +18 -0
  47. package/dist/types/sdk/startup-capability.d.ts +8 -1
  48. package/dist/types/session/agent-session.d.ts +7 -2
  49. package/dist/types/session/artifacts.d.ts +2 -2
  50. package/dist/types/session/session-manager.d.ts +40 -6
  51. package/dist/types/tools/index.d.ts +15 -0
  52. package/dist/types/utils/npm-registry.d.ts +71 -0
  53. package/examples/extensions/README.md +38 -4
  54. package/examples/extensions/ooo-bridge.ts +15 -0
  55. package/package.json +8 -8
  56. package/scripts/generate-sdk-operation-inventory.ts +4 -0
  57. package/src/async/job-manager.ts +9 -2
  58. package/src/cli/fast-help.ts +1 -0
  59. package/src/cli/marketplace-hint.ts +39 -0
  60. package/src/cli/notify-cli.ts +226 -2
  61. package/src/cli/plugin-cli.ts +10 -0
  62. package/src/cli/update-cli.ts +90 -23
  63. package/src/cli.ts +23 -0
  64. package/src/commands/notify.ts +27 -3
  65. package/src/commands/sdk.ts +1 -0
  66. package/src/config/file-lock-gc.ts +65 -26
  67. package/src/config/file-lock.ts +61 -16
  68. package/src/config/model-profiles.ts +46 -30
  69. package/src/config/model-registry.ts +17 -5
  70. package/src/config/models-config-schema.ts +9 -4
  71. package/src/coordinator/contract.ts +1 -0
  72. package/src/coordinator-mcp/question-state.ts +2 -0
  73. package/src/coordinator-mcp/server.ts +358 -7
  74. package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
  75. package/src/defaults/gjc/skills/ultragoal/SKILL.md +2 -0
  76. package/src/extensibility/extensions/index.ts +1 -0
  77. package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +235 -0
  78. package/src/extensibility/extensions/prefix-command-bridge.ts +4 -9
  79. package/src/extensibility/extensions/runner.ts +15 -2
  80. package/src/extensibility/extensions/types.ts +2 -0
  81. package/src/gjc-runtime/deep-interview-recorder.ts +9 -5
  82. package/src/gjc-runtime/deep-interview-state.ts +27 -3
  83. package/src/gjc-runtime/gc-render.ts +8 -1
  84. package/src/gjc-runtime/gc-runtime.ts +15 -1
  85. package/src/gjc-runtime/launch-tmux.ts +53 -1
  86. package/src/internal-urls/docs-index.generated.ts +14 -13
  87. package/src/main.ts +214 -70
  88. package/src/modes/DESIGN.md +8 -5
  89. package/src/modes/acp/acp-agent.ts +123 -7
  90. package/src/modes/components/footer.ts +10 -18
  91. package/src/modes/components/model-selector.ts +52 -5
  92. package/src/modes/components/session-selector.ts +26 -3
  93. package/src/modes/components/status-line/gh.ts +23 -2
  94. package/src/modes/controllers/event-controller.ts +3 -0
  95. package/src/modes/controllers/extension-ui-controller.ts +2 -0
  96. package/src/modes/controllers/input-controller.ts +11 -0
  97. package/src/modes/controllers/selector-controller.ts +8 -2
  98. package/src/modes/interactive-mode.ts +7 -1
  99. package/src/modes/print-mode.ts +10 -0
  100. package/src/modes/utils/host-status.ts +38 -0
  101. package/src/prompts/system/project-prompt.md +19 -0
  102. package/src/runtime-mcp/types.ts +2 -0
  103. package/src/sdk/broker/lifecycle.ts +60 -3
  104. package/src/sdk/bus/chat-daemon-cli.ts +42 -0
  105. package/src/sdk/bus/chat-daemon-command-channel.ts +921 -0
  106. package/src/sdk/bus/chat-daemon-control.ts +16 -3
  107. package/src/sdk/bus/chat-daemon-runtime.ts +257 -21
  108. package/src/sdk/bus/control-plane-frames.ts +51 -0
  109. package/src/sdk/bus/conversation-store.ts +29 -1
  110. package/src/sdk/bus/existing-thread-readiness.ts +155 -0
  111. package/src/sdk/bus/html-format.ts +19 -3
  112. package/src/sdk/bus/index.ts +91 -12
  113. package/src/sdk/bus/notification-service.ts +28 -1
  114. package/src/sdk/bus/rich-render.ts +3 -2
  115. package/src/sdk/bus/slack-daemon.ts +99 -4
  116. package/src/sdk/bus/slack-live-provider.ts +32 -2
  117. package/src/sdk/bus/slack-provider.ts +11 -0
  118. package/src/sdk/bus/slack-thread-binding.ts +641 -0
  119. package/src/sdk/bus/telegram-daemon-cli.ts +11 -0
  120. package/src/sdk/bus/telegram-daemon-contract.ts +28 -7
  121. package/src/sdk/bus/telegram-daemon.ts +2007 -509
  122. package/src/sdk/bus/telegram-reference.ts +114 -15
  123. package/src/sdk/bus/topic-registry.ts +674 -181
  124. package/src/sdk/host/host.ts +180 -1
  125. package/src/sdk/lifecycle-session.ts +8 -2
  126. package/src/sdk/protocol/operation-inventory.generated.json +22 -0
  127. package/src/sdk/session-activation.ts +127 -0
  128. package/src/sdk/session.ts +144 -29
  129. package/src/sdk/startup-capability.ts +10 -1
  130. package/src/session/agent-session.ts +220 -13
  131. package/src/session/artifacts.ts +56 -13
  132. package/src/session/internal/managed-session-storage.ts +228 -7
  133. package/src/session/session-manager.ts +225 -60
  134. package/src/setup/provider-presets.json +3 -3
  135. package/src/task/index.ts +92 -44
  136. package/src/thinking-metadata.ts +2 -1
  137. package/src/tools/ask.ts +10 -0
  138. package/src/tools/index.ts +15 -0
  139. package/src/tools/todo-write.ts +4 -4
  140. package/src/utils/npm-registry.ts +660 -0
@@ -217,8 +217,84 @@ type ReplacementCleanupReceipt = {
217
217
  predecessor: SerializedReplacementIdentity;
218
218
  };
219
219
 
220
+ type LegacyReplacementCleanupIdentity = {
221
+ dev: bigint;
222
+ ino: bigint;
223
+ nlink: bigint;
224
+ size: bigint;
225
+ mtimeNs: bigint;
226
+ ctimeNs: bigint;
227
+ sha256: string;
228
+ };
229
+
220
230
  const U64_MAX = 18_446_744_073_709_551_615n;
221
231
 
232
+ function parseCanonicalU64(value: unknown): bigint | undefined {
233
+ if (typeof value !== "string" || !/^(0|[1-9][0-9]*)$/.test(value) || value.length > 20) return undefined;
234
+ const parsed = BigInt(value);
235
+ return parsed <= U64_MAX ? parsed : undefined;
236
+ }
237
+
238
+ function parseLegacyHexU64(value: string): bigint | undefined {
239
+ if (!/^[0-9a-f]+$/.test(value) || value.length > 16) return undefined;
240
+ const parsed = BigInt(`0x${value}`);
241
+ return parsed <= U64_MAX ? parsed : undefined;
242
+ }
243
+
244
+ function asRecord(value: unknown): Record<string, unknown> | undefined {
245
+ return value !== null && typeof value === "object" && !Array.isArray(value)
246
+ ? (value as Record<string, unknown>)
247
+ : undefined;
248
+ }
249
+
250
+ function legacyReplacementCleanupReceiptBinding(name: string): { dev: bigint; ino: bigint } | undefined {
251
+ const match = /^\.gjc-replace-cleanup-([0-9a-f]+)-([0-9a-f]+)\.json$/.exec(name);
252
+ if (!match?.[1] || !match[2]) return undefined;
253
+ const dev = parseLegacyHexU64(match[1]);
254
+ const ino = parseLegacyHexU64(match[2]);
255
+ return dev !== undefined && ino !== undefined ? { dev, ino } : undefined;
256
+ }
257
+
258
+ function parseLegacyReplacementCleanupIdentity(value: unknown): LegacyReplacementCleanupIdentity | undefined {
259
+ const identity = asRecord(value);
260
+ if (!identity) return undefined;
261
+ const dev = parseCanonicalU64(identity.dev);
262
+ const ino = parseCanonicalU64(identity.ino);
263
+ const nlink = parseCanonicalU64(identity.nlink);
264
+ const size = parseCanonicalU64(identity.size);
265
+ const mtimeNs = parseCanonicalU64(identity.mtimeNs);
266
+ const ctimeNs = parseCanonicalU64(identity.ctimeNs);
267
+ const sha256 = identity.sha256;
268
+ if (
269
+ dev === undefined ||
270
+ ino === undefined ||
271
+ nlink === undefined ||
272
+ size === undefined ||
273
+ mtimeNs === undefined ||
274
+ ctimeNs === undefined ||
275
+ typeof sha256 !== "string" ||
276
+ !/^[0-9a-f]{64}$/.test(sha256)
277
+ )
278
+ return undefined;
279
+ return { dev, ino, nlink, size, mtimeNs, ctimeNs, sha256 };
280
+ }
281
+
282
+ function parseLegacyReplacementCleanupReceipt(
283
+ bytes: Uint8Array,
284
+ ): { predecessor: string; successor: string; identity: LegacyReplacementCleanupIdentity } | undefined {
285
+ let value: unknown;
286
+ try {
287
+ value = JSON.parse(Buffer.from(bytes).toString("utf8")) as unknown;
288
+ } catch {
289
+ return undefined;
290
+ }
291
+ const receipt = asRecord(value);
292
+ if (receipt?.version !== 1 || typeof receipt.predecessor !== "string" || typeof receipt.successor !== "string")
293
+ return undefined;
294
+ const identity = parseLegacyReplacementCleanupIdentity(receipt.identity);
295
+ return identity ? { predecessor: receipt.predecessor, successor: receipt.successor, identity } : undefined;
296
+ }
297
+
222
298
  function replacementCleanupReceiptBinding(
223
299
  name: string,
224
300
  ): { predecessor: { dev: bigint; ino: bigint }; receipt: { dev: bigint; ino: bigint } } | undefined {
@@ -258,12 +334,20 @@ function replacementReceiptPath(
258
334
  }
259
335
 
260
336
  function replacementReceiptRetirementName(
261
- receipt: ManagedFileSnapshot["identity"],
262
- predecessor: ManagedFileSnapshot["identity"],
337
+ receipt: { dev: bigint; ino: bigint },
338
+ predecessor: { dev: bigint; ino: bigint },
263
339
  ): string {
264
340
  return `.gjc-receipt-remove-${receipt.dev.toString(16)}-${receipt.ino.toString(16)}-${predecessor.dev.toString(16)}-${predecessor.ino.toString(16)}`;
265
341
  }
266
342
 
343
+ function replacementReceiptPlaceholderRetirementName(
344
+ placeholder: { dev: bigint; ino: bigint },
345
+ predecessor: { dev: bigint; ino: bigint },
346
+ receipt: { dev: bigint; ino: bigint },
347
+ ): string {
348
+ return `.gjc-receipt-placeholder-remove-${placeholder.dev.toString(16)}-${placeholder.ino.toString(16)}-${predecessor.dev.toString(16)}-${predecessor.ino.toString(16)}-${receipt.dev.toString(16)}-${receipt.ino.toString(16)}`;
349
+ }
350
+
267
351
  const ACL_FAILURE_CODES = new Set(["acl_denied", "acl_io_error", "acl_present", "acl_malformed", "acl_unknown"]);
268
352
  const ACL_CLEAR_EVIDENCE = new Set(["cleared", "already_absent", "unsupported", "not_run"]);
269
353
  const GENERAL_FAILURE_CODES = new Set([
@@ -785,14 +869,68 @@ export class ManagedSessionDescendantStore {
785
869
  }
786
870
  }
787
871
 
872
+ #recoverReplacementCleanupPlaceholder(
873
+ receiptPath: string,
874
+ binding: { predecessor: { dev: bigint; ino: bigint }; receipt: { dev: bigint; ino: bigint } },
875
+ placeholder: ManagedFileSnapshot,
876
+ ): boolean {
877
+ if (placeholder.bytes.byteLength !== 0) return false;
878
+ const detachedReceiptPath = path.join(
879
+ this.#baseDir,
880
+ replacementReceiptRetirementName(binding.receipt, binding.predecessor),
881
+ );
882
+ let detachedReceipt: ManagedFileSnapshot;
883
+ try {
884
+ detachedReceipt = captureManagedFileNoFollow(detachedReceiptPath);
885
+ } catch (error) {
886
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return false;
887
+ throw error;
888
+ }
889
+ if (detachedReceipt.identity.dev !== binding.receipt.dev || detachedReceipt.identity.ino !== binding.receipt.ino)
890
+ return false;
891
+
892
+ const quarantineName = replacementReceiptPlaceholderRetirementName(
893
+ placeholder.identity,
894
+ binding.predecessor,
895
+ binding.receipt,
896
+ );
897
+ const removed = exactUnlink(receiptPath, {
898
+ dev: placeholder.identity.dev,
899
+ ino: placeholder.identity.ino,
900
+ nlink: placeholder.identity.nlink,
901
+ parentDev: this.#subtreeRoot.dev,
902
+ parentIno: this.#subtreeRoot.ino,
903
+ size: BigInt(placeholder.identity.size),
904
+ mtimeNs: placeholder.identity.mtimeNs,
905
+ sha256: placeholder.identity.sha256,
906
+ quarantineName,
907
+ });
908
+ if (
909
+ (!exactUnlinkCompleted(removed) && removed.code !== "not_found") ||
910
+ removed.retainedSuccessorPath !== undefined ||
911
+ removed.retainedUnknownPath !== undefined
912
+ )
913
+ throw new Error(`managed_replace_receipt_cleanup_pending:${removed.code ?? "unknown"}`);
914
+ fsyncDirectory(this.#baseDir);
915
+ return true;
916
+ }
917
+
788
918
  #detachReplacementCleanupReceipt(receiptPath: string): void {
789
919
  const binding = replacementCleanupReceiptBinding(path.basename(receiptPath));
790
920
  if (!binding) throw new Error("managed_replace_cleanup_receipt_invalid");
791
- const receipt = captureManagedFileNoFollow(receiptPath);
792
- if (receipt.identity.dev !== binding.receipt.dev || receipt.identity.ino !== binding.receipt.ino)
921
+ let receipt: ManagedFileSnapshot;
922
+ try {
923
+ receipt = captureManagedFileNoFollow(receiptPath);
924
+ } catch (error) {
925
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return;
926
+ throw error;
927
+ }
928
+ if (receipt.identity.dev !== binding.receipt.dev || receipt.identity.ino !== binding.receipt.ino) {
929
+ if (this.#recoverReplacementCleanupPlaceholder(receiptPath, binding, receipt)) return;
793
930
  throw new Error("managed_replace_cleanup_receipt_invalid");
931
+ }
794
932
  const predecessor = binding.predecessor;
795
- const quarantineName = `.gjc-receipt-remove-${receipt.identity.dev.toString(16)}-${receipt.identity.ino.toString(16)}-${predecessor.dev.toString(16)}-${predecessor.ino.toString(16)}`;
933
+ const quarantineName = replacementReceiptRetirementName(receipt.identity, predecessor);
796
934
  const detached = exactUnlink(receiptPath, {
797
935
  dev: receipt.identity.dev,
798
936
  ino: receipt.identity.ino,
@@ -805,6 +943,13 @@ export class ManagedSessionDescendantStore {
805
943
  detachOnly: true,
806
944
  quarantineName,
807
945
  });
946
+ if (
947
+ !detached.ok &&
948
+ detached.code === "not_found" &&
949
+ detached.retainedSuccessorPath === undefined &&
950
+ detached.retainedUnknownPath === undefined
951
+ )
952
+ return;
808
953
  if (
809
954
  (!detached.ok && detached.code !== "cleanup_pending") ||
810
955
  detached.detachedPath !== path.join(this.#baseDir, quarantineName) ||
@@ -815,14 +960,90 @@ export class ManagedSessionDescendantStore {
815
960
  fsyncDirectory(this.#baseDir);
816
961
  }
817
962
 
963
+ #reconcileLegacyReplacementCleanupReceipt(receiptPath: string, name: string): void {
964
+ const binding = legacyReplacementCleanupReceiptBinding(name);
965
+ if (!binding) throw new Error("managed_replace_cleanup_receipt_invalid");
966
+ let receipt: ManagedFileSnapshot;
967
+ try {
968
+ receipt = captureManagedFileNoFollow(receiptPath);
969
+ } catch (error) {
970
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return;
971
+ throw error;
972
+ }
973
+ const parsed = parseLegacyReplacementCleanupReceipt(receipt.bytes);
974
+ const expectedPredecessor = path.join(
975
+ this.#baseDir,
976
+ `.gjc-exact-replace-destination-${binding.dev.toString(16)}-${binding.ino.toString(16)}`,
977
+ );
978
+ if (
979
+ !parsed ||
980
+ parsed.identity.dev !== binding.dev ||
981
+ parsed.identity.ino !== binding.ino ||
982
+ path.resolve(parsed.predecessor) !== expectedPredecessor ||
983
+ path.dirname(path.resolve(parsed.successor)) !== this.#baseDir
984
+ )
985
+ throw new Error("managed_replace_cleanup_receipt_invalid");
986
+
987
+ const retired = exactUnlink(expectedPredecessor, {
988
+ dev: parsed.identity.dev,
989
+ ino: parsed.identity.ino,
990
+ nlink: parsed.identity.nlink,
991
+ parentDev: this.#subtreeRoot.dev,
992
+ parentIno: this.#subtreeRoot.ino,
993
+ size: parsed.identity.size,
994
+ mtimeNs: parsed.identity.mtimeNs,
995
+ sha256: parsed.identity.sha256,
996
+ quarantineName: `.gjc-replace-retry-${parsed.identity.dev.toString(16)}-${parsed.identity.ino.toString(16)}`,
997
+ });
998
+ if (!exactUnlinkCompleted(retired) && retired.code !== "not_found")
999
+ throw new Error(`managed_replace_cleanup_pending:${retired.code ?? "unknown"}`);
1000
+
1001
+ let currentReceipt: ManagedFileSnapshot;
1002
+ try {
1003
+ currentReceipt = captureManagedFileNoFollow(receiptPath);
1004
+ } catch (error) {
1005
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
1006
+ fsyncDirectory(this.#baseDir);
1007
+ return;
1008
+ }
1009
+ throw error;
1010
+ }
1011
+ if (
1012
+ !sameIdentity(currentReceipt.identity, receipt.identity) ||
1013
+ currentReceipt.identity.sha256 !== receipt.identity.sha256
1014
+ )
1015
+ throw new Error("managed_replace_cleanup_receipt_invalid");
1016
+ const removed = exactUnlink(receiptPath, {
1017
+ dev: currentReceipt.identity.dev,
1018
+ ino: currentReceipt.identity.ino,
1019
+ nlink: currentReceipt.identity.nlink,
1020
+ parentDev: this.#subtreeRoot.dev,
1021
+ parentIno: this.#subtreeRoot.ino,
1022
+ size: BigInt(currentReceipt.identity.size),
1023
+ mtimeNs: currentReceipt.identity.mtimeNs,
1024
+ sha256: currentReceipt.identity.sha256,
1025
+ quarantineName: `.gjc-receipt-remove-${currentReceipt.identity.dev.toString(16)}-${currentReceipt.identity.ino.toString(16)}`,
1026
+ });
1027
+ if (!exactUnlinkCompleted(removed) && removed.code !== "not_found")
1028
+ throw new Error(`managed_replace_receipt_cleanup_pending:${removed.code ?? "unknown"}`);
1029
+ fsyncDirectory(this.#baseDir);
1030
+ }
1031
+
818
1032
  #reconcileReplacementCleanupReceipts(): void {
819
1033
  if (this.#reconcilingReplacementCleanup) return;
820
1034
  this.#reconcilingReplacementCleanup = true;
821
1035
  try {
822
1036
  for (const name of fs.readdirSync(this.#baseDir)) {
823
1037
  if (!name.startsWith(".gjc-replace-cleanup-")) continue;
824
- if (!replacementCleanupReceiptBinding(name)) throw new Error("managed_replace_cleanup_receipt_invalid");
825
- this.#detachReplacementCleanupReceipt(path.join(this.#baseDir, name));
1038
+ if (replacementCleanupReceiptBinding(name)) {
1039
+ this.#detachReplacementCleanupReceipt(path.join(this.#baseDir, name));
1040
+ continue;
1041
+ }
1042
+ if (legacyReplacementCleanupReceiptBinding(name)) {
1043
+ this.#reconcileLegacyReplacementCleanupReceipt(path.join(this.#baseDir, name), name);
1044
+ continue;
1045
+ }
1046
+ throw new Error("managed_replace_cleanup_receipt_invalid");
826
1047
  }
827
1048
  } finally {
828
1049
  this.#reconcilingReplacementCleanup = false;