@astrosheep/keiyaku 4.0.4 → 4.0.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 (233) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +4 -4
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +15 -7
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -3
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +24 -4
  8. package/build/src/akuma/akuma.d.ts +2 -1
  9. package/build/src/akuma/akuma.js +27 -9
  10. package/build/src/akuma/allowed.d.ts +1 -1
  11. package/build/src/akuma/allowed.js +3 -10
  12. package/build/src/akuma/archetype.d.ts +3 -1
  13. package/build/src/akuma/archetype.js +11 -6
  14. package/build/src/akuma/body-turn.d.ts +64 -0
  15. package/build/src/akuma/body-turn.js +449 -0
  16. package/build/src/akuma/body.d.ts +4 -5
  17. package/build/src/akuma/body.js +9 -414
  18. package/build/src/akuma/heart/facts.d.ts +37 -9
  19. package/build/src/akuma/heart/facts.js +3 -1
  20. package/build/src/akuma/heart/index.d.ts +4 -13
  21. package/build/src/akuma/heart/index.js +14 -135
  22. package/build/src/akuma/heart/request-authority.d.ts +12 -0
  23. package/build/src/akuma/heart/request-authority.js +119 -0
  24. package/build/src/akuma/heart/request-rows.d.ts +16 -0
  25. package/build/src/akuma/heart/request-rows.js +88 -0
  26. package/build/src/akuma/heart/rows.d.ts +1 -28
  27. package/build/src/akuma/heart/rows.js +4 -138
  28. package/build/src/akuma/heart/schema.d.ts +1 -1
  29. package/build/src/akuma/heart/schema.js +11 -3
  30. package/build/src/akuma/heart/soul.js +0 -36
  31. package/build/src/akuma/heart/timeline.d.ts +1 -0
  32. package/build/src/akuma/heart/timeline.js +19 -0
  33. package/build/src/akuma/index.d.ts +1 -1
  34. package/build/src/akuma/nuke.d.ts +2 -0
  35. package/build/src/akuma/nuke.js +152 -0
  36. package/build/src/akuma/provider-recipe.js +1 -11
  37. package/build/src/akuma/provider.d.ts +4 -7
  38. package/build/src/akuma/providers/acp/config.d.ts +8 -0
  39. package/build/src/akuma/providers/acp/config.js +37 -0
  40. package/build/src/akuma/providers/acp/core.js +12 -2
  41. package/build/src/akuma/providers/acp/index.d.ts +1 -8
  42. package/build/src/akuma/providers/acp/index.js +2 -38
  43. package/build/src/akuma/providers/claude/index.d.ts +0 -4
  44. package/build/src/akuma/providers/claude/index.js +12 -3
  45. package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
  46. package/build/src/akuma/providers/codex-app-server/index.js +5 -2
  47. package/build/src/akuma/providers/grok-build/index.js +1 -2
  48. package/build/src/akuma/providers/index.d.ts +3 -2
  49. package/build/src/akuma/providers/index.js +36 -36
  50. package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
  51. package/build/src/akuma/providers/opencode-sdk/index.js +14 -4
  52. package/build/src/akuma/providers/opencode-sdk/session.d.ts +2 -2
  53. package/build/src/akuma/providers/opencode-sdk/session.js +2 -2
  54. package/build/src/akuma/providers/pi/index.d.ts +1 -1
  55. package/build/src/akuma/providers/pi/index.js +29 -6
  56. package/build/src/akuma/request-serve.d.ts +88 -0
  57. package/build/src/akuma/request-serve.js +484 -0
  58. package/build/src/akuma/request-wire.d.ts +125 -0
  59. package/build/src/akuma/request-wire.js +383 -0
  60. package/build/src/akuma/requests.d.ts +28 -94
  61. package/build/src/akuma/requests.js +52 -562
  62. package/build/src/akuma-body.d.ts +7 -0
  63. package/build/src/akuma-body.js +69 -2
  64. package/build/src/alias/index.d.ts +1 -0
  65. package/build/src/alias/index.js +34 -1
  66. package/build/src/body/arc.js +4 -29
  67. package/build/src/body/decode.js +5 -39
  68. package/build/src/body/envelope.d.ts +7 -0
  69. package/build/src/body/envelope.js +37 -0
  70. package/build/src/cli/accepted.js +21 -9
  71. package/build/src/cli/commands/akuma-invoke.js +1 -0
  72. package/build/src/cli/commands/akuma.d.ts +1 -0
  73. package/build/src/cli/commands/akuma.js +13 -10
  74. package/build/src/cli/commands/contract.d.ts +28 -17
  75. package/build/src/cli/commands/contract.js +23 -17
  76. package/build/src/cli/commands/install.d.ts +2 -2
  77. package/build/src/cli/commands/install.js +6 -6
  78. package/build/src/cli/commands/nuke.d.ts +10 -0
  79. package/build/src/cli/commands/nuke.js +20 -0
  80. package/build/src/cli/commands/task-invoke.d.ts +15 -0
  81. package/build/src/cli/commands/task-invoke.js +144 -24
  82. package/build/src/cli/commands/task-query.d.ts +2 -2
  83. package/build/src/cli/commands/task-query.js +1 -2
  84. package/build/src/cli/commands/task.js +22 -22
  85. package/build/src/cli/coordinates.d.ts +6 -2
  86. package/build/src/cli/coordinates.js +12 -56
  87. package/build/src/cli/invoke.d.ts +5 -4
  88. package/build/src/cli/invoke.js +112 -58
  89. package/build/src/cli/main.d.ts +0 -2
  90. package/build/src/cli/main.js +4 -140
  91. package/build/src/cli/parse.d.ts +17 -4
  92. package/build/src/cli/parse.js +93 -15
  93. package/build/src/cli/render/akuma.js +111 -53
  94. package/build/src/cli/render/audit.js +2 -6
  95. package/build/src/cli/render/contract.js +61 -20
  96. package/build/src/cli/render/kanshi.js +15 -5
  97. package/build/src/cli/render/nuke.d.ts +3 -0
  98. package/build/src/cli/render/nuke.js +8 -0
  99. package/build/src/cli/render/receipt.js +28 -1
  100. package/build/src/cli/render/refusal.d.ts +2 -1
  101. package/build/src/cli/render/refusal.js +31 -0
  102. package/build/src/cli/render/terminal.d.ts +0 -2
  103. package/build/src/cli/render/terminal.js +0 -29
  104. package/build/src/cli/render/text.js +6 -1
  105. package/build/src/cli/result.d.ts +36 -9
  106. package/build/src/cli/runtime.d.ts +2 -0
  107. package/build/src/cli/runtime.js +140 -0
  108. package/build/src/cli/usage.d.ts +0 -2
  109. package/build/src/cli/usage.js +0 -4
  110. package/build/src/contract-worktree.d.ts +29 -14
  111. package/build/src/contract-worktree.js +131 -70
  112. package/build/src/core/facts/codec.js +9 -0
  113. package/build/src/core/facts/fold.js +13 -1
  114. package/build/src/core/facts/types.d.ts +8 -1
  115. package/build/src/core/subject.js +4 -3
  116. package/build/src/core/verbs/placement.d.ts +9 -1
  117. package/build/src/core/verbs/placement.js +24 -6
  118. package/build/src/core/verbs/reintegrate.d.ts +13 -0
  119. package/build/src/core/verbs/reintegrate.js +24 -0
  120. package/build/src/dispatch/index.d.ts +1 -1
  121. package/build/src/git/admission.d.ts +2 -1
  122. package/build/src/git/hooks.d.ts +2 -0
  123. package/build/src/git/hooks.js +34 -1
  124. package/build/src/git/integration.d.ts +9 -2
  125. package/build/src/git/integration.js +92 -1
  126. package/build/src/git/nuke.d.ts +2 -0
  127. package/build/src/git/nuke.js +97 -0
  128. package/build/src/git/observe.d.ts +2 -1
  129. package/build/src/git/observe.js +6 -5
  130. package/build/src/git/process.d.ts +28 -0
  131. package/build/src/git/process.js +94 -0
  132. package/build/src/git/read-observation.d.ts +2 -1
  133. package/build/src/git/read-observation.js +3 -2
  134. package/build/src/git/reconcile.d.ts +4 -1
  135. package/build/src/git/reconcile.js +42 -8
  136. package/build/src/git/repository.d.ts +2 -29
  137. package/build/src/git/repository.js +7 -118
  138. package/build/src/git/scratch.d.ts +1 -1
  139. package/build/src/git/scratch.js +1 -1
  140. package/build/src/git/target-placement.d.ts +3 -2
  141. package/build/src/git/target-placement.js +15 -14
  142. package/build/src/git/tender.d.ts +2 -1
  143. package/build/src/git/tender.js +4 -3
  144. package/build/src/git/terminal-seal.d.ts +2 -2
  145. package/build/src/git/terminal-seal.js +3 -6
  146. package/build/src/git/workspace.d.ts +4 -1
  147. package/build/src/git/workspace.js +1 -1
  148. package/build/src/index.d.ts +1 -2
  149. package/build/src/index.js +1 -1
  150. package/build/src/kanshi/read.js +5 -1
  151. package/build/src/library/address.js +7 -1
  152. package/build/src/library/akuma-creation.d.ts +1 -0
  153. package/build/src/library/akuma-creation.js +8 -1
  154. package/build/src/library/audit.d.ts +3 -1
  155. package/build/src/library/audit.js +2 -1
  156. package/build/src/library/bind.d.ts +2 -1
  157. package/build/src/library/bind.js +1 -1
  158. package/build/src/library/configuration.d.ts +1 -1
  159. package/build/src/library/configuration.js +52 -18
  160. package/build/src/library/contract.d.ts +59 -4
  161. package/build/src/library/contract.js +195 -34
  162. package/build/src/library/delivery.d.ts +4 -2
  163. package/build/src/library/fleet.d.ts +27 -7
  164. package/build/src/library/fleet.js +79 -39
  165. package/build/src/library/input.d.ts +0 -1
  166. package/build/src/library/input.js +0 -5
  167. package/build/src/library/keiyaku.d.ts +6 -2
  168. package/build/src/library/keiyaku.js +2 -0
  169. package/build/src/library/mutation.d.ts +3 -1
  170. package/build/src/library/mutation.js +3 -0
  171. package/build/src/library/nuke.d.ts +14 -0
  172. package/build/src/library/nuke.js +54 -0
  173. package/build/src/library/reconcile.d.ts +2 -1
  174. package/build/src/library/reconcile.js +8 -3
  175. package/build/src/library/refusal.d.ts +10 -1
  176. package/build/src/library/region.d.ts +1 -1
  177. package/build/src/library/repo.d.ts +4 -1
  178. package/build/src/library/repo.js +10 -4
  179. package/build/src/protocol/abandon.d.ts +9 -0
  180. package/build/src/protocol/abandon.js +15 -0
  181. package/build/src/protocol/amend.d.ts +16 -0
  182. package/build/src/protocol/amend.js +77 -0
  183. package/build/src/protocol/arc.d.ts +6 -0
  184. package/build/src/protocol/arc.js +12 -0
  185. package/build/src/protocol/attempt.d.ts +2 -1
  186. package/build/src/protocol/audit.d.ts +53 -0
  187. package/build/src/protocol/audit.js +147 -0
  188. package/build/src/protocol/bind.d.ts +1 -1
  189. package/build/src/protocol/completion.d.ts +42 -0
  190. package/build/src/protocol/completion.js +183 -0
  191. package/build/src/protocol/deliver.d.ts +49 -0
  192. package/build/src/protocol/deliver.js +261 -0
  193. package/build/src/protocol/intent.d.ts +2 -1
  194. package/build/src/protocol/intent.js +8 -2
  195. package/build/src/protocol/operations.d.ts +93 -202
  196. package/build/src/protocol/operations.js +23 -642
  197. package/build/src/protocol/placement.d.ts +12 -13
  198. package/build/src/protocol/placement.js +8 -19
  199. package/build/src/protocol/read/status.d.ts +17 -5
  200. package/build/src/protocol/read/status.js +57 -13
  201. package/build/src/protocol/reconcile.d.ts +35 -0
  202. package/build/src/protocol/reconcile.js +41 -0
  203. package/build/src/protocol/reintegrate.d.ts +31 -0
  204. package/build/src/protocol/reintegrate.js +74 -0
  205. package/build/src/protocol/review.d.ts +34 -0
  206. package/build/src/protocol/review.js +156 -0
  207. package/build/src/protocol/run.d.ts +1 -1
  208. package/build/src/runtime/proc/run.js +9 -5
  209. package/build/src/settlement/fence.d.ts +3 -1
  210. package/build/src/settlement/fence.js +24 -0
  211. package/build/src/settlement/holder.d.ts +1 -1
  212. package/build/src/settlement/settle.d.ts +1 -1
  213. package/build/src/settlement/settle.js +1 -2
  214. package/build/src/task/board.d.ts +0 -1
  215. package/build/src/task/board.js +0 -3
  216. package/build/src/task/compose.d.ts +2 -2
  217. package/build/src/task/compose.js +13 -11
  218. package/build/src/task/context.d.ts +14 -2
  219. package/build/src/task/context.js +30 -7
  220. package/build/src/task/index.d.ts +7 -6
  221. package/build/src/task/index.js +17 -145
  222. package/build/src/task/input.d.ts +18 -0
  223. package/build/src/task/input.js +189 -0
  224. package/build/src/task/mutation.d.ts +44 -0
  225. package/build/src/task/mutation.js +93 -0
  226. package/build/src/task/operations.d.ts +14 -6
  227. package/build/src/task/operations.js +57 -57
  228. package/build/src/task/store.d.ts +1 -0
  229. package/build/src/task/store.js +91 -3
  230. package/build/src/verification/execution.d.ts +1 -1
  231. package/build/src/workspace-place.d.ts +3 -4
  232. package/build/src/workspace-place.js +26 -15
  233. package/package.json +3 -3
@@ -1,8 +1,7 @@
1
- import { spawn } from "node:child_process";
2
1
  import { isAbsolute, resolve } from "node:path";
3
2
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
4
- import { consumeProcessStdout } from "../runtime/proc/run.js";
5
3
  import { gitObjectId } from "./identity.js";
4
+ import { GitPlumbingError, runGit, runGitWithEnvironment } from "./process.js";
6
5
  import { parseTreeObject, prepareTreeUpdate, treeUpdate, validPath, } from "./tree.js";
7
6
  export const GIT_REF = "refs/heads/keiyaku-state";
8
7
  export const DELIVERY_REF_NAMESPACE = "refs/heads/keiyaku-delivery";
@@ -25,21 +24,6 @@ export class NoGitWorldError extends Error {
25
24
  this.path = path;
26
25
  }
27
26
  }
28
- export class GitPlumbingError extends Error {
29
- stdout;
30
- stderr;
31
- status;
32
- pid;
33
- constructor(input) {
34
- super(input.message);
35
- this.name = "GitPlumbingError";
36
- this.stdout = Buffer.from(input.stdout ?? "");
37
- this.stderr = Buffer.from(input.stderr);
38
- this.status = input.status;
39
- this.pid = input.pid ?? null;
40
- }
41
- }
42
- const GIT_STDERR_BYTES = 16 * 1024;
43
27
  function worktreesFromPorcelain(output) {
44
28
  const fields = output.toString("utf8").split("\0");
45
29
  const worktrees = [];
@@ -79,20 +63,24 @@ export async function registeredWorktrees(repository) {
79
63
  export async function registeredWorktreePaths(repository) {
80
64
  return (await registeredWorktrees(repository)).map((worktree) => worktree.path);
81
65
  }
82
- export async function repositoryAt(cwd) {
66
+ export async function repositoryAt(cwd, gitPath = "git") {
83
67
  if (typeof cwd !== "string" || cwd.length === 0) {
84
68
  throw new Error("repository path must be a nonempty string");
85
69
  }
86
70
  const effectiveCwd = resolve(cwd);
87
71
  const provisional = {
72
+ gitPath,
88
73
  effectiveCwd,
74
+ invocationWorktree: effectiveCwd,
89
75
  primaryWorktree: effectiveCwd,
90
76
  commonDirectory: effectiveCwd,
91
77
  };
78
+ let invocationWorktree;
92
79
  let primaryWorktree;
93
80
  let commonDirectory;
94
81
  try {
95
82
  primaryWorktree = (await registeredWorktreePaths(provisional))[0];
83
+ invocationWorktree = await worktreeRoot(provisional);
96
84
  commonDirectory = await absoluteGitPath(provisional, ["--git-common-dir"], "common Git directory");
97
85
  }
98
86
  catch (error) {
@@ -101,7 +89,7 @@ export async function repositoryAt(cwd) {
101
89
  }
102
90
  throw error;
103
91
  }
104
- return { effectiveCwd, primaryWorktree, commonDirectory };
92
+ return { gitPath, effectiveCwd, invocationWorktree, primaryWorktree, commonDirectory };
105
93
  }
106
94
  async function absoluteGitPath(repository, args, label) {
107
95
  const value = (await runGit(repository, ["rev-parse", "--path-format=absolute", ...args])).toString("utf8").trim();
@@ -119,83 +107,6 @@ export async function worktreeGitDirectory(repository, worktree) {
119
107
  export async function worktreeRoot(repository) {
120
108
  return await absoluteGitPath(repository, ["--show-toplevel"], "worktree root");
121
109
  }
122
- function commandError(command, error) {
123
- const candidate = error;
124
- const stderr = candidate.stderr === undefined ? Buffer.alloc(0) : Buffer.from(candidate.stderr);
125
- const stdout = candidate.stdout === undefined ? Buffer.alloc(0) : Buffer.from(candidate.stdout);
126
- const detail = stderr.length === 0 ? candidate.message ?? "git command failed" : stderr.toString("utf8");
127
- return new GitPlumbingError({
128
- stdout,
129
- stderr,
130
- status: candidate.status ?? null,
131
- message: `${command.join(" ")}: ${detail}`,
132
- pid: candidate.pid ?? null,
133
- });
134
- }
135
- async function executeGit(repository, args, input, environment) {
136
- const stdout = [];
137
- const stderr = [];
138
- let stderrBytes = 0;
139
- let inputError;
140
- const child = spawn("git", [...args], {
141
- cwd: repository.effectiveCwd,
142
- ...(environment === undefined ? {} : { env: { ...process.env, ...environment } }),
143
- stdio: ["pipe", "pipe", "pipe"],
144
- windowsHide: true,
145
- });
146
- child.stdout.on("data", (chunk) => stdout.push(chunk));
147
- child.stderr.on("data", (chunk) => {
148
- if (stderrBytes >= GIT_STDERR_BYTES)
149
- return;
150
- const retained = chunk.subarray(0, GIT_STDERR_BYTES - stderrBytes);
151
- stderr.push(retained);
152
- stderrBytes += retained.length;
153
- });
154
- child.stdin.on("error", (error) => { inputError = error; });
155
- child.stdin.end(input);
156
- const terminal = await new Promise((resolveTerminal) => {
157
- child.once("error", (error) => resolveTerminal({ code: null, error }));
158
- child.once("close", (code) => resolveTerminal({ code }));
159
- });
160
- const output = Buffer.concat(stdout);
161
- if (terminal.code === 0 && inputError === undefined)
162
- return output;
163
- throw commandError(args, {
164
- message: terminal.error?.message ?? inputError?.message ?? `git exited with status ${terminal.code ?? "unknown"}`,
165
- stdout: output,
166
- stderr: Buffer.concat(stderr),
167
- status: terminal.code,
168
- pid: child.pid,
169
- });
170
- }
171
- export async function runGit(repository, args, input) {
172
- return await executeGit(repository, args, input);
173
- }
174
- export async function consumeGitStdout(repository, args, consume) {
175
- const result = await consumeProcessStdout({
176
- argv: ["git", ...args],
177
- cwd: repository.effectiveCwd,
178
- }, consume);
179
- const { outcome } = result;
180
- if (outcome.kind === "terminal" && outcome.code === 0)
181
- return;
182
- const status = outcome.kind === "terminal" ? outcome.code : null;
183
- const stderr = outcome.kind === "terminal" ? outcome.stderr : "";
184
- const message = outcome.kind === "terminal"
185
- ? `git exited with status ${outcome.code}`
186
- : outcome.kind === "spawn-error" || outcome.kind === "stream-error"
187
- ? outcome.diagnostic
188
- : `git process ended with ${outcome.kind}`;
189
- throw commandError(args, {
190
- message,
191
- stderr,
192
- status,
193
- pid: result.pid ?? undefined,
194
- });
195
- }
196
- export async function runGitWithEnvironment(repository, args, input, environment) {
197
- return await executeGit(repository, args, input, environment);
198
- }
199
110
  function assertOid(oid, label) {
200
111
  gitObjectId(oid, label);
201
112
  }
@@ -282,28 +193,6 @@ export async function readGitPaths(repository, requestedPaths) {
282
193
  await validateGitFormat(repository, paths);
283
194
  return { commit, tree, paths };
284
195
  }
285
- /** Add paths from the same immutable Git tree without rereading its ref. */
286
- export async function extendGitPaths(repository, snapshot, requestedPaths) {
287
- for (const path of requestedPaths)
288
- validPath(path);
289
- if (snapshot.tree === null || requestedPaths.length === 0)
290
- return snapshot;
291
- const additions = parseTreeEntries(await runGit(repository, [
292
- "ls-tree",
293
- "-z",
294
- "--full-tree",
295
- snapshot.tree,
296
- "--",
297
- ...requestedPaths,
298
- ]));
299
- return { ...snapshot, paths: new Map([...snapshot.paths, ...additions]) };
300
- }
301
- /** Expand a targeted immutable snapshot to its complete already-pinned tree. */
302
- export async function expandGitSnapshot(repository, snapshot) {
303
- if (snapshot.tree === null)
304
- return snapshot;
305
- return { ...snapshot, paths: await readTreeEntries(repository, snapshot.tree) };
306
- }
307
196
  export async function writeBlob(repository, bytes) {
308
197
  const oid = (await runGit(repository, ["hash-object", "-w", "--stdin"], bytes)).toString("utf8").trim();
309
198
  assertOid(oid, "written blob");
@@ -1,5 +1,5 @@
1
1
  import type { SnapshotId } from "../core/facts/types.js";
2
- import { type GitRepository } from "./repository.js";
2
+ import { type GitRepository } from "./process.js";
3
3
  export type MaterializedScratchCandidate = Readonly<{
4
4
  cwd: string;
5
5
  dispose: () => Promise<WorktreeLeak | null>;
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
4
4
  import { basename, dirname, join } from "node:path";
5
5
  import { tryAcquireSqliteTransactionLock, } from "../coordination/sqlite-transaction-lock.js";
6
6
  import { gitObjectIdForSnapshot } from "./identity.js";
7
- import { runGit } from "./repository.js";
7
+ import { runGit } from "./process.js";
8
8
  const SCRATCH_PREFIX = "keiyaku-v4-verify-";
9
9
  const SCRATCH_ROOT = await realpath(tmpdir());
10
10
  const SCRATCH_PATTERN = /^keiyaku-v4-verify-([0-9a-f]{24})$/;
@@ -1,7 +1,7 @@
1
1
  import { type HeldSqliteTransactionLock } from "../coordination/sqlite-transaction-lock.js";
2
2
  import type { ContractId, ContractState, SnapshotId } from "../core/facts/types.js";
3
3
  import type { RefOperation } from "../core/facts/offer.js";
4
- import { type GitRepository } from "./repository.js";
4
+ import { type GitRepository } from "./process.js";
5
5
  export type WorkspaceNotOnTargetRefusal = Readonly<{
6
6
  kind: "workspace-not-on-target";
7
7
  contractId: ContractId;
@@ -58,6 +58,7 @@ export type TargetPlacementObservationInput = Readonly<{
58
58
  coordinates: TargetedContractCoordinates;
59
59
  predecessor: SnapshotId;
60
60
  candidate: SnapshotId;
61
+ hereWorkspacePath?: string;
61
62
  }>;
62
63
  export type TargetPlacementObservation = Readonly<{
63
64
  kind: "ready";
@@ -86,7 +87,7 @@ export type AuditTargetAnswer = Readonly<{
86
87
  }>;
87
88
  /** Adjudicate the complete post-Verification audit target answer without placing. */
88
89
  export declare function adjudicateAuditTarget(repository: GitRepository, input: TargetPlacementObservationInput): Promise<AuditTargetAnswer>;
89
- export declare function prepareTargetPlacement(repository: GitRepository, state: ContractState, target: RefOperation): Promise<TargetPlacementPreparation>;
90
+ export declare function prepareTargetPlacement(repository: GitRepository, state: ContractState, target: RefOperation, hereWorkspacePath?: string): Promise<TargetPlacementPreparation>;
90
91
  export declare function followTargetPlacement(repository: GitRepository, prepared: PreparedTargetPlacement): Promise<TargetPlacementPhysicalResult>;
91
92
  export declare function recoverTargetPlacement(repository: GitRepository, state: ContractState): Promise<TargetPlacementPhysicalResult>;
92
93
  export {};
@@ -3,7 +3,8 @@ import { resolve } from "node:path";
3
3
  import { acquireSqliteTransactionLock } from "../coordination/sqlite-transaction-lock.js";
4
4
  import { gitObjectId, gitObjectIdForSnapshot, gitRefLocator, mintSnapshotId } from "./identity.js";
5
5
  import { currentBranch } from "./observe.js";
6
- import { commonGitDirectory, consumeGitStdout, GitPlumbingError, readRef, registeredWorktrees, runGit, } from "./repository.js";
6
+ import { commonGitDirectory, readRef, registeredWorktrees, } from "./repository.js";
7
+ import { consumeGitStdout, GitPlumbingError, runGit, } from "./process.js";
7
8
  import { captureWorkspaceTree } from "./workspace.js";
8
9
  export async function observeTargetHead(repository, target) {
9
10
  const value = await readRef(repository, target);
@@ -162,9 +163,6 @@ async function indexMatchesTreeOnPaths(repository, path, tree, paths) {
162
163
  async function workspaceMatchesTreeOnPaths(repository, path, tree, workspaceTree, paths) {
163
164
  return (await gitPaths(repository, path, ["diff", "--name-only", "-z", tree, workspaceTree, "--", ...paths])).length === 0;
164
165
  }
165
- async function sourceWorktree(repository) {
166
- return resolve((await runGit(repository, ["rev-parse", "--show-toplevel"])).toString("utf8").trim());
167
- }
168
166
  async function ordinaryPrecheck(repository, contractId, target, path) {
169
167
  const predecessor = gitObjectIdForSnapshot(target.expectedOid);
170
168
  const candidate = gitObjectIdForSnapshot(target.newOid);
@@ -201,7 +199,7 @@ export async function observeTargetPlacement(repository, input) {
201
199
  const worktrees = (await registeredWorktrees(repository))
202
200
  .filter((worktree) => worktree.branch === target.target)
203
201
  .sort((left, right) => left.path.localeCompare(right.path));
204
- const hereSource = input.coordinates.workspace === "here" ? await sourceWorktree(repository) : null;
202
+ const hereSource = input.coordinates.workspace === "here" ? input.hereWorkspacePath ?? null : null;
205
203
  if (hereSource !== null) {
206
204
  const branch = await currentBranch(repository, hereSource);
207
205
  if (branch !== target.target) {
@@ -226,9 +224,10 @@ export async function observeTargetPlacement(repository, input) {
226
224
  }
227
225
  arms.push({ kind, path: worktree.path });
228
226
  }
229
- if (hereSource !== null && !arms.some((arm) => arm.kind === "here")) {
227
+ if (input.coordinates.workspace === "here" && hereSource === null)
228
+ throw new Error("targeted here workspace is unappointed");
229
+ if (hereSource !== null && !arms.some((arm) => arm.kind === "here"))
230
230
  throw new Error("targeted here workspace is not a registered checkout of its target");
231
- }
232
231
  return { kind: "ready", arms };
233
232
  }
234
233
  /** Adjudicate the complete post-Verification audit target answer without placing. */
@@ -253,8 +252,8 @@ export async function adjudicateAuditTarget(repository, input) {
253
252
  return { kind: "failed", diagnostic: error.message };
254
253
  }
255
254
  }
256
- export async function prepareTargetPlacement(repository, state, target) {
257
- if (state.coordinates.target !== target.target || state.delivery?.data.integration.snapshot !== target.newOid) {
255
+ export async function prepareTargetPlacement(repository, state, target, hereWorkspacePath) {
256
+ if (state.coordinates.target !== target.target || state.currentIntegration?.snapshot !== target.newOid) {
258
257
  throw new Error("placement state does not match its offered target movement");
259
258
  }
260
259
  const observation = await observeTargetPlacement(repository, {
@@ -262,6 +261,7 @@ export async function prepareTargetPlacement(repository, state, target) {
262
261
  coordinates: { ...state.coordinates, target: target.target },
263
262
  predecessor: target.expectedOid,
264
263
  candidate: target.newOid,
264
+ ...(hereWorkspacePath === undefined ? {} : { hereWorkspacePath }),
265
265
  });
266
266
  return observation.kind === "refused"
267
267
  ? observation
@@ -340,10 +340,11 @@ export async function recoverTargetPlacement(repository, state) {
340
340
  const delivery = state.delivery;
341
341
  if (state.terminal?.kind !== "claimed" || target === undefined || delivery === null)
342
342
  return { effects: [], lag: [] };
343
- if (await readRef(repository, target) !== delivery.data.integration.snapshot)
343
+ const integration = state.currentIntegration;
344
+ if (integration === null || await readRef(repository, target) !== integration.snapshot)
344
345
  return { effects: [], lag: [] };
345
- const candidateTree = await commitTree(repository, delivery.data.integration.snapshot);
346
- const predecessorTree = await commitTree(repository, delivery.data.integration.predecessor);
346
+ const candidateTree = await commitTree(repository, integration.snapshot);
347
+ const predecessorTree = await commitTree(repository, integration.predecessor);
347
348
  const worktrees = (await registeredWorktrees(repository))
348
349
  .filter((worktree) => worktree.branch === target)
349
350
  .sort((left, right) => left.path.localeCompare(right.path));
@@ -354,8 +355,8 @@ export async function recoverTargetPlacement(repository, state) {
354
355
  const recovery = await recoverCheckout({
355
356
  repository,
356
357
  path: worktree.path,
357
- predecessor: delivery.data.integration.predecessor,
358
- candidate: delivery.data.integration.snapshot,
358
+ predecessor: integration.predecessor,
359
+ candidate: integration.snapshot,
359
360
  predecessorTree,
360
361
  candidateTree,
361
362
  });
@@ -1,12 +1,13 @@
1
1
  import type { Preparation } from "../core/decide.js";
2
2
  import type { ActorId, ContractCoordinates, ContractId, SnapshotId } from "../core/facts/types.js";
3
3
  import { type GitObjectId } from "./identity.js";
4
- import { type GitRepository } from "./repository.js";
4
+ import { type GitRepository } from "./process.js";
5
5
  import { captureWorkspaceTree } from "./workspace.js";
6
6
  export type TenderCaptureCoordinates = Readonly<{
7
7
  contractId: ContractId;
8
8
  coordinates: ContractCoordinates;
9
9
  place?: string;
10
+ workspacePath?: string;
10
11
  }>;
11
12
  export type TenderCaptureRefusal = Readonly<{
12
13
  kind: "worktree-missing";
@@ -1,6 +1,7 @@
1
1
  import { access } from "node:fs/promises";
2
2
  import { gitObjectIdForSnapshot, mintSnapshotId } from "./identity.js";
3
- import { decodeGitNumstat, GitPlumbingError, registeredWorktreePaths, runGit, runGitWithEnvironment, } from "./repository.js";
3
+ import { decodeGitNumstat, registeredWorktreePaths, } from "./repository.js";
4
+ import { GitPlumbingError, runGit, runGitWithEnvironment, } from "./process.js";
4
5
  import { captureWorkspaceTree, worktreePath } from "./workspace.js";
5
6
  async function workspaceExists(repository, workspace, path) {
6
7
  const exists = await access(path).then(() => true, () => false);
@@ -8,8 +9,8 @@ async function workspaceExists(repository, workspace, path) {
8
9
  || (exists && (await registeredWorktreePaths(repository)).includes(path));
9
10
  }
10
11
  function workspaceFor(repository, input) {
11
- if (input.coordinates.workspace === "here")
12
- return repository.effectiveCwd;
12
+ if (input.workspacePath !== undefined)
13
+ return input.workspacePath;
13
14
  return input.place === undefined ? undefined : worktreePath(repository, input.place);
14
15
  }
15
16
  /** Capture the complete workspace tree through Git's private index mechanics. */
@@ -1,6 +1,7 @@
1
1
  import type { ContractState, SnapshotId } from "../core/facts/types.js";
2
2
  import { type GitObjectId } from "./identity.js";
3
- import { type GitOid, type GitRepository } from "./repository.js";
3
+ import type { GitOid } from "./repository.js";
4
+ import { type GitRepository } from "./process.js";
4
5
  import { captureWorkspaceTree } from "./workspace.js";
5
6
  export type UnsealedBytes = Readonly<{
6
7
  kind: "unsealed-bytes";
@@ -33,6 +34,5 @@ export type TerminalWorkspaceObservation = Readonly<{
33
34
  export declare function terminalSealSnapshots(state: ContractState): readonly SnapshotId[];
34
35
  export declare function terminalSealExpectations(state: ContractState, objects: ReadonlyMap<GitOid, TerminalSealObject>): TerminalSealExpectations;
35
36
  export declare function unsealedWorkspaceBytes(repository: GitRepository, path: string, expected: TerminalSealExpectations, workspace: WorkspaceTree): Promise<UnsealedBytes | null>;
36
- export declare function unsealedBytes(repository: GitRepository, path: string, expected: TerminalSealExpectations): Promise<UnsealedBytes | null>;
37
37
  export declare function observeTerminalWorkspace(repository: GitRepository, path: string, expected: TerminalSealExpectations): Promise<TerminalWorkspaceObservation>;
38
38
  export {};
@@ -1,12 +1,12 @@
1
1
  import { gitObjectId, gitObjectIdForSnapshot, mintSnapshotId } from "./identity.js";
2
- import { runGit } from "./repository.js";
2
+ import { runGit } from "./process.js";
3
3
  import { captureWorkspaceTree } from "./workspace.js";
4
4
  export function terminalSealSnapshots(state) {
5
5
  return [...new Set([
6
6
  state.coordinates.start,
7
7
  ...(state.delivery === null ? [] : [
8
8
  state.delivery.data.tenderSnapshot,
9
- state.delivery.data.integration.snapshot,
9
+ ...(state.currentIntegration === null ? [] : [state.currentIntegration.snapshot]),
10
10
  ]),
11
11
  ])];
12
12
  }
@@ -51,7 +51,7 @@ export function terminalSealExpectations(state, objects) {
51
51
  state.coordinates.start,
52
52
  ...(tenderParent === undefined ? [] : [tenderParent]),
53
53
  tender,
54
- state.delivery.data.integration.snapshot,
54
+ state.currentIntegration?.snapshot ?? state.delivery.data.integration.snapshot,
55
55
  ])],
56
56
  trees: [...treeBySnapshot.values()],
57
57
  treeBySnapshot,
@@ -86,9 +86,6 @@ export async function unsealedWorkspaceBytes(repository, path, expected, workspa
86
86
  ...(headIsSealed ? {} : { head: workspace.head }),
87
87
  };
88
88
  }
89
- export async function unsealedBytes(repository, path, expected) {
90
- return (await observeTerminalWorkspace(repository, path, expected)).unsealed;
91
- }
92
89
  export async function observeTerminalWorkspace(repository, path, expected) {
93
90
  const captured = await captureWorkspaceTree(repository, path);
94
91
  return {
@@ -1,6 +1,6 @@
1
1
  import type { SnapshotId } from "../core/facts/types.js";
2
2
  import { type GitObjectId } from "./identity.js";
3
- import { type GitRepository } from "./repository.js";
3
+ import { type GitRepository } from "./process.js";
4
4
  export type WorkspaceChanges = Readonly<{
5
5
  staged: readonly string[];
6
6
  unstaged: readonly string[];
@@ -39,6 +39,9 @@ export type ContractWorkspaceObservation = Readonly<{
39
39
  location: ContractWorkspaceLocation;
40
40
  }> | Readonly<{
41
41
  kind: "unappointed";
42
+ }> | Readonly<{
43
+ kind: "failed";
44
+ diagnostic: string;
42
45
  }>;
43
46
  export type ContractTargetLag = Readonly<{
44
47
  kind: "counted";
@@ -2,7 +2,7 @@ import { mkdtemp, rm } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join, resolve } from "node:path";
4
4
  import { gitObjectId, mintSnapshotId } from "./identity.js";
5
- import { runGit, runGitWithEnvironment } from "./repository.js";
5
+ import { runGit, runGitWithEnvironment } from "./process.js";
6
6
  const WORKTREE_DIRECTORY = ["keiyaku", "wt"];
7
7
  export function worktreePath(repository, place) {
8
8
  return resolve(repository.commonDirectory, ...WORKTREE_DIRECTORY, place);
@@ -1,6 +1,5 @@
1
- export { AuthorityCorruptionError, AkumaWorldScopeError, Delivery, gatesFrom, Keiyaku, KeiyakuRefused, KeiyakuRetry, NoGitWorldError, Repo, requireBranchesToBeUpToDateFrom, SettingsError, worktreeHooksFrom } from "./library/keiyaku.js";
1
+ export * from "./library/keiyaku.js";
2
2
  export { settings } from "./settings.js";
3
3
  export { World, WorldError } from "./world.js";
4
4
  export type { WorldResolution, WorldResolutionInput, WorldRoot } from "./world.js";
5
5
  export type { Settings, SettingsEntry, SettingsInput, SettingsNamespaceFailure, SettingsNamespaceView, SettingsScope, SettingsScopeState, } from "./settings.js";
6
- export type { AttestationVerdict, AbandonInput, ActorId, AkuId, AllowedAction, AllowedActions, AkumaAddressInput, AkumaAlias, AkumaGlob, AkumaHistoryInput, AkumaHistoryResult, AkumaInterruptInput, AkumaInterruptResult, AkumaKillResult, AkumaObservation, AkumaSetAddressInput, AkumaStatus, AkumaTellInput, CreatedTaskObservation, AkumaTellResult, AkumaWaitInput, AkumaWaitResult, AkumaWorldScopeRefusal, AliasBinding, AliasStage, AmendResult, AmendInput, ArcInput, AuditReport, DeliveryPreparationRefusal, BindInput, BindResult, CallInput, CallObservation, CallResult, Catalog, CatalogInput, CatalogQuery, ChangeId, ContractId, ContractState, ContractBoard, ContractDisposition, ContractGateCurrent, ContractGateReport, ContractHistory, ContractHistoryEvent, ContractListInput, ContractObservation, ContractObservationInput, ContractPhase, ContractRow, DeliverInput, Fact, FactKind, Dispatch, DispatchFailure, DispatchStage, DirectAkumaSelector, Gate, GatesFromInput, HookCommand, RequireBranchesToBeUpToDateFromInput, KeiyakuOfInput, KeiyakuRefusal, KeiyakuRetryReason, ForkInput, ForkResult, IntegrationFailure, Lag, MutationResult, PlacementStop, RegionOverlap, ReconcileInput, RepoReconcileReport, Review, ReconcileReport, ReviewInput, RepoAtInput, AuditInput, SnapshotId, SettlementAction, SettlementLag, SettlementReport, SetAkumaSelector, TaskId, TopologyEffect, VerificationReuse, VerificationStop, WorktreeHooks, } from "./library/keiyaku.js";
@@ -1,3 +1,3 @@
1
- export { AuthorityCorruptionError, AkumaWorldScopeError, Delivery, gatesFrom, Keiyaku, KeiyakuRefused, KeiyakuRetry, NoGitWorldError, Repo, requireBranchesToBeUpToDateFrom, SettingsError, worktreeHooksFrom } from "./library/keiyaku.js";
1
+ export * from "./library/keiyaku.js";
2
2
  export { settings } from "./settings.js";
3
3
  export { World, WorldError } from "./world.js";
@@ -1,5 +1,6 @@
1
1
  import { Repo } from "../library/repo.js";
2
2
  import { scopeForRepo } from "../library/repo.js";
3
+ import { resolveHereContractWorkspace } from "../contract-worktree.js";
3
4
  import { observeTaskBoard } from "../task/operations.js";
4
5
  import { contractNamespace } from "../settlement/settle.js";
5
6
  import { Akuma } from "../akuma/index.js";
@@ -123,7 +124,10 @@ async function readBranch(repo) {
123
124
  }
124
125
  async function readContracts(observation, selected) {
125
126
  try {
126
- return { kind: "present", value: await readContractBoard(observation, selected) };
127
+ return {
128
+ kind: "present",
129
+ value: await readContractBoard(observation, selected, async (id) => await resolveHereContractWorkspace(observation.repository, id)),
130
+ };
127
131
  }
128
132
  catch (error) {
129
133
  return { kind: "failed", failure: { message: diagnostic(error) } };
@@ -116,7 +116,13 @@ function addSelectorIds(selector, sources, selected, contractMembers) {
116
116
  selected.add(selector.value);
117
117
  }
118
118
  async function contractMemberInWorld(path, id) {
119
- return await probeBornAkuma(path, id);
119
+ try {
120
+ return await probeBornAkuma(path, id);
121
+ }
122
+ catch {
123
+ // A dispatched physical member remains selected when its Heart cannot be read.
124
+ return true;
125
+ }
120
126
  }
121
127
  async function refuseForeignContractMembers(path, ids, contractMembers) {
122
128
  const foreign = [];
@@ -40,6 +40,7 @@ export type CallInput = Readonly<{
40
40
  archetype: string;
41
41
  body: string;
42
42
  cwd?: string;
43
+ readonly?: true;
43
44
  mode?: "wait" | "detach";
44
45
  timeoutMs?: number;
45
46
  home?: string;
@@ -59,6 +59,11 @@ function callMode(value) {
59
59
  return "detach";
60
60
  throw new TypeError("mode must be wait or detach");
61
61
  }
62
+ function callReadonly(value) {
63
+ if (value === undefined || value === true)
64
+ return value;
65
+ throw new TypeError("readonly must be true");
66
+ }
62
67
  function callTimeout(value, mode) {
63
68
  if (mode === "detach" && value !== undefined) {
64
69
  throw new TypeError("timeoutMs is not valid in detach mode");
@@ -162,10 +167,11 @@ async function resolveCallExecution(input) {
162
167
  }
163
168
  export async function callKeiyaku(input) {
164
169
  const values = requireInput(input, "Keiyaku.call input");
165
- onlyKeys(values, ["path", "archetype", "body", "cwd", "mode", "timeoutMs", "home", "settings", "contract", "alias", "allowed"], "Keiyaku.call input");
170
+ onlyKeys(values, ["path", "archetype", "body", "cwd", "readonly", "mode", "timeoutMs", "home", "settings", "contract", "alias", "allowed"], "Keiyaku.call input");
166
171
  const path = nonblank(values.path, "path");
167
172
  const archetype = nonblank(values.archetype, "archetype");
168
173
  const body = text(values.body, "body");
174
+ const readonlyRequested = callReadonly(values.readonly);
169
175
  const cwd = values.cwd === undefined ? undefined : nonblank(values.cwd, "cwd");
170
176
  const mode = callMode(values.mode);
171
177
  const timeoutMs = callTimeout(values.timeoutMs, mode);
@@ -184,6 +190,7 @@ export async function callKeiyaku(input) {
184
190
  const call = {
185
191
  archetype,
186
192
  body,
193
+ ...(readonlyRequested === undefined ? {} : { readonly: readonlyRequested }),
187
194
  ...(values.allowed === undefined ? {} : { allowed: values.allowed }),
188
195
  ...(execution === undefined ? {} : { cwd: execution.cwd }),
189
196
  };
@@ -1,5 +1,6 @@
1
1
  import type { ContractId } from "../core/facts/types.js";
2
- import { type AuditReport, type RepositoryScope } from "../protocol/operations.js";
2
+ import { type AuditReport } from "../protocol/audit.js";
3
+ import type { RepositoryScope } from "../protocol/operations.js";
3
4
  import { type WorktreeHooks } from "./configuration.js";
4
5
  import { type MutationResult } from "./mutation.js";
5
6
  export type AuditInput = Readonly<{
@@ -15,4 +16,5 @@ export declare function auditContract(input: Readonly<{
15
16
  scope: RepositoryScope;
16
17
  contractId: ContractId;
17
18
  input?: AuditInput;
19
+ resolveHereWorkspace?: (contractId: ContractId) => Promise<string | undefined>;
18
20
  }>): Promise<MutationResult<AuditReport>>;
@@ -1,6 +1,6 @@
1
1
  import { decodeContractDocument } from "../body/decode.js";
2
2
  import { withGitDecodeChannel } from "../git/read-observation.js";
3
- import { auditOperation, } from "../protocol/operations.js";
3
+ import { auditOperation } from "../protocol/audit.js";
4
4
  import { worktreeHooksOption } from "./configuration.js";
5
5
  import { actorOption, documentDerivation, optionalBoolean, optionalSignal, requireInput, } from "./input.js";
6
6
  import { completeMutation } from "./mutation.js";
@@ -31,6 +31,7 @@ export async function auditContract(input) {
31
31
  requireBranchesToBeUpToDate: normalized.requireBranchesToBeUpToDate,
32
32
  ...(normalized.signal === undefined ? {} : { signal: normalized.signal }),
33
33
  ...(normalized.actor === undefined ? {} : { actor: normalized.actor }),
34
+ ...(input.resolveHereWorkspace === undefined ? {} : { resolveHereWorkspace: input.resolveHereWorkspace }),
34
35
  }));
35
36
  return completeMutation({
36
37
  scope: input.scope,
@@ -1,6 +1,7 @@
1
1
  import { type ActorId, type ContractId } from "../core/facts/types.js";
2
2
  import type { GitDecodeChannel } from "../git/read-observation.js";
3
- import { bindOperation, type IntentOutcome, type RepositoryScope } from "../protocol/operations.js";
3
+ import { bindOperation } from "../protocol/bind.js";
4
+ import type { IntentOutcome, RepositoryScope } from "../protocol/operations.js";
4
5
  import type { TaskId } from "../task/identity.js";
5
6
  import type { VerificationDeclarationPreparation } from "../verification/declaration.js";
6
7
  import type { KeiyakuRefusal } from "./refusal.js";
@@ -2,7 +2,7 @@ import { randomBytes } from "node:crypto";
2
2
  import { releaseContractWorktree, reserveContractWorktree, withContractWorktreeAppointment, } from "../contract-worktree.js";
3
3
  import { contractIdFromSegment } from "../core/facts/types.js";
4
4
  import { fitIdentityStem, normalizeIdentityStem } from "../identity/normalize.js";
5
- import { bindOperation } from "../protocol/operations.js";
5
+ import { bindOperation } from "../protocol/bind.js";
6
6
  import { claimTaskHolder } from "../settlement/holder.js";
7
7
  function candidateId(title, collision) {
8
8
  const stem = fitIdentityStem({ stem: normalizeIdentityStem({ source: title }) || "contract", maxBytes: 48 });
@@ -4,7 +4,7 @@ export type { HookCommand, WorktreeHooks } from "../git/hooks.js";
4
4
  export type Gate = string;
5
5
  export type GatesFromInput = Readonly<{
6
6
  settings: Settings;
7
- name?: string;
7
+ names?: readonly string[];
8
8
  }>;
9
9
  export type RequireBranchesToBeUpToDateFromInput = Readonly<{
10
10
  settings: Settings;