@astrosheep/keiyaku 4.0.1 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -5
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -35
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +98 -58
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +152 -53
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +23 -14
- package/build/src/akuma/akuma.js +120 -104
- package/build/src/akuma/archetype.d.ts +7 -6
- package/build/src/akuma/archetype.js +68 -41
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +408 -213
- package/build/src/akuma/heart/facts.d.ts +25 -34
- package/build/src/akuma/heart/facts.js +18 -7
- package/build/src/akuma/heart/index.d.ts +39 -42
- package/build/src/akuma/heart/index.js +134 -93
- package/build/src/akuma/heart/rows.d.ts +9 -31
- package/build/src/akuma/heart/rows.js +26 -44
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +7 -15
- package/build/src/akuma/heart/soul.d.ts +8 -0
- package/build/src/akuma/heart/soul.js +136 -0
- package/build/src/akuma/heart/storage.d.ts +28 -14
- package/build/src/akuma/heart/storage.js +86 -26
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +6 -1
- package/build/src/akuma/index.js +6 -0
- package/build/src/akuma/projection.d.ts +117 -38
- package/build/src/akuma/projection.js +208 -97
- package/build/src/akuma/provider-recipe.d.ts +24 -0
- package/build/src/akuma/provider-recipe.js +100 -0
- package/build/src/akuma/provider.d.ts +12 -4
- package/build/src/akuma/provider.js +117 -70
- package/build/src/akuma/providers/acp/core.d.ts +19 -0
- package/build/src/akuma/providers/acp/core.js +159 -0
- package/build/src/akuma/providers/acp/events.d.ts +20 -0
- package/build/src/akuma/providers/acp/events.js +73 -0
- package/build/src/akuma/providers/acp/index.d.ts +12 -0
- package/build/src/akuma/providers/acp/index.js +94 -0
- package/build/src/akuma/providers/claude/events.js +66 -13
- package/build/src/akuma/providers/claude/index.d.ts +2 -1
- package/build/src/akuma/providers/claude/index.js +35 -21
- package/build/src/akuma/providers/codex-app-server/events.js +4 -1
- package/build/src/akuma/providers/codex-app-server/index.d.ts +3 -3
- package/build/src/akuma/providers/codex-app-server/index.js +24 -31
- package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
- package/build/src/akuma/providers/grok-build/index.js +70 -0
- package/build/src/akuma/providers/index.d.ts +5 -3
- package/build/src/akuma/providers/index.js +24 -59
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +40 -34
- package/build/src/akuma/providers/opencode-sdk/events.js +220 -101
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +3 -2
- package/build/src/akuma/providers/opencode-sdk/index.js +233 -128
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +11 -26
- package/build/src/akuma/providers/opencode-sdk/session.js +10 -9
- package/build/src/akuma/providers/pi/events.js +49 -11
- package/build/src/akuma/providers/pi/index.d.ts +1 -1
- package/build/src/akuma/providers/pi/index.js +50 -21
- package/build/src/akuma/publication.d.ts +3 -3
- package/build/src/akuma/publication.js +28 -40
- package/build/src/akuma/requests.d.ts +9 -7
- package/build/src/akuma/requests.js +92 -65
- package/build/src/alias/index.d.ts +2 -2
- package/build/src/alias/index.js +10 -10
- package/build/src/body/decode.js +7 -1
- package/build/src/body/region.d.ts +2 -0
- package/build/src/body/region.js +77 -7
- package/build/src/cli/accepted.d.ts +17 -13
- package/build/src/cli/accepted.js +72 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +4 -3
- package/build/src/cli/commands/akuma-invoke.js +14 -9
- package/build/src/cli/commands/akuma.d.ts +13 -3
- package/build/src/cli/commands/akuma.js +67 -34
- package/build/src/cli/commands/contract.d.ts +18 -5
- package/build/src/cli/commands/contract.js +9 -3
- package/build/src/cli/commands/task-invoke.d.ts +17 -4
- package/build/src/cli/commands/task-invoke.js +43 -20
- package/build/src/cli/commands/task-query.d.ts +5 -0
- package/build/src/cli/commands/task-query.js +247 -0
- package/build/src/cli/commands/task.d.ts +3 -1
- package/build/src/cli/commands/task.js +51 -13
- package/build/src/cli/coordinates.d.ts +18 -0
- package/build/src/cli/coordinates.js +120 -0
- package/build/src/cli/draft.d.ts +8 -0
- package/build/src/cli/draft.js +96 -0
- package/build/src/cli/invoke.d.ts +4 -3
- package/build/src/cli/invoke.js +160 -179
- package/build/src/cli/main.js +34 -6
- package/build/src/cli/parse.d.ts +9 -2
- package/build/src/cli/parse.js +29 -7
- package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
- package/build/src/cli/render/akuma-tool-command.js +144 -0
- package/build/src/cli/render/akuma-tool.d.ts +2 -2
- package/build/src/cli/render/akuma-tool.js +30 -4
- package/build/src/cli/render/akuma.d.ts +1 -0
- package/build/src/cli/render/akuma.js +211 -116
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +192 -79
- package/build/src/cli/render/kanshi.js +263 -168
- package/build/src/cli/render/receipt.d.ts +19 -0
- package/build/src/cli/render/receipt.js +106 -0
- package/build/src/cli/render/refusal.d.ts +16 -2
- package/build/src/cli/render/refusal.js +88 -20
- package/build/src/cli/render/region.d.ts +2 -0
- package/build/src/cli/render/region.js +17 -0
- package/build/src/cli/render/task.d.ts +2 -1
- package/build/src/cli/render/task.js +223 -60
- package/build/src/cli/render/terminal.d.ts +7 -0
- package/build/src/cli/render/terminal.js +46 -0
- package/build/src/cli/render/text.js +6 -3
- package/build/src/cli/result.d.ts +115 -20
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +6 -5
- package/build/src/contract-worktree.js +95 -57
- package/build/src/coordination/durable-file.d.ts +4 -3
- package/build/src/coordination/durable-file.js +29 -25
- package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
- package/build/src/coordination/sqlite-transaction-lock.js +22 -5
- package/build/src/core/facts/fold.js +1 -6
- package/build/src/core/facts/gate.d.ts +1 -0
- package/build/src/core/facts/gate.js +1 -0
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +0 -11
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +1 -7
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +4 -1
- package/build/src/dispatch/index.d.ts +2 -2
- package/build/src/dispatch/index.js +17 -17
- package/build/src/git/admission.d.ts +1 -1
- package/build/src/git/admission.js +11 -11
- package/build/src/git/hooks.js +13 -13
- package/build/src/git/integration.d.ts +14 -15
- package/build/src/git/integration.js +80 -44
- package/build/src/git/observe.d.ts +5 -3
- package/build/src/git/observe.js +18 -12
- package/build/src/git/read-observation.js +9 -9
- package/build/src/git/reconcile.d.ts +2 -0
- package/build/src/git/reconcile.js +138 -95
- package/build/src/git/repository.d.ts +27 -19
- package/build/src/git/repository.js +155 -83
- package/build/src/git/scratch.d.ts +7 -3
- package/build/src/git/scratch.js +44 -37
- package/build/src/git/target-placement.d.ts +40 -4
- package/build/src/git/target-placement.js +221 -101
- package/build/src/git/tender.d.ts +6 -5
- package/build/src/git/tender.js +24 -43
- package/build/src/git/terminal-seal.d.ts +1 -1
- package/build/src/git/terminal-seal.js +7 -5
- package/build/src/git/workspace.d.ts +36 -4
- package/build/src/git/workspace.js +53 -18
- package/build/src/identity/selector.js +1 -1
- package/build/src/index.d.ts +3 -3
- package/build/src/index.js +1 -1
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +2 -1
- package/build/src/kanshi/read.js +118 -27
- package/build/src/kanshi/report.d.ts +50 -0
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +32 -0
- package/build/src/library/address.d.ts +12 -3
- package/build/src/library/address.js +77 -46
- package/build/src/library/akuma-creation.d.ts +6 -1
- package/build/src/library/akuma-creation.js +86 -13
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.js +4 -4
- package/build/src/library/catalog.d.ts +1 -1
- package/build/src/library/catalog.js +5 -8
- package/build/src/library/contract.d.ts +5 -6
- package/build/src/library/contract.js +11 -35
- package/build/src/library/delivery.d.ts +2 -1
- package/build/src/library/fleet.d.ts +2 -2
- package/build/src/library/fleet.js +35 -71
- package/build/src/library/keiyaku.d.ts +3 -2
- package/build/src/library/keiyaku.js +1 -0
- package/build/src/library/mutation.d.ts +7 -6
- package/build/src/library/mutation.js +23 -25
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/region.d.ts +12 -0
- package/build/src/library/region.js +15 -1
- package/build/src/library/repo.d.ts +4 -16
- package/build/src/library/repo.js +13 -38
- package/build/src/protocol/attempt.js +6 -6
- package/build/src/protocol/bind.js +4 -4
- package/build/src/protocol/intent.d.ts +15 -2
- package/build/src/protocol/intent.js +21 -6
- package/build/src/protocol/operations.d.ts +73 -22
- package/build/src/protocol/operations.js +292 -88
- package/build/src/protocol/outcome.d.ts +9 -3
- package/build/src/protocol/outcome.js +3 -1
- package/build/src/protocol/placement.d.ts +15 -4
- package/build/src/protocol/placement.js +58 -25
- package/build/src/protocol/read/status.d.ts +8 -1
- package/build/src/protocol/read/status.js +61 -14
- package/build/src/runtime/proc/line-rpc.d.ts +3 -8
- package/build/src/runtime/proc/line-rpc.js +16 -43
- package/build/src/runtime/proc/run.d.ts +15 -29
- package/build/src/runtime/proc/run.js +113 -105
- package/build/src/runtime/proc/stdio.d.ts +18 -0
- package/build/src/runtime/proc/stdio.js +58 -0
- package/build/src/settings.d.ts +2 -2
- package/build/src/settings.js +8 -8
- package/build/src/settlement/fence.d.ts +0 -4
- package/build/src/settlement/fence.js +0 -9
- package/build/src/settlement/holder.d.ts +11 -1
- package/build/src/settlement/holder.js +25 -0
- package/build/src/settlement/settle.d.ts +1 -1
- package/build/src/settlement/settle.js +52 -89
- package/build/src/task/board.d.ts +3 -3
- package/build/src/task/board.js +6 -9
- package/build/src/task/compose.d.ts +1 -1
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +14 -14
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +19 -7
- package/build/src/task/index.js +42 -23
- package/build/src/task/operations.d.ts +15 -9
- package/build/src/task/operations.js +78 -48
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +2 -2
- package/build/src/task/store.js +40 -25
- package/build/src/verification/execution.d.ts +4 -2
- package/build/src/verification/execution.js +9 -5
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +13 -2
- package/build/src/world.js +81 -48
- package/package.json +3 -2
- package/build/src/protocol/read/audit.d.ts +0 -31
- package/build/src/protocol/read/audit.js +0 -55
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { access, mkdir } from "node:fs/promises";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { acquireSqliteTransactionLock } from "../coordination/sqlite-transaction-lock.js";
|
|
4
4
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
@@ -7,33 +7,51 @@ import { contractLocator, contractPhysicalName, gitObjectIdForSnapshot, mintSnap
|
|
|
7
7
|
import { observeContractAt } from "./observe.js";
|
|
8
8
|
import { acquireTargetPlacementFence, recoverTargetPlacement, } from "./target-placement.js";
|
|
9
9
|
import { runCreateHooks, runDestroyHooks, } from "./hooks.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { worktreePath } from "./workspace.js";
|
|
11
|
+
import { collectableScratchWorktrees } from "./scratch.js";
|
|
12
12
|
import { terminalSealExpectations as decodeTerminalSealExpectations, terminalSealSnapshots, unsealedBytes, } from "./terminal-seal.js";
|
|
13
|
-
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const pathExists = (path) => access(path).then(() => true, () => false);
|
|
14
|
+
function deliveryRefFor(contract) {
|
|
15
|
+
return `${DELIVERY_REF_NAMESPACE}/${contractPhysicalName(contract)}`;
|
|
16
|
+
}
|
|
17
|
+
function candidatePinRefFor(contract) {
|
|
18
|
+
return `${CANDIDATE_PIN_REF_NAMESPACE}/${contractPhysicalName(contract)}`;
|
|
19
|
+
}
|
|
20
|
+
function missingPlaceLag(repository) {
|
|
21
|
+
return {
|
|
22
|
+
kind: "reconcile-failed",
|
|
23
|
+
stage: "effect",
|
|
24
|
+
diagnostic: `managed Contract is unappointed: ${join(repository.commonDirectory, "keiyaku", "places.json")}`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function updateRef(repository, ref, desired) {
|
|
28
|
+
const before = await readRef(repository, ref);
|
|
17
29
|
if (before === desired)
|
|
18
30
|
return { kind: "ref", name: ref, action: "unchanged", before, after: desired };
|
|
19
|
-
runGit(repository, [
|
|
31
|
+
await runGit(repository, [
|
|
32
|
+
"update-ref",
|
|
33
|
+
"--no-deref",
|
|
34
|
+
ref,
|
|
35
|
+
gitObjectIdForSnapshot(desired),
|
|
36
|
+
before ?? "0".repeat(desired.length),
|
|
37
|
+
]);
|
|
20
38
|
return { kind: "ref", name: ref, action: before === null ? "created" : "updated", before, after: desired };
|
|
21
39
|
}
|
|
22
|
-
function removeRef(repository, ref) {
|
|
23
|
-
const before = readRef(repository, ref);
|
|
40
|
+
async function removeRef(repository, ref) {
|
|
41
|
+
const before = await readRef(repository, ref);
|
|
24
42
|
if (before === null)
|
|
25
43
|
return { kind: "ref", name: ref, action: "unchanged", before: null, after: null };
|
|
26
|
-
runGit(repository, ["update-ref", "--no-deref", "-d", ref, before]);
|
|
44
|
+
await runGit(repository, ["update-ref", "--no-deref", "-d", ref, before]);
|
|
27
45
|
return { kind: "ref", name: ref, action: "removed", before, after: null };
|
|
28
46
|
}
|
|
29
|
-
function removeRefWithCustody(repository, ref, custodian, expectedCustodian) {
|
|
30
|
-
const before = readRef(repository, ref);
|
|
47
|
+
async function removeRefWithCustody(repository, ref, custodian, expectedCustodian) {
|
|
48
|
+
const before = await readRef(repository, ref);
|
|
31
49
|
if (before === null)
|
|
32
50
|
return { kind: "ref", name: ref, action: "unchanged", before: null, after: null };
|
|
33
|
-
if (readRef(repository, custodian) !== expectedCustodian) {
|
|
51
|
+
if (await readRef(repository, custodian) !== expectedCustodian) {
|
|
34
52
|
return { kind: "ref", name: ref, action: "unchanged", before, after: before };
|
|
35
53
|
}
|
|
36
|
-
runGit(repository, ["update-ref", "--stdin", "--no-deref"], [
|
|
54
|
+
await runGit(repository, ["update-ref", "--stdin", "--no-deref"], [
|
|
37
55
|
"start",
|
|
38
56
|
`verify ${custodian} ${gitObjectIdForSnapshot(expectedCustodian)}`,
|
|
39
57
|
`delete ${ref} ${before}`,
|
|
@@ -43,8 +61,8 @@ function removeRefWithCustody(repository, ref, custodian, expectedCustodian) {
|
|
|
43
61
|
].join("\n"));
|
|
44
62
|
return { kind: "ref", name: ref, action: "removed", before, after: null };
|
|
45
63
|
}
|
|
46
|
-
function acquireWorktreeTopology(repository) {
|
|
47
|
-
return { paths: new Set(registeredWorktreePaths(repository)) };
|
|
64
|
+
async function acquireWorktreeTopology(repository) {
|
|
65
|
+
return { paths: new Set(await registeredWorktreePaths(repository)) };
|
|
48
66
|
}
|
|
49
67
|
function fromPrimaryWorktree(repository) {
|
|
50
68
|
return { ...repository, effectiveCwd: repository.primaryWorktree };
|
|
@@ -64,32 +82,36 @@ function reconcileLockPath(repository, contract) {
|
|
|
64
82
|
const locator = contractLocator(contract);
|
|
65
83
|
return join(commonGitDirectory(repository), "keiyaku", "locks", "reconcile", locator.slice(0, 2), `${locator.slice(2)}.sqlite`);
|
|
66
84
|
}
|
|
67
|
-
function worktree(repository, topology, path, desired) {
|
|
85
|
+
async function worktree(repository, topology, path, desired) {
|
|
68
86
|
const registered = topology.paths.has(path);
|
|
69
|
-
if (registered &&
|
|
87
|
+
if (registered && await pathExists(path))
|
|
70
88
|
return { kind: "worktree", path, action: "unchanged" };
|
|
71
89
|
if (registered) {
|
|
72
|
-
runGit(repository, ["worktree", "remove", path]);
|
|
90
|
+
await runGit(repository, ["worktree", "remove", path]);
|
|
73
91
|
topology.paths.delete(path);
|
|
74
92
|
}
|
|
75
|
-
if (
|
|
93
|
+
if (await pathExists(path))
|
|
76
94
|
throw new Error(`delivery worktree path is occupied: ${path}`);
|
|
77
|
-
|
|
78
|
-
runGit(repository, ["worktree", "add", "--detach", path, gitObjectIdForSnapshot(desired)]);
|
|
95
|
+
await mkdir(dirname(path), { recursive: true });
|
|
96
|
+
await runGit(repository, ["worktree", "add", "--detach", path, gitObjectIdForSnapshot(desired)]);
|
|
79
97
|
topology.paths.add(path);
|
|
80
98
|
return { kind: "worktree", path, action: "created" };
|
|
81
99
|
}
|
|
82
|
-
function removeWorktree(repository, topology, path, force = false) {
|
|
100
|
+
async function removeWorktree(repository, topology, path, force = false) {
|
|
83
101
|
const registered = topology.paths.has(path);
|
|
84
|
-
if (!registered)
|
|
85
|
-
return {
|
|
86
|
-
|
|
87
|
-
|
|
102
|
+
if (!registered) {
|
|
103
|
+
return {
|
|
104
|
+
effect: { kind: "worktree", path, action: "unchanged" },
|
|
105
|
+
retained: await pathExists(path),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (!await pathExists(path)) {
|
|
109
|
+
await runGit(repository, ["worktree", "remove", path]);
|
|
88
110
|
topology.paths.delete(path);
|
|
89
111
|
return { effect: { kind: "worktree", path, action: "removed" }, retained: false };
|
|
90
112
|
}
|
|
91
113
|
try {
|
|
92
|
-
runGit(repository, ["worktree", "remove", ...(force ? ["--force"] : []), path]);
|
|
114
|
+
await runGit(repository, ["worktree", "remove", ...(force ? ["--force"] : []), path]);
|
|
93
115
|
}
|
|
94
116
|
catch {
|
|
95
117
|
return { effect: { kind: "worktree", path, action: "unchanged" }, retained: true };
|
|
@@ -97,19 +119,24 @@ function removeWorktree(repository, topology, path, force = false) {
|
|
|
97
119
|
topology.paths.delete(path);
|
|
98
120
|
return { effect: { kind: "worktree", path, action: "removed" }, retained: false };
|
|
99
121
|
}
|
|
100
|
-
function
|
|
101
|
-
for (const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
122
|
+
async function removeCollectableScratch(repository, topology, effects, lag) {
|
|
123
|
+
for (const scratch of await collectableScratchWorktrees(topology.paths)) {
|
|
124
|
+
try {
|
|
125
|
+
const removal = await removeWorktree(repository, topology, scratch.path, true);
|
|
126
|
+
effects.push(removal.effect);
|
|
127
|
+
if (removal.retained)
|
|
128
|
+
lag.push({ kind: "worktree-retained", path: scratch.path });
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
scratch.release();
|
|
132
|
+
}
|
|
106
133
|
}
|
|
107
134
|
}
|
|
108
|
-
function refRows(repository) {
|
|
109
|
-
const output = runGit(repository, [
|
|
135
|
+
async function refRows(repository) {
|
|
136
|
+
const output = (await runGit(repository, [
|
|
110
137
|
"for-each-ref",
|
|
111
138
|
"--format=%(refname)%00%(objectname)",
|
|
112
|
-
]).toString("utf8");
|
|
139
|
+
])).toString("utf8");
|
|
113
140
|
if (output.length === 0)
|
|
114
141
|
return [];
|
|
115
142
|
return output.trimEnd().split("\n").map((row) => {
|
|
@@ -119,12 +146,12 @@ function refRows(repository) {
|
|
|
119
146
|
return { ref, oid };
|
|
120
147
|
});
|
|
121
148
|
}
|
|
122
|
-
function snapshotCustodian(repository, snapshot) {
|
|
123
|
-
for (const row of refRows(repository)) {
|
|
149
|
+
async function snapshotCustodian(repository, snapshot) {
|
|
150
|
+
for (const row of await refRows(repository)) {
|
|
124
151
|
if (isKeiyakuOwnedRef(row.ref))
|
|
125
152
|
continue;
|
|
126
153
|
try {
|
|
127
|
-
runGit(repository, ["merge-base", "--is-ancestor", gitObjectIdForSnapshot(snapshot), row.oid]);
|
|
154
|
+
await runGit(repository, ["merge-base", "--is-ancestor", gitObjectIdForSnapshot(snapshot), row.oid]);
|
|
128
155
|
return { ref: row.ref, oid: mintSnapshotId(row.oid) };
|
|
129
156
|
}
|
|
130
157
|
catch (error) {
|
|
@@ -149,7 +176,7 @@ async function reconcileTargetCheckouts(repository, state) {
|
|
|
149
176
|
let result;
|
|
150
177
|
let exceptional;
|
|
151
178
|
try {
|
|
152
|
-
const recovered = recoverTargetPlacement(repository, state);
|
|
179
|
+
const recovered = await recoverTargetPlacement(repository, state);
|
|
153
180
|
result = complete(recovered.effects, recovered.lag);
|
|
154
181
|
}
|
|
155
182
|
catch (error) {
|
|
@@ -173,23 +200,23 @@ async function reconcileTargetCheckouts(repository, state) {
|
|
|
173
200
|
result = failed("effect", releaseFailure, result.effects, result.lag);
|
|
174
201
|
return result;
|
|
175
202
|
}
|
|
176
|
-
function reconcileHereWorkspaceRefs({ repository }, state, { effects, lag }) {
|
|
203
|
+
async function reconcileHereWorkspaceRefs({ repository }, state, { effects, lag }) {
|
|
177
204
|
const pin = candidatePinRefFor(state.id);
|
|
178
205
|
if (state.terminal) {
|
|
179
206
|
if (state.delivery === null)
|
|
180
|
-
effects.push(removeRef(repository, pin));
|
|
207
|
+
effects.push(await removeRef(repository, pin));
|
|
181
208
|
else {
|
|
182
209
|
const integration = state.delivery.data.integration.snapshot;
|
|
183
|
-
const custodian = snapshotCustodian(repository, integration);
|
|
184
|
-
effects.push(custodian === null
|
|
185
|
-
? updateRef(repository, pin, integration)
|
|
186
|
-
: removeRefWithCustody(repository, pin, custodian.ref, custodian.oid));
|
|
210
|
+
const custodian = await snapshotCustodian(repository, integration);
|
|
211
|
+
effects.push(await (custodian === null
|
|
212
|
+
? await updateRef(repository, pin, integration)
|
|
213
|
+
: await removeRefWithCustody(repository, pin, custodian.ref, custodian.oid)));
|
|
187
214
|
}
|
|
188
215
|
}
|
|
189
216
|
else if (state.bound) {
|
|
190
|
-
effects.push(state.delivery === null
|
|
191
|
-
? removeRef(repository, pin)
|
|
192
|
-
: updateRef(repository, pin, state.delivery.data.integration.snapshot));
|
|
217
|
+
effects.push(await (state.delivery === null
|
|
218
|
+
? await removeRef(repository, pin)
|
|
219
|
+
: await updateRef(repository, pin, state.delivery.data.integration.snapshot)));
|
|
193
220
|
}
|
|
194
221
|
return complete(effects, lag);
|
|
195
222
|
}
|
|
@@ -204,26 +231,26 @@ async function terminalSealExpectations(channel, state) {
|
|
|
204
231
|
return decodeTerminalSealExpectations(state, objects);
|
|
205
232
|
}
|
|
206
233
|
async function removeSealedTerminalWorktree({ repository, topology, path, expected, hooks, retryHooks, acc }) {
|
|
207
|
-
if (topology.paths.has(path) &&
|
|
208
|
-
const beforeHooks = unsealedBytes(repository, path, expected);
|
|
234
|
+
if (topology.paths.has(path) && await pathExists(path)) {
|
|
235
|
+
const beforeHooks = await unsealedBytes(repository, path, expected);
|
|
209
236
|
if (beforeHooks !== null)
|
|
210
237
|
return retainTerminalWorktree(path, beforeHooks, acc);
|
|
211
|
-
const hookLag = await runDestroyHooks(path, worktreeGitDirectory(repository, path), hooks, retryHooks);
|
|
238
|
+
const hookLag = await runDestroyHooks(path, await worktreeGitDirectory(repository, path), hooks, retryHooks);
|
|
212
239
|
if (hookLag !== null)
|
|
213
240
|
return retainTerminalWorktree(path, hookLag, acc);
|
|
214
|
-
const afterHooks = unsealedBytes(repository, path, expected);
|
|
241
|
+
const afterHooks = await unsealedBytes(repository, path, expected);
|
|
215
242
|
if (afterHooks !== null)
|
|
216
243
|
return retainTerminalWorktree(path, afterHooks, acc);
|
|
217
244
|
}
|
|
218
|
-
const removal = removeWorktree(repository, topology, path, true);
|
|
245
|
+
const removal = await removeWorktree(repository, topology, path, true);
|
|
219
246
|
if (removal.retained)
|
|
220
247
|
return retainTerminalWorktree(path, { kind: "worktree-retained", path }, acc);
|
|
221
248
|
acc.effects.push(removal.effect);
|
|
222
249
|
return null;
|
|
223
250
|
}
|
|
224
|
-
function targetCustodyForClaimedIntegration(repository, state, integration) {
|
|
251
|
+
async function targetCustodyForClaimedIntegration(repository, state, integration) {
|
|
225
252
|
return state.terminal?.kind === "claimed" && state.coordinates.target !== undefined
|
|
226
|
-
&& readRef(repository, state.coordinates.target) === integration
|
|
253
|
+
&& await readRef(repository, state.coordinates.target) === integration
|
|
227
254
|
? { ref: state.coordinates.target, oid: integration }
|
|
228
255
|
: null;
|
|
229
256
|
}
|
|
@@ -233,56 +260,69 @@ function sealedTree(expected, snapshot) {
|
|
|
233
260
|
throw new Error(`terminal seal tree was not resolved: ${snapshot}`);
|
|
234
261
|
return tree;
|
|
235
262
|
}
|
|
236
|
-
function releaseTerminalCustody({ repository, state, expected, ref, pin, acc: { effects } }) {
|
|
263
|
+
async function releaseTerminalCustody({ repository, state, expected, ref, pin, acc: { effects } }) {
|
|
237
264
|
if (state.delivery === null) {
|
|
238
|
-
const custodian = snapshotCustodian(repository, state.coordinates.start);
|
|
265
|
+
const custodian = await snapshotCustodian(repository, state.coordinates.start);
|
|
239
266
|
if (custodian !== null)
|
|
240
|
-
effects.push(removeRefWithCustody(repository, ref, custodian.ref, custodian.oid));
|
|
241
|
-
effects.push(removeRef(repository, pin));
|
|
267
|
+
effects.push(await removeRefWithCustody(repository, ref, custodian.ref, custodian.oid));
|
|
268
|
+
effects.push(await removeRef(repository, pin));
|
|
242
269
|
return;
|
|
243
270
|
}
|
|
244
271
|
const tender = state.delivery.data.tenderSnapshot;
|
|
245
272
|
const integration = state.delivery.data.integration.snapshot;
|
|
246
|
-
const target = targetCustodyForClaimedIntegration(repository, state, integration);
|
|
273
|
+
const target = await targetCustodyForClaimedIntegration(repository, state, integration);
|
|
247
274
|
if (sealedTree(expected, tender) === sealedTree(expected, integration) && target !== null) {
|
|
248
|
-
effects.push(removeRefWithCustody(repository, ref, target.ref, target.oid));
|
|
249
|
-
effects.push(removeRefWithCustody(repository, pin, target.ref, target.oid));
|
|
275
|
+
effects.push(await removeRefWithCustody(repository, ref, target.ref, target.oid));
|
|
276
|
+
effects.push(await removeRefWithCustody(repository, pin, target.ref, target.oid));
|
|
250
277
|
}
|
|
251
278
|
else if (tender === integration) {
|
|
252
|
-
effects.push(removeRefWithCustody(repository, pin, ref, tender));
|
|
279
|
+
effects.push(await removeRefWithCustody(repository, pin, ref, tender));
|
|
253
280
|
}
|
|
254
281
|
else if (target !== null) {
|
|
255
|
-
effects.push(removeRefWithCustody(repository, pin, target.ref, target.oid));
|
|
282
|
+
effects.push(await removeRefWithCustody(repository, pin, target.ref, target.oid));
|
|
256
283
|
}
|
|
257
284
|
}
|
|
258
|
-
async function reconcileTerminalManagedWorktree({ repository, channel, hooks, retryHooks, retainTerminalWorktree }, state, topology, acc) {
|
|
285
|
+
async function reconcileTerminalManagedWorktree({ repository, channel, hooks, retryHooks, retainTerminalWorktree, place }, state, topology, acc) {
|
|
259
286
|
const primary = fromPrimaryWorktree(repository);
|
|
260
287
|
const ref = deliveryRefFor(state.id);
|
|
261
288
|
const pin = candidatePinRefFor(state.id);
|
|
262
|
-
const path =
|
|
289
|
+
const path = place === undefined ? undefined : worktreePath(repository, place);
|
|
290
|
+
if (path === undefined)
|
|
291
|
+
return complete(acc.effects, acc.lag);
|
|
263
292
|
const expected = await terminalSealExpectations(channel, state);
|
|
264
|
-
acc.effects.push(updateRef(primary, ref, state.delivery?.data.tenderSnapshot ?? state.coordinates.start));
|
|
265
|
-
if (state.delivery !== null)
|
|
266
|
-
acc.effects.push(updateRef(primary, pin, state.delivery.data.integration.snapshot));
|
|
293
|
+
acc.effects.push(await updateRef(primary, ref, state.delivery?.data.tenderSnapshot ?? state.coordinates.start));
|
|
294
|
+
if (state.delivery !== null) {
|
|
295
|
+
acc.effects.push(await updateRef(primary, pin, state.delivery.data.integration.snapshot));
|
|
296
|
+
}
|
|
267
297
|
if (retainTerminalWorktree === true)
|
|
268
298
|
return complete(acc.effects, acc.lag);
|
|
269
|
-
const retained = await removeSealedTerminalWorktree({
|
|
299
|
+
const retained = await removeSealedTerminalWorktree({
|
|
300
|
+
repository: primary,
|
|
301
|
+
topology,
|
|
302
|
+
path,
|
|
303
|
+
expected,
|
|
304
|
+
hooks,
|
|
305
|
+
retryHooks,
|
|
306
|
+
acc,
|
|
307
|
+
});
|
|
270
308
|
if (retained !== null)
|
|
271
309
|
return retained;
|
|
272
|
-
releaseTerminalCustody({ repository: primary, state, expected, ref, pin, acc });
|
|
310
|
+
await releaseTerminalCustody({ repository: primary, state, expected, ref, pin, acc });
|
|
273
311
|
return complete(acc.effects, acc.lag);
|
|
274
312
|
}
|
|
275
|
-
async function reconcileActiveManagedWorktree({ repository, hooks, retryHooks }, state, topology, { effects, lag }) {
|
|
276
|
-
|
|
313
|
+
async function reconcileActiveManagedWorktree({ repository, hooks, retryHooks, place }, state, topology, { effects, lag }) {
|
|
314
|
+
if (place === undefined)
|
|
315
|
+
return complete(effects, [...lag, missingPlaceLag(repository)]);
|
|
316
|
+
const path = worktreePath(repository, place);
|
|
277
317
|
const desired = state.delivery?.data.tenderSnapshot ?? state.coordinates.start;
|
|
278
|
-
effects.push(updateRef(repository, deliveryRefFor(state.id), desired));
|
|
279
|
-
effects.push(worktree(repository, topology, path, desired));
|
|
280
|
-
const hookLag = await runCreateHooks(path, worktreeGitDirectory(repository, path), hooks, retryHooks);
|
|
318
|
+
effects.push(await updateRef(repository, deliveryRefFor(state.id), desired));
|
|
319
|
+
effects.push(await worktree(repository, topology, path, desired));
|
|
320
|
+
const hookLag = await runCreateHooks(path, await worktreeGitDirectory(repository, path), hooks, retryHooks);
|
|
281
321
|
if (hookLag !== null)
|
|
282
322
|
lag.push(hookLag);
|
|
283
|
-
effects.push(state.delivery
|
|
284
|
-
? updateRef(repository, candidatePinRefFor(state.id), state.delivery.data.integration.snapshot)
|
|
285
|
-
: removeRef(repository, candidatePinRefFor(state.id)));
|
|
323
|
+
effects.push(await (state.delivery
|
|
324
|
+
? await updateRef(repository, candidatePinRefFor(state.id), state.delivery.data.integration.snapshot)
|
|
325
|
+
: await removeRef(repository, candidatePinRefFor(state.id))));
|
|
286
326
|
return complete(effects, lag);
|
|
287
327
|
}
|
|
288
328
|
async function reconcileWithTopology(input, state, topology) {
|
|
@@ -290,14 +330,14 @@ async function reconcileWithTopology(input, state, topology) {
|
|
|
290
330
|
const effects = [];
|
|
291
331
|
const lag = [];
|
|
292
332
|
try {
|
|
293
|
-
|
|
333
|
+
await removeCollectableScratch(repository, topology, effects, lag);
|
|
294
334
|
if (!state)
|
|
295
335
|
return complete(effects, lag);
|
|
296
336
|
const targetCheckouts = await reconcileTargetCheckouts(repository, state);
|
|
297
337
|
effects.push(...targetCheckouts.effects);
|
|
298
338
|
lag.push(...targetCheckouts.lag);
|
|
299
339
|
if (state.coordinates.workspace === "here")
|
|
300
|
-
return reconcileHereWorkspaceRefs(input, state, { effects, lag });
|
|
340
|
+
return await reconcileHereWorkspaceRefs(input, state, { effects, lag });
|
|
301
341
|
if (state.terminal)
|
|
302
342
|
return await reconcileTerminalManagedWorktree(input, state, topology, { effects, lag });
|
|
303
343
|
return await reconcileActiveManagedWorktree(input, state, topology, { effects, lag });
|
|
@@ -334,7 +374,7 @@ export async function reconcile(input) {
|
|
|
334
374
|
let exceptional;
|
|
335
375
|
try {
|
|
336
376
|
const state = (await observeContractAt(input.repository, input.channel, input.contractId)).state;
|
|
337
|
-
const topology = acquireWorktreeTopology(input.repository);
|
|
377
|
+
const topology = await acquireWorktreeTopology(input.repository);
|
|
338
378
|
observation = {
|
|
339
379
|
state,
|
|
340
380
|
result: await reconcileWithTopology(input, state, topology),
|
|
@@ -359,18 +399,21 @@ export function reconcileObservationFailure(error) {
|
|
|
359
399
|
export function reconcileEffectFailure(error, prior) {
|
|
360
400
|
return failed("effect", error, prior?.effects, prior?.lag);
|
|
361
401
|
}
|
|
362
|
-
async function reconcileBatchItem(repository, channel, contract, options) {
|
|
363
|
-
const observation = await reconcile({ repository, channel, contractId: contract, ...options });
|
|
364
|
-
return {
|
|
365
|
-
contract,
|
|
366
|
-
state: observation.state,
|
|
367
|
-
result: observation.result,
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
402
|
/** Reconcile each discovered Contract through its own serialized, fresh observation. */
|
|
371
403
|
export async function reconcileBatch(repository, channel, contracts, options) {
|
|
372
404
|
const items = [];
|
|
373
|
-
for (const contract of contracts)
|
|
374
|
-
|
|
405
|
+
for (const contract of contracts) {
|
|
406
|
+
const place = options.places?.get(contract);
|
|
407
|
+
const observation = await reconcile({
|
|
408
|
+
repository,
|
|
409
|
+
channel,
|
|
410
|
+
contractId: contract,
|
|
411
|
+
hooks: options.hooks,
|
|
412
|
+
retryHooks: options.retryHooks,
|
|
413
|
+
retainTerminalWorktree: options.retainTerminalWorktree,
|
|
414
|
+
...(place === undefined ? {} : { place }),
|
|
415
|
+
});
|
|
416
|
+
items.push({ contract, state: observation.state, result: observation.result });
|
|
417
|
+
}
|
|
375
418
|
return items;
|
|
376
419
|
}
|
|
@@ -53,29 +53,30 @@ export type RegisteredWorktree = Readonly<{
|
|
|
53
53
|
path: string;
|
|
54
54
|
branch: string | null;
|
|
55
55
|
}>;
|
|
56
|
-
export declare function registeredWorktrees(repository: GitRepository): readonly RegisteredWorktree[]
|
|
57
|
-
export declare function registeredWorktreePaths(repository: GitRepository): readonly string[]
|
|
58
|
-
export declare function repositoryAt(cwd: string): GitRepository
|
|
56
|
+
export declare function registeredWorktrees(repository: GitRepository): Promise<readonly RegisteredWorktree[]>;
|
|
57
|
+
export declare function registeredWorktreePaths(repository: GitRepository): Promise<readonly string[]>;
|
|
58
|
+
export declare function repositoryAt(cwd: string): Promise<GitRepository>;
|
|
59
59
|
export declare function commonGitDirectory(repository: GitRepository): string;
|
|
60
|
-
export declare function worktreeGitDirectory(repository: GitRepository, worktree: string): string
|
|
61
|
-
export declare function worktreeRoot(repository: GitRepository): string
|
|
62
|
-
export declare function runGit(repository: GitRepository, args: readonly string[], input?: string | Uint8Array): Buffer
|
|
63
|
-
export declare function
|
|
64
|
-
export declare function
|
|
65
|
-
export declare function
|
|
66
|
-
export declare function
|
|
60
|
+
export declare function worktreeGitDirectory(repository: GitRepository, worktree: string): Promise<string>;
|
|
61
|
+
export declare function worktreeRoot(repository: GitRepository): Promise<string>;
|
|
62
|
+
export declare function runGit(repository: GitRepository, args: readonly string[], input?: string | Uint8Array): Promise<Buffer>;
|
|
63
|
+
export declare function consumeGitStdout(repository: GitRepository, args: readonly string[], consume: (chunk: Buffer) => void): Promise<void>;
|
|
64
|
+
export declare function runGitWithEnvironment(repository: GitRepository, args: readonly string[], input: string | Uint8Array | undefined, environment: NodeJS.ProcessEnv): Promise<Buffer>;
|
|
65
|
+
export declare function readRef(repository: GitRepository, ref: string): Promise<GitOid | null>;
|
|
66
|
+
export declare function readTreeEntries(repository: GitRepository, tree: GitOid): Promise<Map<string, TreeEntry>>;
|
|
67
|
+
export declare function readGit(repository: GitRepository): Promise<GitSnapshot>;
|
|
67
68
|
/** Read only the requested private Git paths from one immutable Git tree. */
|
|
68
|
-
export declare function readGitPaths(repository: GitRepository, requestedPaths: readonly string[]): GitSnapshot
|
|
69
|
+
export declare function readGitPaths(repository: GitRepository, requestedPaths: readonly string[]): Promise<GitSnapshot>;
|
|
69
70
|
/** Add paths from the same immutable Git tree without rereading its ref. */
|
|
70
|
-
export declare function extendGitPaths(repository: GitRepository, snapshot: GitSnapshot, requestedPaths: readonly string[]): GitSnapshot
|
|
71
|
+
export declare function extendGitPaths(repository: GitRepository, snapshot: GitSnapshot, requestedPaths: readonly string[]): Promise<GitSnapshot>;
|
|
71
72
|
/** Expand a targeted immutable snapshot to its complete already-pinned tree. */
|
|
72
|
-
export declare function expandGitSnapshot(repository: GitRepository, snapshot: GitSnapshot): GitSnapshot
|
|
73
|
-
export declare function writeBlob(repository: GitRepository, bytes: string | Uint8Array): GitOid
|
|
74
|
-
export declare function readBlob(repository: GitRepository, oid: GitOid): Buffer
|
|
73
|
+
export declare function expandGitSnapshot(repository: GitRepository, snapshot: GitSnapshot): Promise<GitSnapshot>;
|
|
74
|
+
export declare function writeBlob(repository: GitRepository, bytes: string | Uint8Array): Promise<GitOid>;
|
|
75
|
+
export declare function readBlob(repository: GitRepository, oid: GitOid): Promise<Buffer>;
|
|
75
76
|
/** Copy only the changed paths' tree ancestors, preserving untouched subtrees by object ID. */
|
|
76
|
-
export declare function updateGitTree(repository: GitRepository, baseTree: GitOid | null, changes: ReadonlyMap<string, TreeChange>): GitOid
|
|
77
|
+
export declare function updateGitTree(repository: GitRepository, baseTree: GitOid | null, changes: ReadonlyMap<string, TreeChange>): Promise<GitOid>;
|
|
77
78
|
/** Write a tree update from directory entries frozen with the admitted base tree. */
|
|
78
|
-
export declare function updateGitTreeFromFrozenDirectories(repository: GitRepository, baseTree: GitOid | null, directories: ReadonlyMap<string, ReadonlyMap<string, TreeEntry>>, changes: ReadonlyMap<string, TreeChange>): GitOid
|
|
79
|
+
export declare function updateGitTreeFromFrozenDirectories(repository: GitRepository, baseTree: GitOid | null, directories: ReadonlyMap<string, ReadonlyMap<string, TreeEntry>>, changes: ReadonlyMap<string, TreeChange>): Promise<GitOid>;
|
|
79
80
|
export declare function writeCommit(input: Readonly<{
|
|
80
81
|
repository: GitRepository;
|
|
81
82
|
tree: GitOid;
|
|
@@ -83,7 +84,7 @@ export declare function writeCommit(input: Readonly<{
|
|
|
83
84
|
message?: string;
|
|
84
85
|
actor?: string;
|
|
85
86
|
at?: string;
|
|
86
|
-
}>): GitOid
|
|
87
|
+
}>): Promise<GitOid>;
|
|
87
88
|
export declare function updateRefsAtomically(repository: GitRepository, updates: readonly ({
|
|
88
89
|
readonly ref: typeof GIT_REF;
|
|
89
90
|
readonly newOid: GitOid;
|
|
@@ -92,4 +93,11 @@ export declare function updateRefsAtomically(repository: GitRepository, updates:
|
|
|
92
93
|
readonly ref: string;
|
|
93
94
|
readonly newOid: GitOid;
|
|
94
95
|
readonly expectedOid: GitOid;
|
|
95
|
-
})[], assertions?: readonly GitRefAssertion[]): RefPublication
|
|
96
|
+
})[], assertions?: readonly GitRefAssertion[]): Promise<RefPublication>;
|
|
97
|
+
export type GitDiffStat = Readonly<{
|
|
98
|
+
filesChanged: number;
|
|
99
|
+
insertions: number;
|
|
100
|
+
deletions: number;
|
|
101
|
+
}>;
|
|
102
|
+
export declare function decodeGitNumstat(output: Buffer): GitDiffStat;
|
|
103
|
+
export declare function decodeGitNameOnly(output: Buffer): readonly string[];
|