@astrosheep/keiyaku 4.0.0 → 4.0.2

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 (308) hide show
  1. package/README.md +133 -8
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
  4. package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
  12. package/build/src/akuma/abort.d.ts +2 -0
  13. package/build/src/akuma/abort.js +50 -0
  14. package/build/src/akuma/akuma.d.ts +50 -33
  15. package/build/src/akuma/akuma.js +175 -127
  16. package/build/src/akuma/archetype.d.ts +14 -5
  17. package/build/src/akuma/archetype.js +85 -39
  18. package/build/src/akuma/body.d.ts +3 -5
  19. package/build/src/akuma/body.js +490 -183
  20. package/build/src/akuma/coordinate.d.ts +9 -0
  21. package/build/src/akuma/coordinate.js +22 -0
  22. package/build/src/akuma/heart/facts.d.ts +88 -45
  23. package/build/src/akuma/heart/facts.js +19 -8
  24. package/build/src/akuma/heart/index.d.ts +64 -55
  25. package/build/src/akuma/heart/index.js +172 -252
  26. package/build/src/akuma/heart/rows.d.ts +38 -83
  27. package/build/src/akuma/heart/rows.js +117 -155
  28. package/build/src/akuma/heart/schema.d.ts +1 -1
  29. package/build/src/akuma/heart/schema.js +61 -22
  30. package/build/src/akuma/heart/soul.d.ts +8 -0
  31. package/build/src/akuma/heart/soul.js +136 -0
  32. package/build/src/akuma/heart/storage.d.ts +47 -0
  33. package/build/src/akuma/heart/storage.js +224 -0
  34. package/build/src/akuma/heart/tells.d.ts +12 -0
  35. package/build/src/akuma/heart/tells.js +79 -0
  36. package/build/src/akuma/heart/timeline.d.ts +15 -0
  37. package/build/src/akuma/heart/timeline.js +86 -0
  38. package/build/src/akuma/identity.d.ts +2 -2
  39. package/build/src/akuma/identity.js +9 -9
  40. package/build/src/akuma/index.d.ts +10 -3
  41. package/build/src/akuma/index.js +7 -1
  42. package/build/src/akuma/projection.d.ts +176 -0
  43. package/build/src/akuma/projection.js +256 -0
  44. package/build/src/akuma/provider-recipe.d.ts +24 -0
  45. package/build/src/akuma/provider-recipe.js +100 -0
  46. package/build/src/akuma/provider.d.ts +67 -13
  47. package/build/src/akuma/provider.js +172 -105
  48. package/build/src/akuma/providers/acp/core.d.ts +19 -0
  49. package/build/src/akuma/providers/acp/core.js +159 -0
  50. package/build/src/akuma/providers/acp/events.d.ts +20 -0
  51. package/build/src/akuma/providers/acp/events.js +73 -0
  52. package/build/src/akuma/providers/acp/index.d.ts +12 -0
  53. package/build/src/akuma/providers/acp/index.js +94 -0
  54. package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
  55. package/build/src/akuma/providers/claude/events.js +238 -0
  56. package/build/src/akuma/providers/claude/index.d.ts +47 -0
  57. package/build/src/akuma/providers/claude/index.js +279 -0
  58. package/build/src/akuma/providers/claude/input.d.ts +13 -0
  59. package/build/src/akuma/providers/claude/input.js +109 -0
  60. package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
  61. package/build/src/akuma/providers/codex-app-server/events.js +15 -12
  62. package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
  63. package/build/src/akuma/providers/codex-app-server/index.js +77 -33
  64. package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
  65. package/build/src/akuma/providers/grok-build/index.js +70 -0
  66. package/build/src/akuma/providers/index.d.ts +5 -3
  67. package/build/src/akuma/providers/index.js +35 -56
  68. package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
  69. package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
  70. package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
  71. package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
  72. package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
  73. package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
  74. package/build/src/akuma/providers/pi/events.d.ts +33 -0
  75. package/build/src/akuma/providers/pi/events.js +166 -0
  76. package/build/src/akuma/providers/pi/index.d.ts +11 -0
  77. package/build/src/akuma/providers/pi/index.js +191 -0
  78. package/build/src/akuma/publication.d.ts +3 -3
  79. package/build/src/akuma/publication.js +28 -40
  80. package/build/src/akuma/requests.d.ts +9 -6
  81. package/build/src/akuma/requests.js +95 -65
  82. package/build/src/alias/index.d.ts +4 -3
  83. package/build/src/alias/index.js +12 -13
  84. package/build/src/body/decode.js +7 -1
  85. package/build/src/body/region.d.ts +2 -0
  86. package/build/src/body/region.js +77 -7
  87. package/build/src/body/render.js +2 -1
  88. package/build/src/body/shape.js +7 -1
  89. package/build/src/body/verification.js +19 -4
  90. package/build/src/cli/accepted.d.ts +18 -12
  91. package/build/src/cli/accepted.js +73 -34
  92. package/build/src/cli/actor.js +3 -3
  93. package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
  94. package/build/src/cli/commands/akuma-invoke.js +101 -52
  95. package/build/src/cli/commands/akuma.d.ts +27 -9
  96. package/build/src/cli/commands/akuma.js +151 -80
  97. package/build/src/cli/commands/contract.d.ts +155 -0
  98. package/build/src/cli/commands/contract.js +20 -0
  99. package/build/src/cli/commands/install.js +2 -0
  100. package/build/src/cli/commands/task-invoke.d.ts +19 -4
  101. package/build/src/cli/commands/task-invoke.js +65 -17
  102. package/build/src/cli/commands/task-query.d.ts +5 -0
  103. package/build/src/cli/commands/task-query.js +247 -0
  104. package/build/src/cli/commands/task.d.ts +3 -1
  105. package/build/src/cli/commands/task.js +52 -14
  106. package/build/src/cli/coordinates.d.ts +18 -0
  107. package/build/src/cli/coordinates.js +120 -0
  108. package/build/src/cli/draft.d.ts +8 -0
  109. package/build/src/cli/draft.js +96 -0
  110. package/build/src/cli/invoke.d.ts +9 -3
  111. package/build/src/cli/invoke.js +287 -108
  112. package/build/src/cli/main.js +54 -7
  113. package/build/src/cli/parse.d.ts +21 -117
  114. package/build/src/cli/parse.js +79 -84
  115. package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
  116. package/build/src/cli/render/akuma-tool-command.js +144 -0
  117. package/build/src/cli/render/akuma-tool.d.ts +4 -2
  118. package/build/src/cli/render/akuma-tool.js +35 -5
  119. package/build/src/cli/render/akuma.d.ts +3 -1
  120. package/build/src/cli/render/akuma.js +247 -212
  121. package/build/src/cli/render/audit.d.ts +3 -0
  122. package/build/src/cli/render/audit.js +104 -0
  123. package/build/src/cli/render/catalog.d.ts +2 -0
  124. package/build/src/cli/render/catalog.js +16 -0
  125. package/build/src/cli/render/contract.d.ts +3 -3
  126. package/build/src/cli/render/contract.js +200 -54
  127. package/build/src/cli/render/kanshi.js +272 -129
  128. package/build/src/cli/render/receipt.d.ts +19 -0
  129. package/build/src/cli/render/receipt.js +106 -0
  130. package/build/src/cli/render/refusal.d.ts +16 -2
  131. package/build/src/cli/render/refusal.js +88 -3
  132. package/build/src/cli/render/region.d.ts +2 -0
  133. package/build/src/cli/render/region.js +17 -0
  134. package/build/src/cli/render/task.d.ts +2 -1
  135. package/build/src/cli/render/task.js +223 -60
  136. package/build/src/cli/render/terminal.d.ts +20 -0
  137. package/build/src/cli/render/terminal.js +121 -0
  138. package/build/src/cli/render/text.js +11 -3
  139. package/build/src/cli/result.d.ts +126 -19
  140. package/build/src/cli/usage.d.ts +1 -0
  141. package/build/src/cli/usage.js +3 -0
  142. package/build/src/contract-worktree.d.ts +44 -0
  143. package/build/src/contract-worktree.js +251 -0
  144. package/build/src/coordination/durable-file.d.ts +5 -1
  145. package/build/src/coordination/durable-file.js +57 -10
  146. package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
  147. package/build/src/coordination/sqlite-transaction-lock.js +22 -5
  148. package/build/src/core/facts/codec.js +23 -4
  149. package/build/src/core/facts/eligibility.d.ts +1 -10
  150. package/build/src/core/facts/eligibility.js +0 -49
  151. package/build/src/core/facts/fold.js +1 -6
  152. package/build/src/core/facts/gate.d.ts +1 -0
  153. package/build/src/core/facts/gate.js +1 -0
  154. package/build/src/core/facts/observation.d.ts +3 -0
  155. package/build/src/core/facts/observation.js +12 -0
  156. package/build/src/core/facts/types.d.ts +10 -3
  157. package/build/src/core/subject.js +2 -2
  158. package/build/src/core/verbs/amend.d.ts +1 -1
  159. package/build/src/core/verbs/amend.js +3 -18
  160. package/build/src/core/verbs/bind.js +2 -16
  161. package/build/src/core/verbs/deliver.d.ts +1 -1
  162. package/build/src/core/verbs/deliver.js +14 -4
  163. package/build/src/core/verbs/placement.d.ts +1 -1
  164. package/build/src/core/verbs/placement.js +7 -9
  165. package/build/src/dispatch/index.d.ts +5 -3
  166. package/build/src/dispatch/index.js +30 -21
  167. package/build/src/duration.d.ts +10 -0
  168. package/build/src/duration.js +22 -0
  169. package/build/src/git/admission.d.ts +2 -2
  170. package/build/src/git/admission.js +33 -23
  171. package/build/src/git/hooks.d.ts +15 -0
  172. package/build/src/git/hooks.js +70 -18
  173. package/build/src/git/identity.d.ts +5 -1
  174. package/build/src/git/identity.js +23 -4
  175. package/build/src/git/integration.d.ts +48 -0
  176. package/build/src/git/integration.js +250 -0
  177. package/build/src/git/observe.d.ts +29 -15
  178. package/build/src/git/observe.js +185 -76
  179. package/build/src/git/read-observation.d.ts +41 -0
  180. package/build/src/git/read-observation.js +361 -0
  181. package/build/src/git/reconcile.d.ts +17 -5
  182. package/build/src/git/reconcile.js +305 -109
  183. package/build/src/git/repository.d.ts +41 -18
  184. package/build/src/git/repository.js +220 -114
  185. package/build/src/git/scratch.d.ts +17 -0
  186. package/build/src/git/scratch.js +73 -0
  187. package/build/src/git/target-placement.d.ts +92 -0
  188. package/build/src/git/target-placement.js +375 -0
  189. package/build/src/git/tender.d.ts +49 -0
  190. package/build/src/git/tender.js +63 -0
  191. package/build/src/git/terminal-seal.d.ts +24 -0
  192. package/build/src/git/terminal-seal.js +89 -0
  193. package/build/src/git/tree.d.ts +2 -2
  194. package/build/src/git/tree.js +4 -0
  195. package/build/src/git/workspace.d.ts +53 -0
  196. package/build/src/git/workspace.js +139 -0
  197. package/build/src/identity/selector.d.ts +6 -0
  198. package/build/src/identity/selector.js +19 -0
  199. package/build/src/index.d.ts +4 -2
  200. package/build/src/index.js +2 -1
  201. package/build/src/kanshi/index.d.ts +2 -2
  202. package/build/src/kanshi/index.js +1 -1
  203. package/build/src/kanshi/read.d.ts +7 -3
  204. package/build/src/kanshi/read.js +245 -45
  205. package/build/src/kanshi/report.d.ts +81 -6
  206. package/build/src/kanshi/select.d.ts +5 -0
  207. package/build/src/kanshi/select.js +33 -1
  208. package/build/src/library/address.d.ts +57 -0
  209. package/build/src/library/address.js +165 -0
  210. package/build/src/library/akuma-creation.d.ts +16 -7
  211. package/build/src/library/akuma-creation.js +96 -22
  212. package/build/src/library/audit.d.ts +18 -0
  213. package/build/src/library/audit.js +44 -0
  214. package/build/src/library/bind.d.ts +21 -0
  215. package/build/src/library/bind.js +56 -0
  216. package/build/src/library/catalog.d.ts +58 -0
  217. package/build/src/library/catalog.js +69 -0
  218. package/build/src/library/configuration.d.ts +6 -15
  219. package/build/src/library/configuration.js +14 -17
  220. package/build/src/library/contract.d.ts +23 -49
  221. package/build/src/library/contract.js +171 -185
  222. package/build/src/library/delivery.d.ts +24 -0
  223. package/build/src/library/delivery.js +21 -0
  224. package/build/src/library/fleet.d.ts +65 -0
  225. package/build/src/library/fleet.js +153 -0
  226. package/build/src/library/input.d.ts +3 -0
  227. package/build/src/library/input.js +19 -0
  228. package/build/src/library/keiyaku.d.ts +18 -3
  229. package/build/src/library/keiyaku.js +12 -1
  230. package/build/src/library/mutation.d.ts +39 -0
  231. package/build/src/library/mutation.js +37 -0
  232. package/build/src/library/reconcile.d.ts +29 -0
  233. package/build/src/library/reconcile.js +179 -0
  234. package/build/src/library/refusal.d.ts +21 -0
  235. package/build/src/library/refusal.js +29 -0
  236. package/build/src/library/region.d.ts +14 -1
  237. package/build/src/library/region.js +18 -4
  238. package/build/src/library/repo.d.ts +4 -13
  239. package/build/src/library/repo.js +14 -24
  240. package/build/src/protocol/attempt.d.ts +16 -3
  241. package/build/src/protocol/attempt.js +41 -10
  242. package/build/src/protocol/bind.d.ts +9 -2
  243. package/build/src/protocol/bind.js +48 -40
  244. package/build/src/protocol/intent.d.ts +57 -20
  245. package/build/src/protocol/intent.js +55 -79
  246. package/build/src/protocol/operations.d.ts +152 -43
  247. package/build/src/protocol/operations.js +482 -166
  248. package/build/src/protocol/outcome.d.ts +14 -3
  249. package/build/src/protocol/outcome.js +11 -3
  250. package/build/src/protocol/placement.d.ts +41 -0
  251. package/build/src/protocol/placement.js +147 -0
  252. package/build/src/protocol/read/documents.d.ts +2 -2
  253. package/build/src/protocol/read/documents.js +4 -4
  254. package/build/src/protocol/read/status.d.ts +18 -5
  255. package/build/src/protocol/read/status.js +73 -13
  256. package/build/src/protocol/run.d.ts +49 -7
  257. package/build/src/protocol/run.js +53 -25
  258. package/build/src/runtime/proc/line-rpc.d.ts +4 -8
  259. package/build/src/runtime/proc/line-rpc.js +22 -28
  260. package/build/src/runtime/proc/run.d.ts +23 -21
  261. package/build/src/runtime/proc/run.js +123 -89
  262. package/build/src/runtime/proc/stdio.d.ts +18 -0
  263. package/build/src/runtime/proc/stdio.js +58 -0
  264. package/build/src/settings.d.ts +7 -1
  265. package/build/src/settings.js +32 -17
  266. package/build/src/settlement/fence.d.ts +5 -0
  267. package/build/src/settlement/fence.js +14 -0
  268. package/build/src/settlement/holder.d.ts +35 -4
  269. package/build/src/settlement/holder.js +127 -28
  270. package/build/src/settlement/settle.d.ts +9 -1
  271. package/build/src/settlement/settle.js +74 -37
  272. package/build/src/task/board.d.ts +23 -5
  273. package/build/src/task/board.js +17 -10
  274. package/build/src/task/compose.d.ts +2 -2
  275. package/build/src/task/compose.js +18 -10
  276. package/build/src/task/context.d.ts +3 -3
  277. package/build/src/task/context.js +15 -20
  278. package/build/src/task/document.d.ts +2 -1
  279. package/build/src/task/document.js +15 -5
  280. package/build/src/task/index.d.ts +27 -15
  281. package/build/src/task/index.js +57 -35
  282. package/build/src/task/operations.d.ts +38 -13
  283. package/build/src/task/operations.js +80 -46
  284. package/build/src/task/query.d.ts +67 -0
  285. package/build/src/task/query.js +279 -0
  286. package/build/src/task/store.d.ts +5 -7
  287. package/build/src/task/store.js +43 -28
  288. package/build/src/verification/declaration.d.ts +1 -0
  289. package/build/src/verification/execution.d.ts +51 -0
  290. package/build/src/verification/execution.js +108 -0
  291. package/build/src/workspace-place.d.ts +41 -0
  292. package/build/src/workspace-place.js +386 -0
  293. package/build/src/world.d.ts +24 -0
  294. package/build/src/world.js +136 -0
  295. package/package.json +8 -4
  296. package/build/src/akuma/activity.d.ts +0 -66
  297. package/build/src/akuma/activity.js +0 -139
  298. package/build/src/akuma/providers/claude.js +0 -305
  299. package/build/src/context-root.d.ts +0 -4
  300. package/build/src/context-root.js +0 -15
  301. package/build/src/git/delivery.d.ts +0 -20
  302. package/build/src/git/delivery.js +0 -109
  303. package/build/src/git/verification.d.ts +0 -14
  304. package/build/src/git/verification.js +0 -56
  305. package/build/src/protocol/read/audit.d.ts +0 -25
  306. package/build/src/protocol/read/audit.js +0 -39
  307. package/build/src/verification/producer.d.ts +0 -23
  308. package/build/src/verification/producer.js +0 -54
@@ -1,139 +0,0 @@
1
- import { decodeAgentEvent } from "./provider.js";
2
- const SETTLED_LIMIT = 8;
3
- const INTENT_LIMIT = 2;
4
- function duration(startedAt, completedAt) {
5
- const start = Date.parse(startedAt);
6
- const end = Date.parse(completedAt);
7
- if (!Number.isFinite(start) || !Number.isFinite(end) || end < start)
8
- return undefined;
9
- return end - start;
10
- }
11
- function toolKey(bodySequence, id) {
12
- return `${bodySequence}:${id}`;
13
- }
14
- function narrationRow(fact, event) {
15
- if (event.type === "assistant") {
16
- return { kind: "said", sequence: fact.sequence, bodySequence: fact.bodySequence, at: fact.at, text: event.text };
17
- }
18
- if (event.type === "thought" || event.type === "note") {
19
- return { kind: event.type, sequence: fact.sequence, bodySequence: fact.bodySequence, at: fact.at, text: event.text };
20
- }
21
- return null;
22
- }
23
- /** Fold the complete retained typed event window before any display budget. */
24
- export function foldActivity(facts) {
25
- const rows = [];
26
- const running = new Map();
27
- for (const fact of facts) {
28
- const event = decodeAgentEvent(fact.event);
29
- const narration = narrationRow(fact, event);
30
- if (narration !== null) {
31
- rows.push({ settled: true, row: narration });
32
- continue;
33
- }
34
- if (event.type !== "tool")
35
- continue;
36
- const key = toolKey(fact.bodySequence, event.id);
37
- if (event.phase === "started") {
38
- const index = rows.length;
39
- rows.push({
40
- settled: false,
41
- row: {
42
- kind: "tool",
43
- sequence: fact.sequence,
44
- bodySequence: fact.bodySequence,
45
- at: fact.at,
46
- name: event.name,
47
- call: event.call,
48
- state: "running",
49
- },
50
- });
51
- running.set(key, index);
52
- continue;
53
- }
54
- const index = running.get(key);
55
- if (index === undefined) {
56
- rows.push({
57
- settled: true,
58
- row: {
59
- kind: "tool",
60
- sequence: fact.sequence,
61
- bodySequence: fact.bodySequence,
62
- at: fact.at,
63
- name: event.name,
64
- call: event.call,
65
- state: event.result,
66
- },
67
- });
68
- continue;
69
- }
70
- const started = rows[index].row;
71
- if (started.kind !== "tool")
72
- throw new Error("Akuma activity tool fold lost its start row");
73
- const elapsed = duration(started.at, fact.at);
74
- rows[index] = {
75
- settled: true,
76
- row: {
77
- kind: "tool",
78
- sequence: started.sequence,
79
- bodySequence: started.bodySequence,
80
- at: started.at,
81
- completedAt: fact.at,
82
- ...(elapsed === undefined ? {} : { durationMs: elapsed }),
83
- name: event.name,
84
- call: event.call,
85
- state: event.result,
86
- },
87
- };
88
- running.delete(key);
89
- }
90
- return rows.map((entry) => entry.row);
91
- }
92
- function pendingTellFacts(tells) {
93
- return tells
94
- .filter((tell) => tell.state !== "consumed" && tell.state !== "voided-by-death")
95
- .map((tell) => ({ id: tell.id, body: tell.body, recordedAt: tell.recordedAt }));
96
- }
97
- /** Apply the one bounded recent selection after folding semantic rows. */
98
- export function selectActivitySnapshot(facts, input = {}) {
99
- const folded = foldActivity(facts);
100
- const settled = folded.filter((row) => row.kind !== "tool" || row.state !== "running");
101
- const selected = new Set(settled.slice(-SETTLED_LIMIT));
102
- const intent = settled.filter((row) => row.kind === "said" || row.kind === "thought").slice(-INTENT_LIMIT);
103
- for (const row of intent)
104
- selected.add(row);
105
- for (const row of folded) {
106
- if (row.kind === "tool" && row.state === "running")
107
- selected.add(row);
108
- }
109
- return {
110
- rows: folded.filter((row) => selected.has(row)),
111
- pendingTells: pendingTellFacts(input.pending ?? []),
112
- omitted: settled.length - [...selected].filter((row) => row.kind !== "tool" || row.state !== "running").length,
113
- lowestRetained: input.lowestRetained ?? (facts[0]?.sequence ?? null),
114
- highest: input.highest ?? (facts.at(-1)?.sequence ?? null),
115
- };
116
- }
117
- function visibleRows(facts, since, limit) {
118
- const folded = foldActivity(facts);
119
- return since ? folded.slice(0, limit) : folded.slice(-limit);
120
- }
121
- /** Project a cursor page; history never applies the recent snapshot pinning rules. */
122
- export function projectActivityHistory(slice, turns, input) {
123
- const all = foldActivity(slice.rows);
124
- const rows = visibleRows(slice.rows, input.since === true, input.limit);
125
- const bodySequences = new Set(rows.map((row) => row.bodySequence));
126
- return {
127
- rows,
128
- turns: turns.filter((turn) => bodySequences.has(turn.bodySequence)),
129
- omitted: Math.max(0, all.length - rows.length),
130
- hasEarlier: input.since !== true && all.length > rows.length,
131
- hasLater: input.since === true && all.length > rows.length,
132
- historyLost: input.since !== true
133
- && all.length === rows.length
134
- && slice.lowestRetained !== null
135
- && slice.lowestRetained > 1,
136
- lowestRetained: slice.lowestRetained,
137
- highest: slice.highest,
138
- };
139
- }
@@ -1,305 +0,0 @@
1
- import { AgentEventChannel, boundedEventText, boundedThoughtText, noteEvent, unknownEvent, } from "../provider.js";
2
- export const CLAUDE_MESSAGE_DISPOSITIONS = {
3
- assistant: "assistant",
4
- auth_status: "auth",
5
- conversation_reset: "note",
6
- prompt_suggestion: "drop",
7
- rate_limit_event: "drop",
8
- result: "terminal",
9
- stream_event: "drop",
10
- system: "system",
11
- tool_progress: "drop",
12
- tool_use_summary: "drop",
13
- user: "tool-results",
14
- };
15
- export const CLAUDE_SYSTEM_DISPOSITIONS = {
16
- api_retry: "note",
17
- background_tasks_changed: "note",
18
- commands_changed: "drop",
19
- compact_boundary: "drop",
20
- control_request_progress: "control-progress",
21
- elicitation_complete: "drop",
22
- files_persisted: "note",
23
- hook_progress: "drop",
24
- hook_response: "drop",
25
- hook_started: "note",
26
- informational: "note",
27
- init: "drop",
28
- local_command_output: "drop",
29
- memory_recall: "drop",
30
- mirror_error: "note",
31
- model_refusal_fallback: "note",
32
- model_refusal_no_fallback: "note",
33
- notification: "note",
34
- permission_denied: "note",
35
- plugin_install: "note",
36
- session_state_changed: "drop",
37
- status: "note",
38
- task_notification: "note",
39
- task_progress: "note",
40
- task_started: "note",
41
- task_updated: "note",
42
- thinking_tokens: "drop",
43
- worker_shutting_down: "note",
44
- };
45
- function assistantText(message) {
46
- if (message.type !== "assistant" || message.aborted === true || message.error !== undefined)
47
- return null;
48
- const text = message.message.content
49
- .filter((block) => block.type === "text")
50
- .map((block) => block.text)
51
- .join("");
52
- return text.length === 0 ? null : text;
53
- }
54
- function object(value) {
55
- return value !== null && typeof value === "object" && !Array.isArray(value)
56
- ? value
57
- : undefined;
58
- }
59
- function nonblank(value) {
60
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
61
- }
62
- function number(value) {
63
- return typeof value === "number" && Number.isFinite(value) ? value : undefined;
64
- }
65
- const CLAUDE_SYSTEM_NOTES = {
66
- api_retry: (message) => {
67
- const attempt = number(message.attempt);
68
- const maximum = number(message.max_retries);
69
- return attempt === undefined || maximum === undefined
70
- ? "Retrying request"
71
- : `Retrying request ${attempt}/${maximum}`;
72
- },
73
- background_tasks_changed: (message) => `Background tasks: ${Array.isArray(message.tasks) ? message.tasks.length : 0}`,
74
- files_persisted: (message) => {
75
- const files = Array.isArray(message.files) ? message.files.length : 0;
76
- const failed = Array.isArray(message.failed) ? message.failed.length : 0;
77
- return failed === 0 ? `Persisted ${files} files` : `Persisted ${files} files; ${failed} failed`;
78
- },
79
- hook_started: (message) => `Hook ${nonblank(message.hook_name) ?? "unknown"} started`,
80
- informational: (message) => nonblank(message.content) ?? "Informational notice",
81
- mirror_error: (message) => `Transcript mirror warning: ${nonblank(message.error) ?? nonblank(message.message) ?? "unknown error"}`,
82
- model_refusal_fallback: () => "Model refusal; using fallback",
83
- model_refusal_no_fallback: () => "Model refusal; no fallback available",
84
- notification: (message) => nonblank(message.message) ?? nonblank(message.content) ?? "Notification",
85
- permission_denied: (message) => `Permission refused${nonblank(message.message) === undefined ? "" : `: ${nonblank(message.message)}`}`,
86
- plugin_install: (message) => `Plugin install ${nonblank(message.status) ?? "updated"}${nonblank(message.name) === undefined ? "" : `: ${nonblank(message.name)}`}`,
87
- status: (message) => `Status: ${nonblank(message.status) ?? "idle"}${nonblank(message.error) === undefined ? "" : ` (${nonblank(message.error)})`}`,
88
- task_notification: (message) => `Task ${nonblank(message.task_id) ?? "unknown"} ${nonblank(message.status) ?? "updated"}`,
89
- task_progress: (message) => nonblank(message.description) ?? `Task ${nonblank(message.task_id) ?? "unknown"} progressed`,
90
- task_started: (message) => nonblank(message.description) ?? `Task ${nonblank(message.task_id) ?? "unknown"} started`,
91
- task_updated: (message) => `Task ${nonblank(message.task_id) ?? "unknown"} updated`,
92
- worker_shutting_down: (message) => `Worker stopping: ${nonblank(message.reason) ?? "unknown reason"}`,
93
- };
94
- function toolCall(name, input) {
95
- const value = object(input) ?? {};
96
- const command = nonblank(value.command);
97
- if (command !== undefined)
98
- return { kind: "run", command: boundedEventText(command) };
99
- const path = nonblank(value.file_path) ?? nonblank(value.path);
100
- if (/^(?:read|view)/iu.test(name) && path !== undefined)
101
- return { kind: "read", path: boundedEventText(path) };
102
- const query = nonblank(value.query) ?? nonblank(value.pattern);
103
- if (/search|grep|glob/iu.test(name) && query !== undefined)
104
- return { kind: "search", query: boundedEventText(query) };
105
- if (/write/iu.test(name) && path !== undefined) {
106
- return { kind: "fileChange", changes: [{ op: "add", path: boundedEventText(path) }] };
107
- }
108
- if (/edit|notebook/iu.test(name) && path !== undefined) {
109
- return { kind: "fileChange", changes: [{ op: "update", path: boundedEventText(path) }] };
110
- }
111
- return { kind: "other", display: boundedEventText(name) };
112
- }
113
- function assistantEvents(message, events, state) {
114
- if (message.aborted === true)
115
- return;
116
- if (message.error !== undefined) {
117
- events.emit(noteEvent(`Assistant error: ${message.error}`));
118
- return;
119
- }
120
- const text = assistantText(message);
121
- if (text !== null)
122
- events.emit({ type: "assistant", text: boundedEventText(text) });
123
- for (const block of message.message.content) {
124
- const value = object(block);
125
- if (value?.type === "thinking" && typeof value.thinking === "string" && value.thinking.trim().length > 0) {
126
- events.emit({ type: "thought", text: boundedThoughtText(value.thinking) });
127
- continue;
128
- }
129
- if (block.type !== "tool_use")
130
- continue;
131
- const call = toolCall(block.name, block.input);
132
- state.tools.set(block.id, { name: block.name, call });
133
- events.emit({ type: "tool", phase: "started", id: block.id, name: block.name, call });
134
- }
135
- }
136
- function toolResultEvents(message, events, state) {
137
- const content = object(message.message)?.content;
138
- if (!Array.isArray(content))
139
- return;
140
- for (const block of content) {
141
- const value = object(block);
142
- if (value?.type !== "tool_result")
143
- continue;
144
- const id = nonblank(value.tool_use_id);
145
- if (id === undefined)
146
- continue;
147
- const observed = state.tools.get(id);
148
- if (observed === undefined)
149
- continue;
150
- state.tools.delete(id);
151
- events.emit({
152
- type: "tool",
153
- phase: "completed",
154
- id,
155
- name: observed.name,
156
- call: observed.call,
157
- result: { status: value.is_error === true ? "error" : "ok" },
158
- });
159
- }
160
- }
161
- function systemNote(message, subtype) {
162
- const note = CLAUDE_SYSTEM_NOTES[subtype];
163
- return note?.(message) ?? subtype;
164
- }
165
- function emitClaudeMessage(message, events, state) {
166
- const value = object(message);
167
- const kind = nonblank(value?.type) ?? "unknown";
168
- if (!Object.hasOwn(CLAUDE_MESSAGE_DISPOSITIONS, kind)) {
169
- events.emit(unknownEvent(kind));
170
- return;
171
- }
172
- const disposition = CLAUDE_MESSAGE_DISPOSITIONS[kind];
173
- if (disposition === "assistant") {
174
- assistantEvents(message, events, state);
175
- return;
176
- }
177
- if (disposition === "tool-results") {
178
- toolResultEvents(message, events, state);
179
- return;
180
- }
181
- if (disposition === "auth") {
182
- const error = nonblank(value?.error);
183
- if (error !== undefined)
184
- events.emit(noteEvent(`Authentication warning: ${error}`));
185
- return;
186
- }
187
- if (disposition === "note") {
188
- events.emit(noteEvent("Conversation reset"));
189
- return;
190
- }
191
- if (disposition !== "system")
192
- return;
193
- const subtype = nonblank(value?.subtype) ?? "unknown";
194
- if (!Object.hasOwn(CLAUDE_SYSTEM_DISPOSITIONS, subtype)) {
195
- events.emit(unknownEvent(subtype));
196
- return;
197
- }
198
- const systemDisposition = CLAUDE_SYSTEM_DISPOSITIONS[subtype];
199
- if (systemDisposition === "drop")
200
- return;
201
- if (systemDisposition === "control-progress" && value?.status !== "api_retry")
202
- return;
203
- events.emit(noteEvent(systemNote(value ?? {}, subtype)));
204
- }
205
- function admitClaudeOptions(options) {
206
- if (options.network !== undefined) {
207
- return { kind: "refused", diagnostic: "Claude provider does not support the Archetype network option" };
208
- }
209
- return { kind: "admitted", options: Object.freeze({ ...options }) };
210
- }
211
- function permissionMode(access) {
212
- if (access === "read")
213
- return "plan";
214
- if (access === "write")
215
- return "acceptEdits";
216
- return "bypassPermissions";
217
- }
218
- async function forkClaude(load, execution, input) {
219
- if (execution.env !== undefined) {
220
- throw new Error("Claude fork cannot apply the frozen provider environment");
221
- }
222
- const sdk = await load();
223
- if (sdk.forkSession === undefined)
224
- throw new Error("Claude SDK does not expose forkSession");
225
- const forked = await sdk.forkSession(input.session.sessionId, { dir: input.cwd, upToMessageId: input.at });
226
- if (forked.sessionId.trim().length === 0)
227
- throw new Error("Claude fork returned an empty child session id");
228
- if (forked.sessionId === input.session.sessionId)
229
- throw new Error("Claude fork reused the source session id");
230
- return { session: { sessionId: forked.sessionId } };
231
- }
232
- export function createClaudeProvider(load, execution = {}) {
233
- return {
234
- confinement: () => ({ kind: "unconfined" }),
235
- admitOptions: admitClaudeOptions,
236
- fork: (input) => forkClaude(load, execution, input),
237
- async start(input) {
238
- const sdk = await load();
239
- const events = new AgentEventChannel();
240
- const abortController = new AbortController();
241
- const providerOptions = input.options;
242
- const access = permissionMode(providerOptions.access);
243
- const options = {
244
- cwd: input.cwd,
245
- abortController,
246
- ...(execution.executable === undefined ? {} : { pathToClaudeCodeExecutable: execution.executable }),
247
- ...(execution.env === undefined ? {} : { env: { ...process.env, ...execution.env } }),
248
- permissionMode: access,
249
- ...(access === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {}),
250
- settingSources: ["user", "project", "local"],
251
- ...(providerOptions.model === undefined ? {} : { model: providerOptions.model }),
252
- ...(providerOptions.effort === undefined ? {} : { effort: providerOptions.effort }),
253
- ...(providerOptions.systemPrompt === undefined || providerOptions.systemPrompt.length === 0 ? {} : {
254
- systemPrompt: { type: "preset", preset: "claude_code", append: providerOptions.systemPrompt },
255
- }),
256
- ...(input.session === undefined ? {} : { resume: input.session.sessionId }),
257
- };
258
- const query = sdk.query({ prompt: input.prompt, options });
259
- const observation = { tools: new Map() };
260
- let admitted = false;
261
- let settle;
262
- const completion = new Promise((resolve) => { settle = resolve; });
263
- void (async () => {
264
- let terminal = null;
265
- let historyId;
266
- try {
267
- for await (const message of query) {
268
- if (!admitted && "session_id" in message && typeof message.session_id === "string") {
269
- admitted = true;
270
- events.emit({ type: "session", coordinate: { sessionId: message.session_id } });
271
- }
272
- emitClaudeMessage(message, events, observation);
273
- if (message.type === "assistant" && message.parent_tool_use_id === null
274
- && typeof message.uuid === "string" && message.uuid.length > 0) {
275
- historyId = message.uuid;
276
- }
277
- if (message.type === "result")
278
- terminal = message.subtype === "success"
279
- ? historyId === undefined
280
- ? { kind: "failed", diagnostic: "Claude query succeeded without an assistant history id" }
281
- : { kind: "answered", answer: message.result, historyId }
282
- : { kind: "failed", diagnostic: message.errors.join("; ") || message.subtype };
283
- }
284
- settle(terminal ?? { kind: "failed", diagnostic: "Claude query ended without a result" });
285
- }
286
- catch (error) {
287
- settle({ kind: "failed", diagnostic: error instanceof Error ? error.message : String(error) });
288
- }
289
- finally {
290
- events.end();
291
- }
292
- })();
293
- return {
294
- events,
295
- completion,
296
- async abort() {
297
- abortController.abort();
298
- query.close();
299
- await completion;
300
- },
301
- };
302
- },
303
- };
304
- }
305
- export const claudeProvider = createClaudeProvider(async () => await import("@anthropic-ai/claude-agent-sdk"));
@@ -1,4 +0,0 @@
1
- export declare function resolveContextRoot(input: Readonly<{
2
- from: string;
3
- marker: string;
4
- }>): string;
@@ -1,15 +0,0 @@
1
- import { existsSync, realpathSync, statSync } from "node:fs";
2
- import { dirname, parse, resolve } from "node:path";
3
- export function resolveContextRoot(input) {
4
- const origin = realpathSync(resolve(input.from));
5
- for (let candidate = origin;; candidate = dirname(candidate)) {
6
- const marker = resolve(candidate, input.marker);
7
- if (existsSync(marker)) {
8
- if (!statSync(marker).isDirectory())
9
- throw new Error(`context marker is not a directory: ${marker}`);
10
- return candidate;
11
- }
12
- if (candidate === parse(candidate).root)
13
- return origin;
14
- }
15
- }
@@ -1,20 +0,0 @@
1
- import type { Preparation } from "../core/decide.js";
2
- import type { ChangeId, ContractCoordinates, ContractId, DeliverData } from "../core/facts/types.js";
3
- import { type GitRepository } from "./repository.js";
4
- export type DeliveryPreparationRefusal = Readonly<{
5
- kind: "target-missing" | "candidate-not-based-on-target" | "worktree-missing";
6
- contractId: ContractId;
7
- }>;
8
- export type ReviewPreparationRefusal = Readonly<{
9
- kind: "worktree-missing";
10
- contractId: ContractId;
11
- }>;
12
- export type DeliveryPreparationCoordinates = Readonly<{
13
- contractId: ContractId;
14
- coordinates: ContractCoordinates;
15
- }>;
16
- export declare function prepareReview(repository: GitRepository, input: DeliveryPreparationCoordinates): Preparation<ChangeId, ReviewPreparationRefusal>;
17
- export declare function prepareDelivery(repository: GitRepository, stage: DeliveryPreparationCoordinates, input: Readonly<{
18
- title: string;
19
- message?: string;
20
- }>): Preparation<DeliverData, DeliveryPreparationRefusal>;
@@ -1,109 +0,0 @@
1
- import { existsSync, mkdtempSync, rmSync } from "node:fs";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { mintChangeId, mintSnapshotId, gitObjectIdForSnapshot, gitObjectId } from "./identity.js";
5
- import { readRef, registeredWorktreePaths, runGit, runGitWithEnvironment } from "./repository.js";
6
- import { deliveryWorktreePath } from "./reconcile.js";
7
- function workspaceExists(repository, workspace, path) {
8
- return workspace === "here"
9
- || (existsSync(path) && registeredWorktreePaths(repository).includes(path));
10
- }
11
- function withPrivateGitIndex(action) {
12
- const directory = mkdtempSync(join(tmpdir(), "keiyaku-v4-index-"));
13
- const index = join(directory, "index");
14
- try {
15
- return action({ GIT_INDEX_FILE: index });
16
- }
17
- finally {
18
- rmSync(directory, { recursive: true, force: true });
19
- }
20
- }
21
- function workspaceFor(repository, id, workspace) {
22
- return workspace === "worktree" ? deliveryWorktreePath(repository, id) : repository.effectiveCwd;
23
- }
24
- function stablePatchId(repository, predecessor, tree) {
25
- const diff = runGit(repository, ["diff", "--binary", gitObjectIdForSnapshot(predecessor), tree]);
26
- const output = runGit(repository, ["patch-id", "--stable"], diff).toString("utf8").trim();
27
- const separator = output.indexOf(" ");
28
- const identity = output.length === 0
29
- ? runGit(repository, ["hash-object", "-t", "blob", "--stdin"], diff).toString("utf8").trim()
30
- : separator < 0 ? output : output.slice(0, separator);
31
- return mintChangeId(identity);
32
- }
33
- function workspaceTree(repository, workspace) {
34
- const identities = runGit(repository, ["-C", workspace, "rev-parse", "HEAD", "HEAD^{tree}"])
35
- .toString("utf8")
36
- .split("\n");
37
- if (identities.length !== 3 || identities[0] === undefined || identities[1] === undefined || identities[2] !== "") {
38
- throw new Error("workspace HEAD/tree resolution did not return exactly two object IDs");
39
- }
40
- const head = mintSnapshotId(identities[0]);
41
- const tree = gitObjectId(identities[1], "workspace tree");
42
- const status = runGit(repository, ["-C", workspace, "status", "--porcelain=v1", "--untracked-files=all"]).toString("utf8");
43
- const dirty = status.length > 0;
44
- if (!dirty)
45
- return { tree, head, dirty };
46
- return withPrivateGitIndex((environment) => {
47
- runGitWithEnvironment(repository, ["-C", workspace, "read-tree", "HEAD"], undefined, environment);
48
- runGitWithEnvironment(repository, ["-C", workspace, "add", "--all"], undefined, environment);
49
- const tree = gitObjectId(runGitWithEnvironment(repository, ["-C", workspace, "write-tree"], undefined, environment).toString("utf8").trim(), "workspace tree");
50
- return { tree, head, dirty };
51
- });
52
- }
53
- function materializeCandidate(input) {
54
- const subject = input.message ?? `${input.contractId}: ${input.title}`;
55
- const message = `${subject}\n\nKeiyaku-Contract: ${input.contractId}\n`;
56
- const commit = runGitWithEnvironment(input.repository, ["-C", input.workspace, "commit-tree", input.tree, "-p", gitObjectIdForSnapshot(input.head)], message, {
57
- GIT_AUTHOR_NAME: "Keiyaku",
58
- GIT_AUTHOR_EMAIL: "keiyaku@localhost",
59
- GIT_COMMITTER_NAME: "Keiyaku",
60
- GIT_COMMITTER_EMAIL: "keiyaku@localhost",
61
- GIT_AUTHOR_DATE: "Thu, 01 Jan 1970 00:00:00 +0000",
62
- GIT_COMMITTER_DATE: "Thu, 01 Jan 1970 00:00:00 +0000",
63
- }).toString("utf8").trim();
64
- return mintSnapshotId(commit);
65
- }
66
- export function prepareReview(repository, input) {
67
- const workspace = workspaceFor(repository, input.contractId, input.coordinates.workspace);
68
- if (!workspaceExists(repository, input.coordinates.workspace, workspace)) {
69
- return { kind: "refused", refusal: { kind: "worktree-missing", contractId: input.contractId } };
70
- }
71
- const tree = workspaceTree(repository, workspace);
72
- return { kind: "prepared", data: stablePatchId(repository, input.coordinates.start, tree.tree) };
73
- }
74
- export function prepareDelivery(repository, stage, input) {
75
- const id = stage.contractId;
76
- const coordinates = stage.coordinates;
77
- const observedTarget = coordinates.target === undefined ? null : readRef(repository, coordinates.target);
78
- if (coordinates.target !== undefined && observedTarget === null) {
79
- return { kind: "refused", refusal: { kind: "target-missing", contractId: id } };
80
- }
81
- const predecessor = observedTarget === null ? coordinates.start : mintSnapshotId(observedTarget);
82
- const workspace = workspaceFor(repository, id, coordinates.workspace);
83
- if (!workspaceExists(repository, coordinates.workspace, workspace)) {
84
- return { kind: "refused", refusal: { kind: "worktree-missing", contractId: id } };
85
- }
86
- const content = workspaceTree(repository, workspace);
87
- const candidate = content.dirty
88
- ? materializeCandidate({ repository, contractId: id, workspace, ...input, tree: content.tree, head: content.head })
89
- : content.head;
90
- if (coordinates.target !== undefined) {
91
- try {
92
- runGit(repository, ["merge-base", "--is-ancestor", gitObjectIdForSnapshot(predecessor), gitObjectIdForSnapshot(candidate)]);
93
- }
94
- catch (error) {
95
- const status = error.status;
96
- if (status === 1)
97
- return { kind: "refused", refusal: { kind: "candidate-not-based-on-target", contractId: id } };
98
- throw error;
99
- }
100
- }
101
- return {
102
- kind: "prepared",
103
- data: {
104
- expectedPredecessor: predecessor,
105
- candidate,
106
- deliveryPatchId: stablePatchId(repository, predecessor, content.tree),
107
- },
108
- };
109
- }
@@ -1,14 +0,0 @@
1
- import type { SnapshotId } from "../core/facts/types.js";
2
- import { type GitRepository } from "./repository.js";
3
- type MaterializedVerificationCandidate = Readonly<{
4
- cwd: string;
5
- dispose: () => WorktreeLeak | null;
6
- }>;
7
- export type WorktreeLeak = Readonly<{
8
- path: string;
9
- diagnostic: string;
10
- }>;
11
- /** Materialize a temporary candidate worktree for verification and own its cleanup. */
12
- export declare function materializeVerificationCandidate(repository: GitRepository, candidate: SnapshotId): MaterializedVerificationCandidate;
13
- export declare function readDeliveryDiff(repository: GitRepository, predecessor: SnapshotId, candidate: SnapshotId): string | null;
14
- export {};
@@ -1,56 +0,0 @@
1
- import { randomBytes } from "node:crypto";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { AuthorityCorruptionError } from "../core/facts/errors.js";
5
- import { gitObjectIdForSnapshot } from "./identity.js";
6
- import { runGit } from "./repository.js";
7
- /** Materialize a temporary candidate worktree for verification and own its cleanup. */
8
- export function materializeVerificationCandidate(repository, candidate) {
9
- const cwd = join(tmpdir(), `keiyaku-v4-verify-${randomBytes(12).toString("hex")}`);
10
- runGit(repository, ["worktree", "add", "--detach", cwd, gitObjectIdForSnapshot(candidate)]);
11
- return {
12
- cwd,
13
- dispose: () => {
14
- try {
15
- runGit(repository, ["worktree", "remove", "--force", cwd]);
16
- return null;
17
- }
18
- catch (error) {
19
- return {
20
- path: cwd,
21
- diagnostic: error instanceof Error ? error.message : String(error),
22
- };
23
- }
24
- },
25
- };
26
- }
27
- /** Resolve both pinned delivery objects through one structured Git batch. */
28
- function deliverySnapshotAvailability(repository, predecessor, candidate) {
29
- const objects = [gitObjectIdForSnapshot(predecessor), gitObjectIdForSnapshot(candidate)];
30
- const types = runGit(repository, ["cat-file", "--batch-check=%(objectname) %(objecttype)"], `${objects.join("\n")}\n`).toString("ascii").trimEnd().split("\n").map((record) => record.split(" ")[1]);
31
- if (types.includes("missing"))
32
- return "unavailable";
33
- if (types.some((type) => type !== "commit")) {
34
- throw new AuthorityCorruptionError("recorded delivery snapshot is not a Git commit");
35
- }
36
- return "available";
37
- }
38
- export function readDeliveryDiff(repository, predecessor, candidate) {
39
- if (deliverySnapshotAvailability(repository, predecessor, candidate) === "unavailable")
40
- return null;
41
- try {
42
- return runGit(repository, [
43
- "diff",
44
- "--no-ext-diff",
45
- "--no-color",
46
- gitObjectIdForSnapshot(predecessor),
47
- gitObjectIdForSnapshot(candidate),
48
- ]).toString("utf8");
49
- }
50
- catch (error) {
51
- // A pruning race after the probes is still Git absence, not a Git error for callers.
52
- if (deliverySnapshotAvailability(repository, predecessor, candidate) === "unavailable")
53
- return null;
54
- throw error;
55
- }
56
- }