@astrosheep/keiyaku 4.6.3 → 4.6.6

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 (193) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +47 -11
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +2 -2
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +8 -9
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +37 -25
  6. package/build/src/akuma/akuma-observe.d.ts +18 -15
  7. package/build/src/akuma/akuma-observe.js +75 -16
  8. package/build/src/akuma/akuma-wait.d.ts +4 -3
  9. package/build/src/akuma/akuma-wait.js +75 -53
  10. package/build/src/akuma/akuma.d.ts +6 -4
  11. package/build/src/akuma/akuma.js +4 -0
  12. package/build/src/akuma/call-initial-tell.d.ts +2 -2
  13. package/build/src/akuma/call-initial-tell.js +1 -1
  14. package/build/src/akuma/call-request.d.ts +2 -2
  15. package/build/src/akuma/heart/index.d.ts +7 -2
  16. package/build/src/akuma/heart/index.js +50 -5
  17. package/build/src/akuma/heart/tells.d.ts +33 -2
  18. package/build/src/akuma/heart/tells.js +24 -18
  19. package/build/src/akuma/heart/timeline.d.ts +23 -1
  20. package/build/src/akuma/heart/timeline.js +28 -21
  21. package/build/src/akuma/projection.d.ts +10 -10
  22. package/build/src/akuma/providers/pi/index.js +72 -39
  23. package/build/src/akuma/selection-observation.d.ts +20 -20
  24. package/build/src/akuma-body.js +1 -0
  25. package/build/src/alias/index.d.ts +0 -1
  26. package/build/src/alias/index.js +0 -4
  27. package/build/src/body/amend.d.ts +0 -4
  28. package/build/src/body/amend.js +0 -3
  29. package/build/src/body/region.d.ts +0 -1
  30. package/build/src/body/region.js +0 -3
  31. package/build/src/body/verification.d.ts +0 -1
  32. package/build/src/cli/commands/akuma-grammar.js +23 -66
  33. package/build/src/cli/commands/akuma.js +17 -30
  34. package/build/src/cli/commands/contract-grammar.d.ts +14 -1
  35. package/build/src/cli/commands/contract-grammar.js +54 -21
  36. package/build/src/cli/commands/contract-help.d.ts +9 -8
  37. package/build/src/cli/commands/contract-help.js +14 -7
  38. package/build/src/cli/commands/contract.js +57 -117
  39. package/build/src/cli/commands/install.d.ts +5 -5
  40. package/build/src/cli/commands/install.js +1 -4
  41. package/build/src/cli/commands/task-grammar.js +10 -66
  42. package/build/src/cli/commands/task.d.ts +0 -1
  43. package/build/src/cli/commands/task.js +34 -53
  44. package/build/src/cli/coordinates.d.ts +1 -2
  45. package/build/src/cli/coordinates.js +1 -4
  46. package/build/src/cli/parse.d.ts +2 -3
  47. package/build/src/cli/parse.js +24 -66
  48. package/build/src/cli/render/akuma.d.ts +3 -16
  49. package/build/src/cli/render/akuma.js +1 -13
  50. package/build/src/cli/render/audit.js +1 -1
  51. package/build/src/cli/render/contract.js +34 -32
  52. package/build/src/cli/render/kanshi-akuma.d.ts +8 -2
  53. package/build/src/cli/render/kanshi-akuma.js +14 -7
  54. package/build/src/cli/render/kanshi.d.ts +3 -1
  55. package/build/src/cli/render/kanshi.js +44 -32
  56. package/build/src/cli/render/receipt.js +6 -1
  57. package/build/src/cli/render/task.d.ts +1 -1
  58. package/build/src/cli/render/task.js +3 -27
  59. package/build/src/cli/render/terminal.d.ts +6 -2
  60. package/build/src/cli/render/terminal.js +8 -2
  61. package/build/src/cli/runtime.js +3 -16
  62. package/build/src/cli/scan.d.ts +26 -0
  63. package/build/src/cli/scan.js +82 -0
  64. package/build/src/cli/streams.d.ts +5 -0
  65. package/build/src/cli/streams.js +11 -0
  66. package/build/src/contract-worktree.js +38 -21
  67. package/build/src/core/facts/codec.d.ts +1 -2
  68. package/build/src/core/facts/codec.js +5 -11
  69. package/build/src/core/facts/types.d.ts +16 -2
  70. package/build/src/core/facts/types.js +15 -0
  71. package/build/src/core/verbs/abandon.js +3 -9
  72. package/build/src/core/verbs/amend.js +2 -9
  73. package/build/src/core/verbs/arc.js +6 -13
  74. package/build/src/core/verbs/attestation.js +2 -9
  75. package/build/src/core/verbs/bind.js +2 -9
  76. package/build/src/core/verbs/deliver.js +2 -9
  77. package/build/src/core/verbs/placement.d.ts +1 -1
  78. package/build/src/core/verbs/placement.js +2 -9
  79. package/build/src/core/verbs/reintegrate.d.ts +1 -1
  80. package/build/src/core/verbs/reintegrate.js +2 -9
  81. package/build/src/dispatch/index.d.ts +2 -2
  82. package/build/src/dispatch/index.js +33 -11
  83. package/build/src/git/hooks.d.ts +2 -4
  84. package/build/src/git/hooks.js +0 -12
  85. package/build/src/git/integration.d.ts +5 -3
  86. package/build/src/git/integration.js +36 -25
  87. package/build/src/git/nuke.js +4 -4
  88. package/build/src/git/observe.d.ts +4 -4
  89. package/build/src/git/observe.js +5 -5
  90. package/build/src/git/process.d.ts +1 -4
  91. package/build/src/git/process.js +1 -11
  92. package/build/src/git/read-observation.js +1 -1
  93. package/build/src/git/reconcile.d.ts +1 -1
  94. package/build/src/git/reconcile.js +15 -13
  95. package/build/src/git/repository.d.ts +2 -6
  96. package/build/src/git/repository.js +18 -31
  97. package/build/src/git/scratch.d.ts +6 -6
  98. package/build/src/git/scratch.js +110 -46
  99. package/build/src/git/target-placement.d.ts +5 -5
  100. package/build/src/git/target-placement.js +18 -33
  101. package/build/src/git/tender.d.ts +6 -2
  102. package/build/src/git/tender.js +19 -12
  103. package/build/src/git/terminal-reconcile.js +24 -13
  104. package/build/src/git/terminal-seal.d.ts +2 -5
  105. package/build/src/git/terminal-seal.js +5 -3
  106. package/build/src/git/workspace.d.ts +17 -13
  107. package/build/src/git/workspace.js +58 -41
  108. package/build/src/kanshi/index.d.ts +2 -2
  109. package/build/src/kanshi/index.js +1 -1
  110. package/build/src/kanshi/read.d.ts +8 -1
  111. package/build/src/kanshi/read.js +72 -7
  112. package/build/src/kanshi/report.d.ts +12 -0
  113. package/build/src/library/akuma-creation.d.ts +4 -4
  114. package/build/src/library/bind.d.ts +1 -63
  115. package/build/src/library/bind.js +3 -9
  116. package/build/src/library/contract-creation.js +2 -30
  117. package/build/src/library/contract-execution.d.ts +0 -1
  118. package/build/src/library/contract-execution.js +9 -34
  119. package/build/src/library/contract-operations.d.ts +5 -1
  120. package/build/src/library/contract-operations.js +7 -3
  121. package/build/src/library/contract-types.d.ts +1 -1
  122. package/build/src/library/delivery.d.ts +91 -93
  123. package/build/src/library/delivery.js +2 -1
  124. package/build/src/library/input.d.ts +0 -2
  125. package/build/src/library/input.js +0 -4
  126. package/build/src/library/invocation.d.ts +0 -1
  127. package/build/src/library/invocation.js +3 -25
  128. package/build/src/library/outcome.d.ts +651 -602
  129. package/build/src/library/outcome.js +4 -4
  130. package/build/src/library/reconcile.d.ts +6 -0
  131. package/build/src/library/reconcile.js +31 -1
  132. package/build/src/library/repo.d.ts +0 -1
  133. package/build/src/library/selection.d.ts +1 -10
  134. package/build/src/library/selection.js +14 -15
  135. package/build/src/protocol/abandon.d.ts +1 -1
  136. package/build/src/protocol/abandon.js +3 -10
  137. package/build/src/protocol/amend.js +2 -5
  138. package/build/src/protocol/arc.d.ts +1 -1
  139. package/build/src/protocol/arc.js +2 -9
  140. package/build/src/protocol/attempt.d.ts +3 -20
  141. package/build/src/protocol/attempt.js +6 -5
  142. package/build/src/protocol/audit.d.ts +1 -0
  143. package/build/src/protocol/audit.js +10 -11
  144. package/build/src/protocol/completion.d.ts +129 -55
  145. package/build/src/protocol/completion.js +62 -73
  146. package/build/src/protocol/deliver.d.ts +7 -5
  147. package/build/src/protocol/deliver.js +74 -44
  148. package/build/src/protocol/execution-observation.d.ts +2 -4
  149. package/build/src/protocol/execution-observation.js +3 -7
  150. package/build/src/protocol/intent.d.ts +1 -1
  151. package/build/src/protocol/intent.js +1 -0
  152. package/build/src/protocol/operations.d.ts +24 -12
  153. package/build/src/protocol/operations.js +36 -15
  154. package/build/src/protocol/placement.d.ts +2 -1
  155. package/build/src/protocol/placement.js +21 -5
  156. package/build/src/protocol/progress.d.ts +1 -1
  157. package/build/src/protocol/read/status.js +58 -41
  158. package/build/src/protocol/reintegrate.d.ts +1 -1
  159. package/build/src/protocol/reintegrate.js +10 -19
  160. package/build/src/protocol/review.d.ts +3 -28
  161. package/build/src/protocol/review.js +10 -37
  162. package/build/src/protocol/run.d.ts +19 -7
  163. package/build/src/protocol/run.js +19 -9
  164. package/build/src/runtime/proc/windows-launch.exe +0 -0
  165. package/build/src/settlement/holder.d.ts +2 -4
  166. package/build/src/settlement/holder.js +3 -6
  167. package/build/src/task/board.d.ts +6 -0
  168. package/build/src/task/board.js +30 -1
  169. package/build/src/task/catalog.js +1 -4
  170. package/build/src/task/compose.d.ts +0 -1
  171. package/build/src/task/compose.js +0 -1
  172. package/build/src/task/context.d.ts +0 -1
  173. package/build/src/task/context.js +0 -3
  174. package/build/src/task/created-observation.d.ts +5 -1
  175. package/build/src/task/created-observation.js +12 -5
  176. package/build/src/task/index.d.ts +1 -1
  177. package/build/src/task/index.js +7 -6
  178. package/build/src/task/input.d.ts +0 -6
  179. package/build/src/task/input.js +2 -14
  180. package/build/src/task/mutation.d.ts +3 -4
  181. package/build/src/task/mutation.js +11 -39
  182. package/build/src/task/operations.d.ts +2 -7
  183. package/build/src/task/operations.js +37 -49
  184. package/build/src/task/query.d.ts +0 -1
  185. package/build/src/task/query.js +1 -4
  186. package/build/src/task/store.d.ts +0 -2
  187. package/build/src/task/store.js +27 -11
  188. package/build/src/verification/declaration.js +3 -2
  189. package/build/src/verification/execution.d.ts +3 -2
  190. package/build/src/verification/execution.js +10 -6
  191. package/build/src/workspace-place.d.ts +0 -1
  192. package/build/src/workspace-place.js +0 -11
  193. package/package.json +7 -3
@@ -61,14 +61,12 @@ export declare const worktreeHookLagSchema: z.ZodObject<{
61
61
  }, z.core.$strict>]>;
62
62
  }, z.core.$strict>;
63
63
  export type WorktreeHookLag = z.infer<typeof worktreeHookLagSchema>;
64
- export type HookPhase = "create" | "destroy";
65
64
  type WorktreeHooksFromInput = Readonly<{
66
65
  settings: Settings;
67
66
  }>;
68
67
  export declare function worktreeHooksFrom(input: WorktreeHooksFromInput): WorktreeHooks;
69
- export declare function normalizedWorktreeHooks(value: unknown): WorktreeHooks;
70
68
  export declare const EMPTY_WORKTREE_HOOKS: WorktreeHooks;
71
- export type HookCommandRun = Readonly<{
69
+ type HookCommandRun = Readonly<{
72
70
  kind: "ok";
73
71
  }> | Readonly<{
74
72
  kind: "cancelled";
@@ -85,7 +83,7 @@ export declare function runHookCommands(worktree: string, commands: readonly Hoo
85
83
  stream: "stdout" | "stderr";
86
84
  text: string;
87
85
  }>) => void): Promise<HookCommandRun>;
88
- export type HookPhaseRun = Readonly<{
86
+ type HookPhaseRun = Readonly<{
89
87
  lag: WorktreeHookLag | null;
90
88
  runs: readonly string[];
91
89
  }>;
@@ -94,18 +94,6 @@ export function worktreeHooksFrom(input) {
94
94
  };
95
95
  return Object.freeze({ create: selected("create"), destroy: selected("destroy") });
96
96
  }
97
- export function normalizedWorktreeHooks(value) {
98
- if (!record(value))
99
- throw new TypeError("hooks must be an object");
100
- for (const key of Object.keys(value)) {
101
- if (key !== "create" && key !== "destroy")
102
- throw new TypeError(`hooks has unknown field: ${key}`);
103
- }
104
- return Object.freeze({
105
- create: commands(value.create, "hooks.create", TypeError),
106
- destroy: commands(value.destroy, "hooks.destroy", TypeError),
107
- });
108
- }
109
97
  export const EMPTY_WORKTREE_HOOKS = Object.freeze({
110
98
  create: Object.freeze([]),
111
99
  destroy: Object.freeze([]),
@@ -3,7 +3,7 @@ import type { Preparation } from "../core/decide.js";
3
3
  import type { ChangeId, ContractCoordinates, ContractId, SnapshotId } from "../core/facts/types.js";
4
4
  import { type GitObjectId } from "./identity.js";
5
5
  import { type GitRepository } from "./process.js";
6
- import type { DeliveryCommitMetadata, TenderCapture } from "./tender.js";
6
+ import { type DeliveryCommitMetadata, type TenderCapture } from "./tender.js";
7
7
  import { workspaceMergeStatePresent } from "./workspace.js";
8
8
  export { workspaceMergeStatePresent };
9
9
  type IntegrationTender = Pick<TenderCapture, "head" | "tree">;
@@ -36,16 +36,18 @@ export declare const integrationPreparationRefusalSchema: z.ZodUnion<readonly [z
36
36
  requiredGit: z.ZodLiteral<"2.38">;
37
37
  }, z.core.$strict>]>;
38
38
  export type IntegrationPreparationRefusal = z.infer<typeof integrationPreparationRefusalSchema>;
39
- export type IntegrationCoordinates = Readonly<{
39
+ type IntegrationCoordinates = Readonly<{
40
40
  contractId: ContractId;
41
41
  coordinates: ContractCoordinates;
42
42
  }>;
43
- export type IntegrationPlan = Readonly<{
43
+ type IntegrationPlan = Readonly<{
44
44
  predecessor: SnapshotId;
45
45
  tree: GitObjectId;
46
46
  }>;
47
47
  /** Mint the one worktree-content identity shared by review and delivery. */
48
48
  export declare function worktreeChangeId(repository: GitRepository, input: IntegrationCoordinates, tender: TenderCapture): Promise<ChangeId>;
49
+ /** Reuse only recorded commits with this exact tree and sole predecessor. */
50
+ export declare function reusableIntegrationSnapshot(repository: GitRepository, tree: GitObjectId, parent: SnapshotId, recordedSnapshots: readonly SnapshotId[]): Promise<SnapshotId | undefined>;
49
51
  /** Materialize the exact integration tree against its observed predecessor. */
50
52
  export declare function materializeIntegrationSnapshot(repository: GitRepository, tree: GitObjectId, parent: SnapshotId, metadata: DeliveryCommitMetadata): Promise<SnapshotId>;
51
53
  export declare function persistedTender(repository: GitRepository, snapshot: SnapshotId): Promise<IntegrationTender>;
@@ -3,13 +3,15 @@ import { z } from "zod";
3
3
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
4
4
  import { gitObjectId, gitObjectIdForSnapshot, mintChangeId, mintSnapshotId } from "./identity.js";
5
5
  import { decodeGitNameOnly, decodeGitNumstat, readRef } from "./repository.js";
6
- import { GitPlumbingError, runGit, runGitPipe, runGitWithEnvironment } from "./process.js";
6
+ import { executeGit, GitPlumbingError, runGitPipe } from "./process.js";
7
+ import { deliveryEnvironment, materializeSnapshotCommit, } from "./tender.js";
7
8
  import { workspaceMergeStatePresent } from "./workspace.js";
9
+ import { withGitDecodeChannel } from "./read-observation.js";
8
10
  export { workspaceMergeStatePresent };
9
11
  const REQUIRED_GIT = "2.38";
10
12
  async function runAllowingNonzero(repository, args, input) {
11
13
  try {
12
- return { stdout: await runGit(repository, args, input), stderr: Buffer.alloc(0), status: 0 };
14
+ return { stdout: await executeGit(repository, args, input), stderr: Buffer.alloc(0), status: 0 };
13
15
  }
14
16
  catch (error) {
15
17
  if (!(error instanceof GitPlumbingError))
@@ -76,22 +78,34 @@ export async function worktreeChangeId(repository, input, tender) {
76
78
  const id = result.toString("utf8").trim().split(/\s/, 1)[0] ?? "";
77
79
  return mintChangeId(id === "" ? "0000000000000000000000000000000000000000" : id);
78
80
  }
81
+ /** Reuse only recorded commits with this exact tree and sole predecessor. */
82
+ export async function reusableIntegrationSnapshot(repository, tree, parent, recordedSnapshots) {
83
+ if (recordedSnapshots.length === 0)
84
+ return undefined;
85
+ return await withGitDecodeChannel(repository, async (channel) => {
86
+ for (const snapshot of recordedSnapshots) {
87
+ const oid = gitObjectIdForSnapshot(snapshot);
88
+ const object = (await channel.readObjects([oid])).get(oid);
89
+ if (object.kind === "missing")
90
+ continue;
91
+ if (object.type !== "commit") {
92
+ throw new AuthorityCorruptionError(`recorded integration snapshot is not a Git commit: ${snapshot}`);
93
+ }
94
+ const headers = object.bytes.toString("utf8").split("\n\n", 1)[0].split("\n");
95
+ const parents = headers.filter((line) => line.startsWith("parent "));
96
+ if (headers[0] === `tree ${tree}` && parents.length === 1 && parents[0] === `parent ${parent}`) {
97
+ return snapshot;
98
+ }
99
+ }
100
+ return undefined;
101
+ });
102
+ }
79
103
  /** Materialize the exact integration tree against its observed predecessor. */
80
104
  export async function materializeIntegrationSnapshot(repository, tree, parent, metadata) {
81
- const commit = (await runGitWithEnvironment(repository, ["commit-tree", tree, "-p", gitObjectIdForSnapshot(parent)], metadata.message, {
82
- GIT_AUTHOR_NAME: metadata.identity.name,
83
- GIT_AUTHOR_EMAIL: metadata.identity.email,
84
- GIT_COMMITTER_NAME: metadata.identity.name,
85
- GIT_COMMITTER_EMAIL: metadata.identity.email,
86
- GIT_AUTHOR_DATE: metadata.at,
87
- GIT_COMMITTER_DATE: metadata.at,
88
- }))
89
- .toString("utf8")
90
- .trim();
91
- return mintSnapshotId(commit);
105
+ return await materializeSnapshotCommit(repository, tree, [parent], metadata.message, deliveryEnvironment(metadata));
92
106
  }
93
107
  export async function persistedTender(repository, snapshot) {
94
- const tree = (await runGit(repository, ["show", "-s", "--format=%T", gitObjectIdForSnapshot(snapshot)]))
108
+ const tree = (await executeGit(repository, ["show", "-s", "--format=%T", gitObjectIdForSnapshot(snapshot)]))
95
109
  .toString("ascii")
96
110
  .trim();
97
111
  return { head: snapshot, tree: gitObjectId(tree, "persisted tender tree") };
@@ -100,7 +114,7 @@ export async function materializeReintegrationSnapshot(repository, tree, parent,
100
114
  const templateObject = gitObjectIdForSnapshot(template);
101
115
  let raw;
102
116
  try {
103
- raw = await runGit(repository, ["cat-file", "commit", templateObject]);
117
+ raw = await executeGit(repository, ["cat-file", "commit", templateObject]);
104
118
  }
105
119
  catch (error) {
106
120
  if (error instanceof GitPlumbingError) {
@@ -114,7 +128,7 @@ export async function materializeReintegrationSnapshot(repository, tree, parent,
114
128
  const message = raw.subarray(separator + 2);
115
129
  let fields;
116
130
  try {
117
- const formatted = (await runGit(repository, ["show", "-s", "--format=%an%x00%ae%x00%aI%x00%cn%x00%ce%x00%cI", templateObject]))
131
+ const formatted = (await executeGit(repository, ["show", "-s", "--format=%an%x00%ae%x00%aI%x00%cn%x00%ce%x00%cI", templateObject]))
118
132
  .toString("utf8")
119
133
  .replace(/\n$/u, "");
120
134
  fields = formatted.split("\0");
@@ -129,17 +143,14 @@ export async function materializeReintegrationSnapshot(repository, tree, parent,
129
143
  throw new AuthorityCorruptionError(`recorded delivery snapshot metadata is malformed: ${template}`);
130
144
  }
131
145
  const [authorName, authorEmail, authorDate, committerName, committerEmail, committerDate] = fields;
132
- const commit = (await runGitWithEnvironment(repository, ["commit-tree", tree, "-p", gitObjectIdForSnapshot(parent)], message, {
146
+ return await materializeSnapshotCommit(repository, tree, [parent], message, {
133
147
  GIT_AUTHOR_NAME: authorName,
134
148
  GIT_AUTHOR_EMAIL: authorEmail,
135
149
  GIT_AUTHOR_DATE: authorDate,
136
150
  GIT_COMMITTER_NAME: committerName,
137
151
  GIT_COMMITTER_EMAIL: committerEmail,
138
152
  GIT_COMMITTER_DATE: committerDate,
139
- }))
140
- .toString("utf8")
141
- .trim();
142
- return mintSnapshotId(commit);
153
+ });
143
154
  }
144
155
  async function isAncestor(repository, ancestor, descendant) {
145
156
  const result = await runAllowingNonzero(repository, [
@@ -302,7 +313,7 @@ export async function planIntegration(repository, input, tender, requireBranches
302
313
  }
303
314
  async function deliverySnapshotAvailability(repository, predecessor, candidate) {
304
315
  const objects = [gitObjectIdForSnapshot(predecessor), gitObjectIdForSnapshot(candidate)];
305
- const types = (await runGit(repository, ["cat-file", "--batch-check=%(objectname) %(objecttype)"], `${objects.join("\n")}\n`))
316
+ const types = (await executeGit(repository, ["cat-file", "--batch-check=%(objectname) %(objecttype)"], `${objects.join("\n")}\n`))
306
317
  .toString("ascii")
307
318
  .trimEnd()
308
319
  .split("\n")
@@ -323,7 +334,7 @@ export const deliveryDiffScopeSchema = z
323
334
  })
324
335
  .strict();
325
336
  export async function readDeliveryScope(repository, predecessor, candidate, includePaths) {
326
- const scope = decodeGitNumstat(await runGit(repository, [
337
+ const scope = decodeGitNumstat(await executeGit(repository, [
327
338
  "diff",
328
339
  "--numstat",
329
340
  "-z",
@@ -334,7 +345,7 @@ export async function readDeliveryScope(repository, predecessor, candidate, incl
334
345
  return scope;
335
346
  return {
336
347
  ...scope,
337
- paths: decodeGitNameOnly(await runGit(repository, [
348
+ paths: decodeGitNameOnly(await executeGit(repository, [
338
349
  "diff",
339
350
  "--name-only",
340
351
  "--no-renames",
@@ -349,7 +360,7 @@ export async function readDeliveryDiff(repository, predecessor, candidate) {
349
360
  if ((await deliverySnapshotAvailability(repository, predecessor, candidate)) === "unavailable")
350
361
  return null;
351
362
  try {
352
- return (await runGit(repository, [
363
+ return (await executeGit(repository, [
353
364
  "diff",
354
365
  "--no-ext-diff",
355
366
  "--no-color",
@@ -1,7 +1,7 @@
1
1
  import { access, lstat, realpath, rm } from "node:fs/promises";
2
2
  import { isAbsolute, relative, sep } from "node:path";
3
3
  import { nukeEmptyPlaceAuthority, readPlaceRegister, releaseManagedWorktrees, withPlaceAuthorityFence, } from "../workspace-place.js";
4
- import { GitPlumbingError, runGit } from "./process.js";
4
+ import { GitPlumbingError, executeGit } from "./process.js";
5
5
  import { confirmPrivateStatePublication, withPrivateStatePublicationSeat, } from "./private-state-seat.js";
6
6
  import { CANDIDATE_PIN_REF_NAMESPACE, DELIVERY_REF_NAMESPACE, GIT_REF, NoGitWorldError, readRef, registeredWorktrees, repositoryAt, worktreeGitDirectory, } from "./repository.js";
7
7
  import { worktreePath } from "./workspace.js";
@@ -89,7 +89,7 @@ async function removeManagedWorktree(repository, entry) {
89
89
  return await removeUnregisteredResidue(repository, entry);
90
90
  if (registered.branch !== null)
91
91
  return false;
92
- await runGit(repository, ["worktree", "remove", "--force", entry.path]);
92
+ await executeGit(repository, ["worktree", "remove", "--force", entry.path]);
93
93
  if ((await registeredWorktrees(repository)).some((candidate) => candidate.path === entry.path)) {
94
94
  throw new GitResetStopError(`managed Place worktree remains registered: ${entry.path}`);
95
95
  }
@@ -104,7 +104,7 @@ async function removeManagedWorktree(repository, entry) {
104
104
  throw new GitResetStopError(`managed Place worktree remains present: ${entry.path}`);
105
105
  }
106
106
  async function deleteRefAt(repository, ref, expectedOid) {
107
- await runGit(repository, ["update-ref", "--no-deref", "-d", ref, expectedOid]);
107
+ await executeGit(repository, ["update-ref", "--no-deref", "-d", ref, expectedOid]);
108
108
  }
109
109
  async function deleteObservedStateRef(repository, expectedOid, seat) {
110
110
  try {
@@ -126,7 +126,7 @@ async function removeOwnedRefs(repository, onRemoved) {
126
126
  let removed = 0;
127
127
  const roots = [DELIVERY_REF_NAMESPACE, CANDIDATE_PIN_REF_NAMESPACE];
128
128
  for (const root of roots) {
129
- const refs = (await runGit(repository, ["for-each-ref", "--format=%(refname)", root]))
129
+ const refs = (await executeGit(repository, ["for-each-ref", "--format=%(refname)", root]))
130
130
  .toString("utf8")
131
131
  .split("\n")
132
132
  .filter((ref) => ref.length > root.length && ref.startsWith(`${root}/`));
@@ -3,7 +3,7 @@ import type { ContractsObservation } from "../core/facts/observation.js";
3
3
  import { type GitSnapshot, type GitOid } from "./repository.js";
4
4
  import { type GitRepository } from "./process.js";
5
5
  import { type GitDecodeChannel, type GitReadObservation, type GitTreeSelection } from "./read-observation.js";
6
- export type TargetObservation = Readonly<{
6
+ type TargetObservation = Readonly<{
7
7
  head: SnapshotId | null;
8
8
  drift: boolean;
9
9
  }>;
@@ -12,11 +12,11 @@ type GitJournalRecord = Readonly<{
12
12
  entries: readonly JournalEntry[];
13
13
  state: ContractState | null;
14
14
  }>;
15
- export type ContractWorldObservation = Readonly<{
15
+ type ContractWorldObservation = Readonly<{
16
16
  snapshot: SnapshotId | null;
17
17
  contracts: ReadonlyMap<ContractId, GitJournalRecord>;
18
18
  }>;
19
- export type ActiveContractWorldObservation = ContractWorldObservation & Readonly<{
19
+ type ActiveContractWorldObservation = ContractWorldObservation & Readonly<{
20
20
  eligibility: ContractsObservation;
21
21
  }>;
22
22
  export type GitAdmissionSnapshot = Readonly<{
@@ -34,7 +34,7 @@ export type BindCoordinatesObservation = Readonly<{
34
34
  target?: string;
35
35
  branch: string | null;
36
36
  }>;
37
- export type UnbornHeadObservation = Readonly<{
37
+ type UnbornHeadObservation = Readonly<{
38
38
  kind: "unborn-head";
39
39
  branch: string | null;
40
40
  }>;
@@ -3,7 +3,7 @@ import { AuthorityCorruptionError } from "../core/facts/errors.js";
3
3
  import { foldJournal } from "../core/facts/fold.js";
4
4
  import { contractJournalPath, contractJournalPaths, mintContractHead, mintSnapshotId, } from "./identity.js";
5
5
  import { isKeiyakuOwnedRef } from "./repository.js";
6
- import { GitPlumbingError, runGit } from "./process.js";
6
+ import { GitPlumbingError, executeGit } from "./process.js";
7
7
  import { readBlobResults, readGitTreeSelection, withGitTargetedReadObservation, } from "./read-observation.js";
8
8
  export async function observeDeliveryTargetAt(observation, state) {
9
9
  const target = state.coordinates.target;
@@ -29,7 +29,7 @@ export async function normalizeTargetBranch(repository, input) {
29
29
  if (branch.length === 0 || branch.startsWith("-") || isKeiyakuOwnedRef(target))
30
30
  return null;
31
31
  try {
32
- const checked = (await runGit(repository, ["check-ref-format", "--branch", branch])).toString("utf8").trim();
32
+ const checked = (await executeGit(repository, ["check-ref-format", "--branch", branch])).toString("utf8").trim();
33
33
  return checked === branch ? target : null;
34
34
  }
35
35
  catch (error) {
@@ -41,7 +41,7 @@ export async function normalizeTargetBranch(repository, input) {
41
41
  /** Read one worktree's attached branch, or null for detached HEAD. */
42
42
  export async function currentBranch(repository, path) {
43
43
  try {
44
- const ref = (await runGit(repository, [...(path === undefined ? [] : ["-C", path]), "symbolic-ref", "--quiet", "HEAD"]))
44
+ const ref = (await executeGit(repository, [...(path === undefined ? [] : ["-C", path]), "symbolic-ref", "--quiet", "HEAD"]))
45
45
  .toString("utf8")
46
46
  .trim();
47
47
  return ref.startsWith("refs/heads/") ? ref : null;
@@ -64,7 +64,7 @@ function structuredFields(output, fieldCount) {
64
64
  async function observeHeadCoordinates(repository) {
65
65
  try {
66
66
  return {
67
- start: mintSnapshotId((await runGit(repository, ["rev-parse", "--verify", "HEAD"])).toString("utf8").trim()),
67
+ start: mintSnapshotId((await executeGit(repository, ["rev-parse", "--verify", "HEAD"])).toString("utf8").trim()),
68
68
  branch: await currentBranch(repository),
69
69
  };
70
70
  }
@@ -84,7 +84,7 @@ export async function observeBindCoordinates(repository, selection = { kind: "ta
84
84
  if (isKeiyakuOwnedRef(requestedTarget)) {
85
85
  throw new Error(`bind target names a Keiyaku-owned ref: ${requestedTarget}`);
86
86
  }
87
- const output = await runGit(repository, [
87
+ const output = await executeGit(repository, [
88
88
  "for-each-ref",
89
89
  `--format=${TARGET_COORDINATES_FORMAT}`,
90
90
  "--",
@@ -16,8 +16,6 @@ export type GitRepository = Readonly<{
16
16
  /** Test-only hook after the private-state seat close attempt. */
17
17
  readonly onPrivateStateSeatClose?: () => void;
18
18
  }>;
19
- /** Give one caller's Git capability view its cancellation boundary. */
20
- export declare function withGitAbortSignal(repository: GitRepository, signal: AbortSignal | undefined): GitRepository;
21
19
  export declare class GitPlumbingError extends Error {
22
20
  readonly stdout: Buffer;
23
21
  readonly stderr: Buffer;
@@ -31,8 +29,7 @@ export declare class GitPlumbingError extends Error {
31
29
  pid?: number | null;
32
30
  }>);
33
31
  }
34
- export declare function runGit(repository: GitRepository, args: readonly string[], input?: string | Uint8Array): Promise<Buffer>;
32
+ export declare function executeGit(repository: GitRepository, args: readonly string[], input?: string | Uint8Array, environment?: NodeJS.ProcessEnv): Promise<Buffer>;
35
33
  /** Connect two owned Git commands without materializing the intermediate output. */
36
34
  export declare function runGitPipe(repository: GitRepository, sourceArgs: readonly string[], sinkArgs: readonly string[]): Promise<Buffer>;
37
35
  export declare function consumeGitStdout(repository: GitRepository, args: readonly string[], consume: (chunk: Buffer) => void): Promise<void>;
38
- export declare function runGitWithEnvironment(repository: GitRepository, args: readonly string[], input: string | Uint8Array | undefined, environment: NodeJS.ProcessEnv): Promise<Buffer>;
@@ -1,9 +1,5 @@
1
1
  import { consumeProcessStdout, spawnCancellableProcess } from "../runtime/proc/run.js";
2
2
  import { pipeline } from "node:stream/promises";
3
- /** Give one caller's Git capability view its cancellation boundary. */
4
- export function withGitAbortSignal(repository, signal) {
5
- return signal === undefined ? repository : { ...repository, signal };
6
- }
7
3
  export class GitPlumbingError extends Error {
8
4
  stdout;
9
5
  stderr;
@@ -32,7 +28,7 @@ function commandError(command, error) {
32
28
  pid: candidate.pid ?? null,
33
29
  });
34
30
  }
35
- async function executeGit(repository, args, input, environment) {
31
+ export async function executeGit(repository, args, input, environment) {
36
32
  if (repository.signal?.aborted === true) {
37
33
  throw commandError(args, { message: "git process cancelled", status: null });
38
34
  }
@@ -81,9 +77,6 @@ async function executeGit(repository, args, input, environment) {
81
77
  pid: child.pid,
82
78
  });
83
79
  }
84
- export async function runGit(repository, args, input) {
85
- return await executeGit(repository, args, input);
86
- }
87
80
  function boundedPipeOutput(child, args) {
88
81
  const stdout = [];
89
82
  let bytes = 0;
@@ -212,6 +205,3 @@ export async function consumeGitStdout(repository, args, consume) {
212
205
  pid: result.pid ?? undefined,
213
206
  });
214
207
  }
215
- export async function runGitWithEnvironment(repository, args, input, environment) {
216
- return await executeGit(repository, args, input, environment);
217
- }
@@ -6,7 +6,7 @@ import { GIT_FORMAT_BYTES, GIT_FORMAT_PATH, GIT_REF, readRef } from "./repositor
6
6
  import { GitPlumbingError } from "./process.js";
7
7
  const gitReadObservationBrand = Symbol("GitReadObservation");
8
8
  const gitDecodeChannelBrand = Symbol("GitDecodeChannel");
9
- const BATCH_RETIREMENT_GRACE_MS = 1_000;
9
+ const BATCH_RETIREMENT_GRACE_MS = 5_000;
10
10
  function streamCursor(stream) {
11
11
  const iterator = stream[Symbol.asyncIterator]();
12
12
  let buffer = Buffer.alloc(0);
@@ -142,7 +142,7 @@ type ReconcileBatchItem = Readonly<{
142
142
  state: ContractState | null;
143
143
  result: ReconcileResult;
144
144
  }>;
145
- export type GitReconcileObservation = Readonly<{
145
+ type GitReconcileObservation = Readonly<{
146
146
  state: ContractState | null;
147
147
  result: ReconcileResult;
148
148
  }>;
@@ -8,7 +8,7 @@ import { dirname, join } from "node:path";
8
8
  import { acquireSqliteTransactionLock, SqliteTransactionLockError, } from "../coordination/sqlite-transaction-lock.js";
9
9
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
10
10
  import { CANDIDATE_PIN_REF_NAMESPACE, commonGitDirectory, DELIVERY_REF_NAMESPACE, registeredWorktreePaths, } from "./repository.js";
11
- import { runGit, GitPlumbingError } from "./process.js";
11
+ import { executeGit, GitPlumbingError } from "./process.js";
12
12
  import { contractLocator, contractPhysicalName, gitObjectIdForSnapshot } from "./identity.js";
13
13
  import { observeContractAt } from "./observe.js";
14
14
  import { acquireTargetPlacementFence, recoverTargetPlacement } from "./target-placement.js";
@@ -158,25 +158,27 @@ async function worktree(repository, topology, path, desired) {
158
158
  if (registered && (await pathExists(path)))
159
159
  return { kind: "worktree", path, action: "unchanged" };
160
160
  if (registered) {
161
- await runGit(repository, ["worktree", "remove", path]);
161
+ await executeGit(repository, ["worktree", "remove", path]);
162
162
  topology.paths.delete(path);
163
163
  }
164
164
  if (await pathExists(path))
165
165
  throw new WorktreeCustodyError(`delivery worktree path is occupied: ${path}`);
166
166
  await mkdir(dirname(path), { recursive: true });
167
- await runGit(repository, ["worktree", "add", "--detach", path, gitObjectIdForSnapshot(desired)]);
167
+ await executeGit(repository, ["worktree", "add", "--detach", path, gitObjectIdForSnapshot(desired)]);
168
168
  topology.paths.add(path);
169
169
  return { kind: "worktree", path, action: "created" };
170
170
  }
171
- async function removeCollectableScratch(repository, topology, acc) {
172
- for (const removal of await removeCollectableScratchWorktrees(repository, topology.paths)) {
173
- acc.recordEffect({ kind: "worktree", path: removal.path, action: removal.action });
174
- if (removal.retained)
175
- acc.recordLag({
176
- kind: "worktree-retained",
177
- path: removal.path,
178
- ...(removal.diagnostic === undefined ? {} : { diagnostic: removal.diagnostic }),
179
- });
171
+ async function removeCollectableScratch(repository, topology, acc, terminalContract) {
172
+ for (const removal of await removeCollectableScratchWorktrees(repository, topology.paths, terminalContract)) {
173
+ if (!removal.retained) {
174
+ acc.recordEffect({ kind: "worktree", path: removal.path, action: "removed" });
175
+ continue;
176
+ }
177
+ acc.recordLag({
178
+ kind: "worktree-retained",
179
+ path: removal.path,
180
+ ...(removal.diagnostic === undefined ? {} : { diagnostic: removal.diagnostic }),
181
+ });
180
182
  }
181
183
  }
182
184
  async function reconcileTargetCheckouts(repository, state, onPhysical) {
@@ -288,7 +290,7 @@ async function reconcileWithTopology(input, state, topology) {
288
290
  const acc = reconcileAccumulation(input.onPhysical);
289
291
  const { effects, lag, hookRuns } = acc;
290
292
  try {
291
- await removeCollectableScratch(repository, topology, acc);
293
+ await removeCollectableScratch(repository, topology, acc, state?.terminal ? state.id : undefined);
292
294
  if (!state)
293
295
  return complete(effects, lag);
294
296
  const targetCheckouts = await reconcileTargetCheckouts(repository, state, input.onPhysical);
@@ -7,7 +7,6 @@ export declare const CANDIDATE_PIN_REF_NAMESPACE = "refs/keiyaku/candidate";
7
7
  export declare const HANDOFF_RECEIPT_REF_NAMESPACE = "refs/keiyaku/handoff";
8
8
  export declare const GIT_FORMAT_PATH = "meta/format.json";
9
9
  export declare const GIT_FORMAT_BYTES = "{\"version\":4}\n";
10
- export declare const STATE_COMMIT_SUBJECT = "keiyaku authority - do not delete or rewrite";
11
10
  export declare function isKeiyakuOwnedRef(ref: string): boolean;
12
11
  export type GitOid = string;
13
12
  export type RefPublication = Readonly<{
@@ -31,7 +30,7 @@ export declare class NoGitWorldError extends Error {
31
30
  readonly path: string;
32
31
  constructor(path: string);
33
32
  }
34
- export type RegisteredWorktree = Readonly<{
33
+ type RegisteredWorktree = Readonly<{
35
34
  path: string;
36
35
  branch: string | null;
37
36
  }>;
@@ -40,12 +39,9 @@ export declare function registeredWorktreePaths(repository: GitRepository): Prom
40
39
  export declare function repositoryAt(cwd: string, gitPath?: string): Promise<GitRepository>;
41
40
  export declare function commonGitDirectory(repository: GitRepository): string;
42
41
  export declare function worktreeGitDirectory(repository: GitRepository, worktree: string): Promise<string>;
43
- export declare function worktreeRoot(repository: GitRepository): Promise<string>;
44
42
  export declare function readRef(repository: GitRepository, ref: string): Promise<GitOid | null>;
45
43
  /** Read an explicit set of asserted refs from one fresh Git observation. */
46
44
  export declare function readRefs(repository: GitRepository, refs: readonly string[]): Promise<Map<any, any>>;
47
- export declare function readTreeEntries(repository: GitRepository, tree: GitOid): Promise<Map<string, TreeEntry>>;
48
- export declare function readGit(repository: GitRepository): Promise<GitSnapshot>;
49
45
  /** Read only the requested private Git paths from one immutable Git tree. */
50
46
  export declare function readGitPaths(repository: GitRepository, requestedPaths: readonly string[]): Promise<GitSnapshot>;
51
47
  export declare function writeBlob(repository: GitRepository, bytes: string | Uint8Array): Promise<GitOid>;
@@ -74,7 +70,7 @@ export declare function updateRefsAtomically(repository: GitRepository, updates:
74
70
  readonly newOid: GitOid;
75
71
  readonly expectedOid: GitOid;
76
72
  })[], assertions?: readonly GitRefAssertion[]): Promise<RefPublication>;
77
- export type GitDiffStat = Readonly<{
73
+ type GitDiffStat = Readonly<{
78
74
  filesChanged: number;
79
75
  insertions: number;
80
76
  deletions: number;