@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.
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +47 -11
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +8 -9
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +37 -25
- package/build/src/akuma/akuma-observe.d.ts +18 -15
- package/build/src/akuma/akuma-observe.js +75 -16
- package/build/src/akuma/akuma-wait.d.ts +4 -3
- package/build/src/akuma/akuma-wait.js +75 -53
- package/build/src/akuma/akuma.d.ts +6 -4
- package/build/src/akuma/akuma.js +4 -0
- package/build/src/akuma/call-initial-tell.d.ts +2 -2
- package/build/src/akuma/call-initial-tell.js +1 -1
- package/build/src/akuma/call-request.d.ts +2 -2
- package/build/src/akuma/heart/index.d.ts +7 -2
- package/build/src/akuma/heart/index.js +50 -5
- package/build/src/akuma/heart/tells.d.ts +33 -2
- package/build/src/akuma/heart/tells.js +24 -18
- package/build/src/akuma/heart/timeline.d.ts +23 -1
- package/build/src/akuma/heart/timeline.js +28 -21
- package/build/src/akuma/projection.d.ts +10 -10
- package/build/src/akuma/providers/pi/index.js +72 -39
- package/build/src/akuma/selection-observation.d.ts +20 -20
- package/build/src/akuma-body.js +1 -0
- package/build/src/alias/index.d.ts +0 -1
- package/build/src/alias/index.js +0 -4
- package/build/src/body/amend.d.ts +0 -4
- package/build/src/body/amend.js +0 -3
- package/build/src/body/region.d.ts +0 -1
- package/build/src/body/region.js +0 -3
- package/build/src/body/verification.d.ts +0 -1
- package/build/src/cli/commands/akuma-grammar.js +23 -66
- package/build/src/cli/commands/akuma.js +17 -30
- package/build/src/cli/commands/contract-grammar.d.ts +14 -1
- package/build/src/cli/commands/contract-grammar.js +54 -21
- package/build/src/cli/commands/contract-help.d.ts +9 -8
- package/build/src/cli/commands/contract-help.js +14 -7
- package/build/src/cli/commands/contract.js +57 -117
- package/build/src/cli/commands/install.d.ts +5 -5
- package/build/src/cli/commands/install.js +1 -4
- package/build/src/cli/commands/task-grammar.js +10 -66
- package/build/src/cli/commands/task.d.ts +0 -1
- package/build/src/cli/commands/task.js +34 -53
- package/build/src/cli/coordinates.d.ts +1 -2
- package/build/src/cli/coordinates.js +1 -4
- package/build/src/cli/parse.d.ts +2 -3
- package/build/src/cli/parse.js +24 -66
- package/build/src/cli/render/akuma.d.ts +3 -16
- package/build/src/cli/render/akuma.js +1 -13
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/contract.js +34 -32
- package/build/src/cli/render/kanshi-akuma.d.ts +8 -2
- package/build/src/cli/render/kanshi-akuma.js +14 -7
- package/build/src/cli/render/kanshi.d.ts +3 -1
- package/build/src/cli/render/kanshi.js +44 -32
- package/build/src/cli/render/receipt.js +6 -1
- package/build/src/cli/render/task.d.ts +1 -1
- package/build/src/cli/render/task.js +3 -27
- package/build/src/cli/render/terminal.d.ts +6 -2
- package/build/src/cli/render/terminal.js +8 -2
- package/build/src/cli/runtime.js +3 -16
- package/build/src/cli/scan.d.ts +26 -0
- package/build/src/cli/scan.js +82 -0
- package/build/src/cli/streams.d.ts +5 -0
- package/build/src/cli/streams.js +11 -0
- package/build/src/contract-worktree.js +38 -21
- package/build/src/core/facts/codec.d.ts +1 -2
- package/build/src/core/facts/codec.js +5 -11
- package/build/src/core/facts/types.d.ts +16 -2
- package/build/src/core/facts/types.js +15 -0
- package/build/src/core/verbs/abandon.js +3 -9
- package/build/src/core/verbs/amend.js +2 -9
- package/build/src/core/verbs/arc.js +6 -13
- package/build/src/core/verbs/attestation.js +2 -9
- package/build/src/core/verbs/bind.js +2 -9
- package/build/src/core/verbs/deliver.js +2 -9
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +2 -9
- package/build/src/core/verbs/reintegrate.d.ts +1 -1
- package/build/src/core/verbs/reintegrate.js +2 -9
- package/build/src/dispatch/index.d.ts +2 -2
- package/build/src/dispatch/index.js +33 -11
- package/build/src/git/hooks.d.ts +2 -4
- package/build/src/git/hooks.js +0 -12
- package/build/src/git/integration.d.ts +5 -3
- package/build/src/git/integration.js +36 -25
- package/build/src/git/nuke.js +4 -4
- package/build/src/git/observe.d.ts +4 -4
- package/build/src/git/observe.js +5 -5
- package/build/src/git/process.d.ts +1 -4
- package/build/src/git/process.js +1 -11
- package/build/src/git/read-observation.js +1 -1
- package/build/src/git/reconcile.d.ts +1 -1
- package/build/src/git/reconcile.js +15 -13
- package/build/src/git/repository.d.ts +2 -6
- package/build/src/git/repository.js +18 -31
- package/build/src/git/scratch.d.ts +6 -6
- package/build/src/git/scratch.js +110 -46
- package/build/src/git/target-placement.d.ts +5 -5
- package/build/src/git/target-placement.js +18 -33
- package/build/src/git/tender.d.ts +6 -2
- package/build/src/git/tender.js +19 -12
- package/build/src/git/terminal-reconcile.js +24 -13
- package/build/src/git/terminal-seal.d.ts +2 -5
- package/build/src/git/terminal-seal.js +5 -3
- package/build/src/git/workspace.d.ts +17 -13
- package/build/src/git/workspace.js +58 -41
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +8 -1
- package/build/src/kanshi/read.js +72 -7
- package/build/src/kanshi/report.d.ts +12 -0
- package/build/src/library/akuma-creation.d.ts +4 -4
- package/build/src/library/bind.d.ts +1 -63
- package/build/src/library/bind.js +3 -9
- package/build/src/library/contract-creation.js +2 -30
- package/build/src/library/contract-execution.d.ts +0 -1
- package/build/src/library/contract-execution.js +9 -34
- package/build/src/library/contract-operations.d.ts +5 -1
- package/build/src/library/contract-operations.js +7 -3
- package/build/src/library/contract-types.d.ts +1 -1
- package/build/src/library/delivery.d.ts +91 -93
- package/build/src/library/delivery.js +2 -1
- package/build/src/library/input.d.ts +0 -2
- package/build/src/library/input.js +0 -4
- package/build/src/library/invocation.d.ts +0 -1
- package/build/src/library/invocation.js +3 -25
- package/build/src/library/outcome.d.ts +651 -602
- package/build/src/library/outcome.js +4 -4
- package/build/src/library/reconcile.d.ts +6 -0
- package/build/src/library/reconcile.js +31 -1
- package/build/src/library/repo.d.ts +0 -1
- package/build/src/library/selection.d.ts +1 -10
- package/build/src/library/selection.js +14 -15
- package/build/src/protocol/abandon.d.ts +1 -1
- package/build/src/protocol/abandon.js +3 -10
- package/build/src/protocol/amend.js +2 -5
- package/build/src/protocol/arc.d.ts +1 -1
- package/build/src/protocol/arc.js +2 -9
- package/build/src/protocol/attempt.d.ts +3 -20
- package/build/src/protocol/attempt.js +6 -5
- package/build/src/protocol/audit.d.ts +1 -0
- package/build/src/protocol/audit.js +10 -11
- package/build/src/protocol/completion.d.ts +129 -55
- package/build/src/protocol/completion.js +62 -73
- package/build/src/protocol/deliver.d.ts +7 -5
- package/build/src/protocol/deliver.js +74 -44
- package/build/src/protocol/execution-observation.d.ts +2 -4
- package/build/src/protocol/execution-observation.js +3 -7
- package/build/src/protocol/intent.d.ts +1 -1
- package/build/src/protocol/intent.js +1 -0
- package/build/src/protocol/operations.d.ts +24 -12
- package/build/src/protocol/operations.js +36 -15
- package/build/src/protocol/placement.d.ts +2 -1
- package/build/src/protocol/placement.js +21 -5
- package/build/src/protocol/progress.d.ts +1 -1
- package/build/src/protocol/read/status.js +58 -41
- package/build/src/protocol/reintegrate.d.ts +1 -1
- package/build/src/protocol/reintegrate.js +10 -19
- package/build/src/protocol/review.d.ts +3 -28
- package/build/src/protocol/review.js +10 -37
- package/build/src/protocol/run.d.ts +19 -7
- package/build/src/protocol/run.js +19 -9
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settlement/holder.d.ts +2 -4
- package/build/src/settlement/holder.js +3 -6
- package/build/src/task/board.d.ts +6 -0
- package/build/src/task/board.js +30 -1
- package/build/src/task/catalog.js +1 -4
- package/build/src/task/compose.d.ts +0 -1
- package/build/src/task/compose.js +0 -1
- package/build/src/task/context.d.ts +0 -1
- package/build/src/task/context.js +0 -3
- package/build/src/task/created-observation.d.ts +5 -1
- package/build/src/task/created-observation.js +12 -5
- package/build/src/task/index.d.ts +1 -1
- package/build/src/task/index.js +7 -6
- package/build/src/task/input.d.ts +0 -6
- package/build/src/task/input.js +2 -14
- package/build/src/task/mutation.d.ts +3 -4
- package/build/src/task/mutation.js +11 -39
- package/build/src/task/operations.d.ts +2 -7
- package/build/src/task/operations.js +37 -49
- package/build/src/task/query.d.ts +0 -1
- package/build/src/task/query.js +1 -4
- package/build/src/task/store.d.ts +0 -2
- package/build/src/task/store.js +27 -11
- package/build/src/verification/declaration.js +3 -2
- package/build/src/verification/execution.d.ts +3 -2
- package/build/src/verification/execution.js +10 -6
- package/build/src/workspace-place.d.ts +0 -1
- package/build/src/workspace-place.js +0 -11
- package/package.json +7 -3
|
@@ -2,7 +2,7 @@ import { isAbsolute, resolve } from "node:path";
|
|
|
2
2
|
import { realpath } from "node:fs/promises";
|
|
3
3
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
4
4
|
import { gitObjectId } from "./identity.js";
|
|
5
|
-
import {
|
|
5
|
+
import { executeGit, GitPlumbingError } from "./process.js";
|
|
6
6
|
import { parseTreeObject, prepareTreeUpdate, treeUpdate, validPath, } from "./tree.js";
|
|
7
7
|
export const GIT_REF = "refs/heads/keiyaku-state";
|
|
8
8
|
export const DELIVERY_REF_NAMESPACE = "refs/keiyaku/delivery";
|
|
@@ -11,7 +11,7 @@ export const HANDOFF_RECEIPT_REF_NAMESPACE = "refs/keiyaku/handoff";
|
|
|
11
11
|
export const GIT_FORMAT_PATH = "meta/format.json";
|
|
12
12
|
const CURRENT_FORMAT_VERSION = 4;
|
|
13
13
|
export const GIT_FORMAT_BYTES = `{"version":${CURRENT_FORMAT_VERSION}}\n`;
|
|
14
|
-
|
|
14
|
+
const STATE_COMMIT_SUBJECT = "keiyaku authority - do not delete or rewrite";
|
|
15
15
|
export function isKeiyakuOwnedRef(ref) {
|
|
16
16
|
return (ref === GIT_REF ||
|
|
17
17
|
ref === DELIVERY_REF_NAMESPACE ||
|
|
@@ -67,7 +67,7 @@ function worktreesFromPorcelain(output) {
|
|
|
67
67
|
return worktrees;
|
|
68
68
|
}
|
|
69
69
|
export async function registeredWorktrees(repository) {
|
|
70
|
-
return await Promise.all(worktreesFromPorcelain(await
|
|
70
|
+
return await Promise.all(worktreesFromPorcelain(await executeGit(repository, ["worktree", "list", "--porcelain", "-z"])).map(async (worktree) => {
|
|
71
71
|
const { prunable, ...registered } = worktree;
|
|
72
72
|
try {
|
|
73
73
|
return { ...registered, path: await realpath(registered.path) };
|
|
@@ -111,7 +111,9 @@ export async function repositoryAt(cwd, gitPath = "git") {
|
|
|
111
111
|
return { gitPath, effectiveCwd, invocationWorktree, primaryWorktree, commonDirectory };
|
|
112
112
|
}
|
|
113
113
|
async function absoluteGitPath(repository, args, label) {
|
|
114
|
-
const value = (await
|
|
114
|
+
const value = (await executeGit(repository, ["rev-parse", "--path-format=absolute", ...args]))
|
|
115
|
+
.toString("utf8")
|
|
116
|
+
.trim();
|
|
115
117
|
if (value.length === 0)
|
|
116
118
|
throw new Error(`${label} is empty`);
|
|
117
119
|
return await realpath(resolve(isAbsolute(value) ? value : resolve(repository.effectiveCwd, value)));
|
|
@@ -123,7 +125,7 @@ export async function worktreeGitDirectory(repository, worktree) {
|
|
|
123
125
|
const scoped = { ...repository, effectiveCwd: worktree };
|
|
124
126
|
return await absoluteGitPath(scoped, ["--git-dir"], "worktree Git directory");
|
|
125
127
|
}
|
|
126
|
-
|
|
128
|
+
async function worktreeRoot(repository) {
|
|
127
129
|
return await absoluteGitPath(repository, ["--show-toplevel"], "worktree root");
|
|
128
130
|
}
|
|
129
131
|
function assertRef(ref) {
|
|
@@ -138,7 +140,7 @@ function assertAssertionRef(ref) {
|
|
|
138
140
|
export async function readRef(repository, ref) {
|
|
139
141
|
assertAssertionRef(ref);
|
|
140
142
|
try {
|
|
141
|
-
const oid = (await
|
|
143
|
+
const oid = (await executeGit(repository, ["rev-parse", "--verify", "--quiet", ref])).toString("utf8").trim();
|
|
142
144
|
return oid.length === 0 ? null : gitObjectId(oid, `ref ${ref}`);
|
|
143
145
|
}
|
|
144
146
|
catch (error) {
|
|
@@ -154,7 +156,7 @@ export async function readRefs(repository, refs) {
|
|
|
154
156
|
assertAssertionRef(ref);
|
|
155
157
|
if (refsToRead.length === 0)
|
|
156
158
|
return new Map();
|
|
157
|
-
const output = (await
|
|
159
|
+
const output = (await executeGit(repository, ["cat-file", "--batch-check=%(objectname)"], `${refsToRead.join("\n")}\n`)).toString("utf8");
|
|
158
160
|
const records = output.split("\n");
|
|
159
161
|
if (records.pop() !== "" || records.length !== refsToRead.length)
|
|
160
162
|
throw new Error("Git ref batch output is malformed");
|
|
@@ -168,7 +170,7 @@ export async function readRefs(repository, refs) {
|
|
|
168
170
|
}
|
|
169
171
|
async function readTreeForCommit(repository, commit) {
|
|
170
172
|
gitObjectId(commit, "Git commit");
|
|
171
|
-
const tree = (await
|
|
173
|
+
const tree = (await executeGit(repository, ["show", "-s", "--format=%T", commit])).toString("utf8").trim();
|
|
172
174
|
gitObjectId(tree, "Git tree");
|
|
173
175
|
return tree;
|
|
174
176
|
}
|
|
@@ -190,21 +192,6 @@ function parseTreeEntries(output) {
|
|
|
190
192
|
}
|
|
191
193
|
return entries;
|
|
192
194
|
}
|
|
193
|
-
export async function readTreeEntries(repository, tree) {
|
|
194
|
-
gitObjectId(tree, "tree");
|
|
195
|
-
const output = await runGit(repository, ["ls-tree", "-r", "-z", "--full-tree", tree]);
|
|
196
|
-
return parseTreeEntries(output);
|
|
197
|
-
}
|
|
198
|
-
export async function readGit(repository) {
|
|
199
|
-
const commit = await readRef(repository, GIT_REF);
|
|
200
|
-
if (commit === null) {
|
|
201
|
-
return { commit: null, tree: null, paths: new Map() };
|
|
202
|
-
}
|
|
203
|
-
const tree = await readTreeForCommit(repository, commit);
|
|
204
|
-
const paths = await readTreeEntries(repository, tree);
|
|
205
|
-
await validateGitFormat(repository, paths);
|
|
206
|
-
return { commit, tree, paths };
|
|
207
|
-
}
|
|
208
195
|
/** Read only the requested private Git paths from one immutable Git tree. */
|
|
209
196
|
export async function readGitPaths(repository, requestedPaths) {
|
|
210
197
|
for (const path of requestedPaths)
|
|
@@ -213,18 +200,18 @@ export async function readGitPaths(repository, requestedPaths) {
|
|
|
213
200
|
if (commit === null)
|
|
214
201
|
return { commit: null, tree: null, paths: new Map() };
|
|
215
202
|
const tree = await readTreeForCommit(repository, commit);
|
|
216
|
-
const paths = parseTreeEntries(await
|
|
203
|
+
const paths = parseTreeEntries(await executeGit(repository, ["ls-tree", "-z", "--full-tree", tree, "--", GIT_FORMAT_PATH, ...requestedPaths]));
|
|
217
204
|
await validateGitFormat(repository, paths);
|
|
218
205
|
return { commit, tree, paths };
|
|
219
206
|
}
|
|
220
207
|
export async function writeBlob(repository, bytes) {
|
|
221
|
-
const oid = (await
|
|
208
|
+
const oid = (await executeGit(repository, ["hash-object", "-w", "--stdin"], bytes)).toString("utf8").trim();
|
|
222
209
|
gitObjectId(oid, "written blob");
|
|
223
210
|
return oid;
|
|
224
211
|
}
|
|
225
212
|
export async function readBlob(repository, oid) {
|
|
226
213
|
gitObjectId(oid, "blob");
|
|
227
|
-
return await
|
|
214
|
+
return await executeGit(repository, ["cat-file", "blob", oid]);
|
|
228
215
|
}
|
|
229
216
|
function malformedBatchOutput(detail) {
|
|
230
217
|
throw new GitPlumbingError({
|
|
@@ -239,7 +226,7 @@ async function readObjects(repository, oids) {
|
|
|
239
226
|
gitObjectId(oid, "Git object");
|
|
240
227
|
if (unique.length === 0)
|
|
241
228
|
return new Map();
|
|
242
|
-
const output = await
|
|
229
|
+
const output = await executeGit(repository, ["cat-file", "--batch"], `${unique.join("\n")}\n`);
|
|
243
230
|
const objects = new Map();
|
|
244
231
|
let offset = 0;
|
|
245
232
|
for (const oid of unique) {
|
|
@@ -290,7 +277,7 @@ async function baseTreeEntries(repository, baseTree, changedPaths, nodePaths) {
|
|
|
290
277
|
const byPath = new Map();
|
|
291
278
|
if (baseTree === null)
|
|
292
279
|
return byPath;
|
|
293
|
-
const ancestry = parseTreeEntries(await
|
|
280
|
+
const ancestry = parseTreeEntries(await executeGit(repository, [
|
|
294
281
|
"ls-tree",
|
|
295
282
|
"-z",
|
|
296
283
|
"-t",
|
|
@@ -323,7 +310,7 @@ async function baseTreeEntries(repository, baseTree, changedPaths, nodePaths) {
|
|
|
323
310
|
return byPath;
|
|
324
311
|
}
|
|
325
312
|
async function writePreparedTrees(repository, prepared) {
|
|
326
|
-
const output = await
|
|
313
|
+
const output = await executeGit(repository, ["mktree", "--batch"], prepared.map(({ records }) => `${records}\n`).join(""));
|
|
327
314
|
const written = output.toString("ascii").trimEnd().split("\n");
|
|
328
315
|
if (written.length !== prepared.length) {
|
|
329
316
|
throw new GitPlumbingError({ stderr: output, status: null, message: "malformed mktree --batch output" });
|
|
@@ -364,7 +351,7 @@ async function writeCommitObject(input) {
|
|
|
364
351
|
const args = ["commit-tree", tree];
|
|
365
352
|
for (const parent of parents)
|
|
366
353
|
args.push("-p", parent);
|
|
367
|
-
const commit = (await
|
|
354
|
+
const commit = (await executeGit(repository, args, `${message}\n`, {
|
|
368
355
|
GIT_AUTHOR_NAME: actor,
|
|
369
356
|
GIT_AUTHOR_EMAIL: email,
|
|
370
357
|
GIT_COMMITTER_NAME: actor,
|
|
@@ -420,7 +407,7 @@ export async function updateRefsAtomically(repository, updates, assertions = [])
|
|
|
420
407
|
}
|
|
421
408
|
const lines = ["start", ...assertions.map(refAssertionLine), ...updates.map(refUpdateLine), "prepare", "commit", ""];
|
|
422
409
|
try {
|
|
423
|
-
await
|
|
410
|
+
await executeGit(repository, ["update-ref", "--stdin"], lines.join("\n"));
|
|
424
411
|
return { kind: "published" };
|
|
425
412
|
}
|
|
426
413
|
catch (error) {
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import type { SnapshotId } from "../core/facts/types.js";
|
|
2
|
+
import type { ContractId, SnapshotId } from "../core/facts/types.js";
|
|
3
3
|
import { type GitRepository } from "./process.js";
|
|
4
4
|
export type MaterializedScratchCandidate = Readonly<{
|
|
5
5
|
cwd: string;
|
|
6
|
-
dispose: () => Promise<WorktreeLeak | null>;
|
|
6
|
+
dispose: (retain?: boolean) => Promise<WorktreeLeak | null>;
|
|
7
7
|
}>;
|
|
8
8
|
export declare const worktreeLeakSchema: z.ZodObject<{
|
|
9
|
-
path: z.ZodString
|
|
9
|
+
path: z.ZodOptional<z.ZodString>;
|
|
10
10
|
diagnostic: z.ZodString;
|
|
11
11
|
}, z.core.$strict>;
|
|
12
12
|
export type WorktreeLeak = z.infer<typeof worktreeLeakSchema>;
|
|
13
13
|
type CollectableScratchRemoval = Readonly<{
|
|
14
14
|
path: string;
|
|
15
|
-
|
|
15
|
+
/** False only when Git removed the path and absence was confirmed; retained removals own a diagnostic. */
|
|
16
16
|
retained: boolean;
|
|
17
17
|
diagnostic?: string;
|
|
18
18
|
}>;
|
|
19
19
|
/** Remove only abandoned Verification scratch worktrees whose ownership locks are held. */
|
|
20
|
-
export declare function removeCollectableScratchWorktrees(repository: GitRepository, paths: Set<string
|
|
20
|
+
export declare function removeCollectableScratchWorktrees(repository: GitRepository, paths: Set<string>, terminalContract?: ContractId): Promise<readonly CollectableScratchRemoval[]>;
|
|
21
21
|
/** Materialize a disposable candidate worktree and own only its removal. */
|
|
22
|
-
export declare function materializeScratchCandidate(repository: GitRepository, candidate: SnapshotId): Promise<MaterializedScratchCandidate>;
|
|
22
|
+
export declare function materializeScratchCandidate(repository: GitRepository, candidate: SnapshotId, contract?: ContractId): Promise<MaterializedScratchCandidate>;
|
|
23
23
|
export {};
|
package/build/src/git/scratch.js
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { randomBytes } from "node:crypto";
|
|
3
|
-
import {
|
|
3
|
+
import { lstat, realpath, unlink } from "node:fs/promises";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { basename, dirname, join } from "node:path";
|
|
6
|
-
import { tryAcquireSqliteTransactionLock, } from "../coordination/sqlite-transaction-lock.js";
|
|
7
|
-
import { gitObjectIdForSnapshot } from "./identity.js";
|
|
8
|
-
import {
|
|
6
|
+
import { acquireSqliteTransactionLock, tryAcquireSqliteTransactionLock, } from "../coordination/sqlite-transaction-lock.js";
|
|
7
|
+
import { contractLocator, gitRefLocator, gitObjectIdForSnapshot } from "./identity.js";
|
|
8
|
+
import { executeGit } from "./process.js";
|
|
9
9
|
const SCRATCH_PREFIX = "keiyaku-v4-verify-";
|
|
10
10
|
const SCRATCH_ROOT = await realpath(tmpdir());
|
|
11
|
-
const SCRATCH_PATTERN = /^keiyaku-v4-verify-([0-9a-f]{24})$/;
|
|
12
|
-
|
|
11
|
+
const SCRATCH_PATTERN = /^keiyaku-v4-verify-([0-9a-f]{24}|[0-9a-f]{64}-[0-9a-f]{64})$/;
|
|
12
|
+
/** One bounded removal attempt per scratch; expiry is reported, never retried inside this call. */
|
|
13
|
+
const SCRATCH_REMOVAL_TIMEOUT_MS = 120_000;
|
|
14
|
+
export const worktreeLeakSchema = z.object({ path: z.string().optional(), diagnostic: z.string() }).strict();
|
|
13
15
|
function scratchPath() {
|
|
14
16
|
return join(SCRATCH_ROOT, `${SCRATCH_PREFIX}${randomBytes(12).toString("hex")}`);
|
|
15
17
|
}
|
|
18
|
+
function retainedScratchPath(repository, contract) {
|
|
19
|
+
return join(SCRATCH_ROOT, `${SCRATCH_PREFIX}${gitRefLocator(repository.commonDirectory)}-${contractLocator(contract)}`);
|
|
20
|
+
}
|
|
16
21
|
function ownershipLockPath(path) {
|
|
17
22
|
if (dirname(path) !== SCRATCH_ROOT)
|
|
18
23
|
return null;
|
|
@@ -25,69 +30,132 @@ async function removeOwnershipLock(lockPath) {
|
|
|
25
30
|
throw error;
|
|
26
31
|
});
|
|
27
32
|
}
|
|
28
|
-
async function collectableScratchWorktrees(paths) {
|
|
33
|
+
async function collectableScratchWorktrees(paths, terminalScratch) {
|
|
29
34
|
const collectable = [];
|
|
30
35
|
for (const path of paths) {
|
|
31
36
|
const lockPath = ownershipLockPath(path);
|
|
32
37
|
if (lockPath === null)
|
|
33
38
|
continue;
|
|
39
|
+
if (basename(path).length !== SCRATCH_PREFIX.length + 24 && path !== terminalScratch)
|
|
40
|
+
continue;
|
|
34
41
|
const lock = await tryAcquireSqliteTransactionLock({ path: lockPath, mode: "exclusive" });
|
|
35
42
|
if (lock !== null)
|
|
36
43
|
collectable.push({ path, lockPath, release: () => lock.close() });
|
|
37
44
|
}
|
|
38
45
|
return collectable;
|
|
39
46
|
}
|
|
40
|
-
|
|
47
|
+
/** Absence is ENOENT on the path entry itself: a dangling symlink is present residue, not a missing path. */
|
|
48
|
+
async function pathExists(path) {
|
|
49
|
+
try {
|
|
50
|
+
await lstat(path);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error.code === "ENOENT")
|
|
55
|
+
return false;
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function removeScratch(repository, path) {
|
|
60
|
+
const removal = AbortSignal.timeout(SCRATCH_REMOVAL_TIMEOUT_MS);
|
|
61
|
+
try {
|
|
62
|
+
const present = await pathExists(path);
|
|
63
|
+
await executeGit({ ...repository, signal: removal }, ["worktree", "remove", ...(present ? ["--force"] : []), path]);
|
|
64
|
+
return (await pathExists(path))
|
|
65
|
+
? { path, diagnostic: `Git reported scratch worktree removal but the path remains: ${path}` }
|
|
66
|
+
: null;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const original = error instanceof Error ? error.message : String(error);
|
|
70
|
+
return {
|
|
71
|
+
path,
|
|
72
|
+
diagnostic: removal.aborted
|
|
73
|
+
? `scratch worktree removal timed out after ${SCRATCH_REMOVAL_TIMEOUT_MS}ms: ${original}`
|
|
74
|
+
: original,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
41
78
|
/** Remove only abandoned Verification scratch worktrees whose ownership locks are held. */
|
|
42
|
-
export async function removeCollectableScratchWorktrees(repository, paths) {
|
|
79
|
+
export async function removeCollectableScratchWorktrees(repository, paths, terminalContract) {
|
|
43
80
|
const removals = [];
|
|
44
|
-
|
|
81
|
+
const terminalScratch = terminalContract === undefined ? undefined : retainedScratchPath(repository, terminalContract);
|
|
82
|
+
for (const scratch of await collectableScratchWorktrees(paths, terminalScratch)) {
|
|
45
83
|
let removed = false;
|
|
46
84
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
removed = true;
|
|
51
|
-
removals.push({ path: scratch.path, action: "removed", retained: false });
|
|
85
|
+
const leak = await removeScratch(repository, scratch.path);
|
|
86
|
+
if (leak !== null) {
|
|
87
|
+
removals.push({ path: scratch.path, retained: true, diagnostic: leak.diagnostic });
|
|
52
88
|
continue;
|
|
53
89
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
removed = true;
|
|
58
|
-
removals.push({ path: scratch.path, action: "removed", retained: false });
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
removals.push({
|
|
62
|
-
path: scratch.path,
|
|
63
|
-
action: "unchanged",
|
|
64
|
-
retained: true,
|
|
65
|
-
diagnostic: error instanceof Error ? error.message : String(error),
|
|
66
|
-
});
|
|
67
|
-
}
|
|
90
|
+
paths.delete(scratch.path);
|
|
91
|
+
removed = true;
|
|
92
|
+
removals.push({ path: scratch.path, retained: false });
|
|
68
93
|
}
|
|
69
94
|
finally {
|
|
70
95
|
scratch.release();
|
|
71
|
-
if (removed)
|
|
96
|
+
if (removed && scratch.path !== terminalScratch)
|
|
72
97
|
await removeOwnershipLock(scratch.lockPath);
|
|
73
98
|
}
|
|
74
99
|
}
|
|
75
100
|
return removals;
|
|
76
101
|
}
|
|
102
|
+
async function retainScratch(repository, cwd, contract) {
|
|
103
|
+
const retained = retainedScratchPath(repository, contract);
|
|
104
|
+
const lockPath = ownershipLockPath(retained);
|
|
105
|
+
if (lockPath === null)
|
|
106
|
+
throw new Error("scratch ownership lock path is invalid");
|
|
107
|
+
const { signal: _signal, ...retirementRepository } = repository;
|
|
108
|
+
const fallback = async (reason) => {
|
|
109
|
+
const ownLeak = await removeScratch(retirementRepository, cwd);
|
|
110
|
+
return {
|
|
111
|
+
...(ownLeak === null ? {} : { path: ownLeak.path }),
|
|
112
|
+
diagnostic: `failed Verification scratch could not be retained: ${reason}${ownLeak === null ? "" : `; ${ownLeak.diagnostic}`}`,
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
let lock;
|
|
116
|
+
try {
|
|
117
|
+
lock = await acquireSqliteTransactionLock({
|
|
118
|
+
path: lockPath,
|
|
119
|
+
mode: "exclusive",
|
|
120
|
+
timeoutMs: SCRATCH_REMOVAL_TIMEOUT_MS,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
return await fallback(`retained scratch busy: ${error instanceof Error ? error.message : String(error)}`);
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const replaced = await pathExists(retained);
|
|
128
|
+
if (replaced) {
|
|
129
|
+
const leak = await removeScratch(retirementRepository, retained);
|
|
130
|
+
if (leak !== null)
|
|
131
|
+
return await fallback(leak.diagnostic);
|
|
132
|
+
}
|
|
133
|
+
await executeGit(retirementRepository, ["worktree", "move", cwd, retained]);
|
|
134
|
+
return {
|
|
135
|
+
path: retained,
|
|
136
|
+
diagnostic: `failed Verification scratch retained for diagnosis${replaced ? " (replaced the previous retained scratch)" : ""}`,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
return await fallback(error instanceof Error ? error.message : String(error));
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
lock.close();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
77
146
|
/** Materialize a disposable candidate worktree and own only its removal. */
|
|
78
|
-
export async function materializeScratchCandidate(repository, candidate) {
|
|
147
|
+
export async function materializeScratchCandidate(repository, candidate, contract) {
|
|
79
148
|
const cwd = scratchPath();
|
|
80
149
|
const lockPath = ownershipLockPath(cwd);
|
|
81
150
|
if (lockPath === null)
|
|
82
151
|
throw new Error("scratch ownership lock path is invalid");
|
|
83
|
-
const ownership = await
|
|
152
|
+
const ownership = await acquireSqliteTransactionLock({
|
|
84
153
|
path: lockPath,
|
|
85
154
|
mode: "exclusive",
|
|
155
|
+
...(repository.signal === undefined ? {} : { signal: repository.signal }),
|
|
86
156
|
});
|
|
87
|
-
if (ownership === null)
|
|
88
|
-
throw new Error("new scratch ownership lock is unexpectedly held");
|
|
89
157
|
try {
|
|
90
|
-
await
|
|
158
|
+
await executeGit(repository, ["worktree", "add", "--detach", cwd, gitObjectIdForSnapshot(candidate)]);
|
|
91
159
|
}
|
|
92
160
|
catch (error) {
|
|
93
161
|
ownership.close();
|
|
@@ -97,26 +165,22 @@ export async function materializeScratchCandidate(repository, candidate) {
|
|
|
97
165
|
let disposed = false;
|
|
98
166
|
return {
|
|
99
167
|
cwd,
|
|
100
|
-
dispose: async () => {
|
|
168
|
+
dispose: async (retain = false) => {
|
|
101
169
|
if (disposed)
|
|
102
170
|
return null;
|
|
103
171
|
disposed = true;
|
|
104
|
-
let leak = null;
|
|
105
172
|
try {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
diagnostic: error instanceof Error ? error.message : String(error),
|
|
112
|
-
};
|
|
173
|
+
if (!retain)
|
|
174
|
+
return await removeScratch(repository, cwd);
|
|
175
|
+
if (contract === undefined)
|
|
176
|
+
return { path: cwd, diagnostic: "failed Verification scratch retained for diagnosis" };
|
|
177
|
+
return await retainScratch(repository, cwd, contract);
|
|
113
178
|
}
|
|
114
179
|
finally {
|
|
115
180
|
ownership.close();
|
|
116
|
-
if (
|
|
181
|
+
if (!(await pathExists(cwd)))
|
|
117
182
|
await removeOwnershipLock(lockPath);
|
|
118
183
|
}
|
|
119
|
-
return leak;
|
|
120
184
|
},
|
|
121
185
|
};
|
|
122
186
|
}
|
|
@@ -30,7 +30,7 @@ export declare const targetCheckoutLagSchema: z.ZodObject<{
|
|
|
30
30
|
diagnostic: z.ZodString;
|
|
31
31
|
}, z.core.$strict>;
|
|
32
32
|
type TargetCheckoutLag = z.infer<typeof targetCheckoutLagSchema>;
|
|
33
|
-
|
|
33
|
+
type TargetPlacementPhysicalResult = Readonly<{
|
|
34
34
|
effects: readonly TargetCheckoutEffect[];
|
|
35
35
|
lag: readonly TargetCheckoutLag[];
|
|
36
36
|
}>;
|
|
@@ -42,7 +42,7 @@ export type PreparedTargetPlacement = Readonly<{
|
|
|
42
42
|
target: RefOperation;
|
|
43
43
|
arms: readonly FollowArm[];
|
|
44
44
|
}>;
|
|
45
|
-
|
|
45
|
+
type TargetPlacementPreparation = Readonly<{
|
|
46
46
|
kind: "prepared";
|
|
47
47
|
placement: PreparedTargetPlacement;
|
|
48
48
|
}> | Readonly<{
|
|
@@ -63,16 +63,16 @@ export type TargetPlacementChanges = Readonly<{
|
|
|
63
63
|
/** Only immutable commit contents are prepared outside the publication seat. */
|
|
64
64
|
export declare function prepareTargetPlacementChanges(repository: GitRepository, target: RefOperation): Promise<TargetPlacementChanges>;
|
|
65
65
|
export declare function acquireTargetPlacementFence(repository: GitRepository, target: string): Promise<HeldSqliteTransactionLock>;
|
|
66
|
-
|
|
66
|
+
type TargetedContractCoordinates = ContractState["coordinates"] & Readonly<{
|
|
67
67
|
target: string;
|
|
68
68
|
}>;
|
|
69
|
-
|
|
69
|
+
type TargetPlacementObservationInput = Readonly<{
|
|
70
70
|
contractId: ContractId;
|
|
71
71
|
coordinates: TargetedContractCoordinates;
|
|
72
72
|
predecessor: SnapshotId;
|
|
73
73
|
candidate: SnapshotId;
|
|
74
74
|
}>;
|
|
75
|
-
|
|
75
|
+
type TargetPlacementObservation = Readonly<{
|
|
76
76
|
kind: "ready";
|
|
77
77
|
arms: readonly FollowArm[];
|
|
78
78
|
}> | Readonly<{
|
|
@@ -6,7 +6,7 @@ import { resolve } from "node:path";
|
|
|
6
6
|
import { acquireSqliteTransactionLock, } from "../coordination/sqlite-transaction-lock.js";
|
|
7
7
|
import { gitObjectId, gitObjectIdForSnapshot, gitRefLocator, mintSnapshotId } from "./identity.js";
|
|
8
8
|
import { commonGitDirectory, decodeGitNameOnly, readRef, registeredWorktrees } from "./repository.js";
|
|
9
|
-
import { consumeGitStdout, GitPlumbingError,
|
|
9
|
+
import { consumeGitStdout, GitPlumbingError, executeGit } from "./process.js";
|
|
10
10
|
import { captureWorkspaceTree } from "./workspace.js";
|
|
11
11
|
export const checkoutNotFollowableRefusalSchema = z
|
|
12
12
|
.object({
|
|
@@ -42,13 +42,15 @@ function diagnostic(error) {
|
|
|
42
42
|
return error instanceof Error ? error.message : String(error);
|
|
43
43
|
}
|
|
44
44
|
async function gitPaths(repository, path, args) {
|
|
45
|
-
return [...new Set(decodeGitNameOnly(await
|
|
45
|
+
return [...new Set(decodeGitNameOnly(await executeGit(repository, ["-C", path, ...args])))].sort();
|
|
46
46
|
}
|
|
47
47
|
function literalPath(path) {
|
|
48
48
|
return `:(literal)${path}`;
|
|
49
49
|
}
|
|
50
50
|
async function commitTree(repository, snapshot) {
|
|
51
|
-
return gitObjectId((await
|
|
51
|
+
return gitObjectId((await executeGit(repository, ["show", "-s", "--format=%T", gitObjectIdForSnapshot(snapshot)]))
|
|
52
|
+
.toString("utf8")
|
|
53
|
+
.trim(), "commit tree");
|
|
52
54
|
}
|
|
53
55
|
export async function observedTreeEqualsCandidate(repository, observed, snapshot) {
|
|
54
56
|
if (observed === null)
|
|
@@ -60,7 +62,7 @@ function checkoutRefusal(contractId, target, path, reason, paths) {
|
|
|
60
62
|
}
|
|
61
63
|
/** Only immutable commit contents are prepared outside the publication seat. */
|
|
62
64
|
export async function prepareTargetPlacementChanges(repository, target) {
|
|
63
|
-
const records = (await
|
|
65
|
+
const records = (await executeGit(repository, [
|
|
64
66
|
"diff",
|
|
65
67
|
"--raw",
|
|
66
68
|
"--no-renames",
|
|
@@ -175,27 +177,10 @@ async function untrackedRefusalWithinScopes(input, scopes) {
|
|
|
175
177
|
const first = directories.find((scope) => found.has(scope.path));
|
|
176
178
|
return first === undefined ? null : checkoutRefusal(contractId, target, path, "untracked", [first.path]);
|
|
177
179
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
"--name-only",
|
|
183
|
-
"-z",
|
|
184
|
-
tree,
|
|
185
|
-
"--",
|
|
186
|
-
...paths.map(literalPath),
|
|
187
|
-
])).length === 0);
|
|
188
|
-
}
|
|
189
|
-
async function workspaceMatchesTreeOnPaths(repository, path, tree, workspaceTree, paths) {
|
|
190
|
-
return ((await gitPaths(repository, path, [
|
|
191
|
-
"diff",
|
|
192
|
-
"--name-only",
|
|
193
|
-
"-z",
|
|
194
|
-
tree,
|
|
195
|
-
workspaceTree,
|
|
196
|
-
"--",
|
|
197
|
-
...paths.map(literalPath),
|
|
198
|
-
])).length === 0);
|
|
180
|
+
/** Compare the index or a workspace tree against another tree over the given paths. */
|
|
181
|
+
async function matchesTreeOnPaths(repository, path, command, trees, paths) {
|
|
182
|
+
const args = [...command, "--name-only", "-z", ...trees, "--", ...paths.map(literalPath)];
|
|
183
|
+
return (await gitPaths(repository, path, args)).length === 0;
|
|
199
184
|
}
|
|
200
185
|
/**
|
|
201
186
|
* A checkout that git cannot carry is judged by the physical follow, which records its own lag.
|
|
@@ -207,7 +192,7 @@ async function ordinaryPrecheck(repository, contractId, target, path, changes) {
|
|
|
207
192
|
const candidate = gitObjectIdForSnapshot(target.newOid);
|
|
208
193
|
const observation = { repository, contractId, target, path, predecessor, candidate, changes };
|
|
209
194
|
try {
|
|
210
|
-
await
|
|
195
|
+
await executeGit(repository, ["-C", path, "read-tree", "--dry-run", "-m", "-u", predecessor, candidate]);
|
|
211
196
|
}
|
|
212
197
|
catch (error) {
|
|
213
198
|
if (!(error instanceof GitPlumbingError) || repository.signal?.aborted === true)
|
|
@@ -311,7 +296,7 @@ export async function followTargetPlacement(repository, prepared, onPhysical) {
|
|
|
311
296
|
for (const arm of prepared.arms) {
|
|
312
297
|
const beforeEffects = effects.length, beforeLag = lag.length;
|
|
313
298
|
try {
|
|
314
|
-
await
|
|
299
|
+
await executeGit(repository, ["-C", arm.path, "read-tree", "-m", "-u", predecessor, candidate]);
|
|
315
300
|
effects.push({ kind: "target-checkout", path: arm.path, target: prepared.target.target, action: "followed" });
|
|
316
301
|
}
|
|
317
302
|
catch (error) {
|
|
@@ -337,15 +322,15 @@ async function classifyCheckout(input) {
|
|
|
337
322
|
if (changedPaths.length === 0)
|
|
338
323
|
return { kind: "complete" };
|
|
339
324
|
const workspaceTree = (await captureWorkspaceTree(repository, path)).tree;
|
|
340
|
-
const candidateIndex = await
|
|
341
|
-
const candidateWorkspace = await
|
|
325
|
+
const candidateIndex = await matchesTreeOnPaths(repository, path, ["diff-index", "--cached"], [candidateTree], changedPaths);
|
|
326
|
+
const candidateWorkspace = await matchesTreeOnPaths(repository, path, ["diff"], [candidateTree, workspaceTree], changedPaths);
|
|
342
327
|
if (candidateIndex && candidateWorkspace)
|
|
343
328
|
return { kind: "complete" };
|
|
344
|
-
const predecessorIndex = await
|
|
329
|
+
const predecessorIndex = await matchesTreeOnPaths(repository, path, ["diff-index", "--cached"], [predecessorTree], changedPaths);
|
|
345
330
|
if (predecessorIndex && candidateWorkspace)
|
|
346
331
|
return { kind: "recoverable", action: "index-merge" };
|
|
347
332
|
return !predecessorIndex ||
|
|
348
|
-
!(await
|
|
333
|
+
!(await matchesTreeOnPaths(repository, path, ["diff"], [predecessorTree, workspaceTree], changedPaths))
|
|
349
334
|
? { kind: "retained" }
|
|
350
335
|
: { kind: "recoverable", action: "worktree-merge" };
|
|
351
336
|
}
|
|
@@ -365,7 +350,7 @@ async function recoverCheckout(input) {
|
|
|
365
350
|
return "retained";
|
|
366
351
|
const { repository, path, predecessor, candidate } = input;
|
|
367
352
|
if (classified.action === "index-merge") {
|
|
368
|
-
await
|
|
353
|
+
await executeGit(repository, [
|
|
369
354
|
"-C",
|
|
370
355
|
path,
|
|
371
356
|
"read-tree",
|
|
@@ -376,7 +361,7 @@ async function recoverCheckout(input) {
|
|
|
376
361
|
]);
|
|
377
362
|
return "recovered";
|
|
378
363
|
}
|
|
379
|
-
await
|
|
364
|
+
await executeGit(repository, [
|
|
380
365
|
"-C",
|
|
381
366
|
path,
|
|
382
367
|
"read-tree",
|
|
@@ -4,7 +4,7 @@ import type { ActorId, ContractCoordinates, ContractId, SnapshotId } from "../co
|
|
|
4
4
|
import { type GitObjectId } from "./identity.js";
|
|
5
5
|
import { type GitRepository } from "./process.js";
|
|
6
6
|
import { captureWorkspaceTree } from "./workspace.js";
|
|
7
|
-
|
|
7
|
+
type TenderCaptureCoordinates = Readonly<{
|
|
8
8
|
contractId: ContractId;
|
|
9
9
|
coordinates: ContractCoordinates;
|
|
10
10
|
place?: string;
|
|
@@ -23,7 +23,7 @@ export declare const unmergedPathsRefusalSchema: z.ZodObject<{
|
|
|
23
23
|
contractId: z.ZodPipe<z.ZodString, z.ZodTransform<ContractId, string>>;
|
|
24
24
|
paths: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
25
25
|
}, z.core.$strict>;
|
|
26
|
-
|
|
26
|
+
type TenderCaptureRefusal = WorktreeMissingRefusal | z.infer<typeof unmergedPathsRefusalSchema>;
|
|
27
27
|
export declare const workspaceDirtyDeltaSchema: z.ZodObject<{
|
|
28
28
|
staged: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
29
29
|
unstaged: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
@@ -81,6 +81,10 @@ export declare function prepareDeliveryCommitMetadata(repository: GitRepository,
|
|
|
81
81
|
actor?: ActorId;
|
|
82
82
|
message?: string;
|
|
83
83
|
}>): Promise<DeliveryCommitMetadata>;
|
|
84
|
+
/** The Git identity environment for one delivery snapshot commit. */
|
|
85
|
+
export declare function deliveryEnvironment(commit: DeliveryCommitMetadata): NodeJS.ProcessEnv;
|
|
86
|
+
/** Materialize one delivery snapshot commit over the given parents. */
|
|
87
|
+
export declare function materializeSnapshotCommit(repository: GitRepository, tree: GitObjectId, parents: readonly SnapshotId[], message: string | Uint8Array, environment: NodeJS.ProcessEnv): Promise<SnapshotId>;
|
|
84
88
|
/** Materialize the tender tree when it contains admitted dirty workspace bytes. */
|
|
85
89
|
export declare function materializeTenderSnapshot(repository: GitRepository, tender: TenderCapture, commit: DeliveryCommitMetadata): Promise<SnapshotId>;
|
|
86
90
|
export {};
|