@astrosheep/keiyaku 4.0.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -8
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +50 -33
- package/build/src/akuma/akuma.js +175 -127
- package/build/src/akuma/archetype.d.ts +14 -5
- package/build/src/akuma/archetype.js +85 -39
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +490 -183
- package/build/src/akuma/coordinate.d.ts +9 -0
- package/build/src/akuma/coordinate.js +22 -0
- package/build/src/akuma/heart/facts.d.ts +88 -45
- package/build/src/akuma/heart/facts.js +19 -8
- package/build/src/akuma/heart/index.d.ts +64 -55
- package/build/src/akuma/heart/index.js +172 -252
- package/build/src/akuma/heart/rows.d.ts +38 -83
- package/build/src/akuma/heart/rows.js +117 -155
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +61 -22
- 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 +47 -0
- package/build/src/akuma/heart/storage.js +224 -0
- package/build/src/akuma/heart/tells.d.ts +12 -0
- package/build/src/akuma/heart/tells.js +79 -0
- package/build/src/akuma/heart/timeline.d.ts +15 -0
- package/build/src/akuma/heart/timeline.js +86 -0
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +10 -3
- package/build/src/akuma/index.js +7 -1
- package/build/src/akuma/projection.d.ts +176 -0
- package/build/src/akuma/projection.js +256 -0
- 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 +67 -13
- package/build/src/akuma/provider.js +172 -105
- 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.d.ts → claude/events.d.ts} +9 -41
- package/build/src/akuma/providers/claude/events.js +238 -0
- package/build/src/akuma/providers/claude/index.d.ts +47 -0
- package/build/src/akuma/providers/claude/index.js +279 -0
- package/build/src/akuma/providers/claude/input.d.ts +13 -0
- package/build/src/akuma/providers/claude/input.js +109 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
- package/build/src/akuma/providers/codex-app-server/events.js +15 -12
- package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
- package/build/src/akuma/providers/codex-app-server/index.js +77 -33
- 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 +35 -56
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
- package/build/src/akuma/providers/pi/events.d.ts +33 -0
- package/build/src/akuma/providers/pi/events.js +166 -0
- package/build/src/akuma/providers/pi/index.d.ts +11 -0
- package/build/src/akuma/providers/pi/index.js +191 -0
- 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 -6
- package/build/src/akuma/requests.js +95 -65
- package/build/src/alias/index.d.ts +4 -3
- package/build/src/alias/index.js +12 -13
- 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/body/render.js +2 -1
- package/build/src/body/shape.js +7 -1
- package/build/src/body/verification.js +19 -4
- package/build/src/cli/accepted.d.ts +18 -12
- package/build/src/cli/accepted.js +73 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
- package/build/src/cli/commands/akuma-invoke.js +101 -52
- package/build/src/cli/commands/akuma.d.ts +27 -9
- package/build/src/cli/commands/akuma.js +151 -80
- package/build/src/cli/commands/contract.d.ts +155 -0
- package/build/src/cli/commands/contract.js +20 -0
- package/build/src/cli/commands/install.js +2 -0
- package/build/src/cli/commands/task-invoke.d.ts +19 -4
- package/build/src/cli/commands/task-invoke.js +65 -17
- 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 +52 -14
- 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 +9 -3
- package/build/src/cli/invoke.js +287 -108
- package/build/src/cli/main.js +54 -7
- package/build/src/cli/parse.d.ts +21 -117
- package/build/src/cli/parse.js +79 -84
- 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 +4 -2
- package/build/src/cli/render/akuma-tool.js +35 -5
- package/build/src/cli/render/akuma.d.ts +3 -1
- package/build/src/cli/render/akuma.js +247 -212
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/catalog.d.ts +2 -0
- package/build/src/cli/render/catalog.js +16 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +200 -54
- package/build/src/cli/render/kanshi.js +272 -129
- 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 -3
- 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 +20 -0
- package/build/src/cli/render/terminal.js +121 -0
- package/build/src/cli/render/text.js +11 -3
- package/build/src/cli/result.d.ts +126 -19
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +44 -0
- package/build/src/contract-worktree.js +251 -0
- package/build/src/coordination/durable-file.d.ts +5 -1
- package/build/src/coordination/durable-file.js +57 -10
- 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/codec.js +23 -4
- package/build/src/core/facts/eligibility.d.ts +1 -10
- package/build/src/core/facts/eligibility.js +0 -49
- 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/facts/observation.d.ts +3 -0
- package/build/src/core/facts/observation.js +12 -0
- package/build/src/core/facts/types.d.ts +10 -3
- package/build/src/core/subject.js +2 -2
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +3 -18
- package/build/src/core/verbs/bind.js +2 -16
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +14 -4
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +7 -9
- package/build/src/dispatch/index.d.ts +5 -3
- package/build/src/dispatch/index.js +30 -21
- package/build/src/duration.d.ts +10 -0
- package/build/src/duration.js +22 -0
- package/build/src/git/admission.d.ts +2 -2
- package/build/src/git/admission.js +33 -23
- package/build/src/git/hooks.d.ts +15 -0
- package/build/src/git/hooks.js +70 -18
- package/build/src/git/identity.d.ts +5 -1
- package/build/src/git/identity.js +23 -4
- package/build/src/git/integration.d.ts +48 -0
- package/build/src/git/integration.js +250 -0
- package/build/src/git/observe.d.ts +29 -15
- package/build/src/git/observe.js +185 -76
- package/build/src/git/read-observation.d.ts +41 -0
- package/build/src/git/read-observation.js +361 -0
- package/build/src/git/reconcile.d.ts +17 -5
- package/build/src/git/reconcile.js +305 -109
- package/build/src/git/repository.d.ts +41 -18
- package/build/src/git/repository.js +220 -114
- package/build/src/git/scratch.d.ts +17 -0
- package/build/src/git/scratch.js +73 -0
- package/build/src/git/target-placement.d.ts +92 -0
- package/build/src/git/target-placement.js +375 -0
- package/build/src/git/tender.d.ts +49 -0
- package/build/src/git/tender.js +63 -0
- package/build/src/git/terminal-seal.d.ts +24 -0
- package/build/src/git/terminal-seal.js +89 -0
- package/build/src/git/tree.d.ts +2 -2
- package/build/src/git/tree.js +4 -0
- package/build/src/git/workspace.d.ts +53 -0
- package/build/src/git/workspace.js +139 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +19 -0
- package/build/src/index.d.ts +4 -2
- package/build/src/index.js +2 -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 +7 -3
- package/build/src/kanshi/read.js +245 -45
- package/build/src/kanshi/report.d.ts +81 -6
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +33 -1
- package/build/src/library/address.d.ts +57 -0
- package/build/src/library/address.js +165 -0
- package/build/src/library/akuma-creation.d.ts +16 -7
- package/build/src/library/akuma-creation.js +96 -22
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.d.ts +21 -0
- package/build/src/library/bind.js +56 -0
- package/build/src/library/catalog.d.ts +58 -0
- package/build/src/library/catalog.js +69 -0
- package/build/src/library/configuration.d.ts +6 -15
- package/build/src/library/configuration.js +14 -17
- package/build/src/library/contract.d.ts +23 -49
- package/build/src/library/contract.js +171 -185
- package/build/src/library/delivery.d.ts +24 -0
- package/build/src/library/delivery.js +21 -0
- package/build/src/library/fleet.d.ts +65 -0
- package/build/src/library/fleet.js +153 -0
- package/build/src/library/input.d.ts +3 -0
- package/build/src/library/input.js +19 -0
- package/build/src/library/keiyaku.d.ts +18 -3
- package/build/src/library/keiyaku.js +12 -1
- package/build/src/library/mutation.d.ts +39 -0
- package/build/src/library/mutation.js +37 -0
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/refusal.d.ts +21 -0
- package/build/src/library/refusal.js +29 -0
- package/build/src/library/region.d.ts +14 -1
- package/build/src/library/region.js +18 -4
- package/build/src/library/repo.d.ts +4 -13
- package/build/src/library/repo.js +14 -24
- package/build/src/protocol/attempt.d.ts +16 -3
- package/build/src/protocol/attempt.js +41 -10
- package/build/src/protocol/bind.d.ts +9 -2
- package/build/src/protocol/bind.js +48 -40
- package/build/src/protocol/intent.d.ts +57 -20
- package/build/src/protocol/intent.js +55 -79
- package/build/src/protocol/operations.d.ts +152 -43
- package/build/src/protocol/operations.js +482 -166
- package/build/src/protocol/outcome.d.ts +14 -3
- package/build/src/protocol/outcome.js +11 -3
- package/build/src/protocol/placement.d.ts +41 -0
- package/build/src/protocol/placement.js +147 -0
- package/build/src/protocol/read/documents.d.ts +2 -2
- package/build/src/protocol/read/documents.js +4 -4
- package/build/src/protocol/read/status.d.ts +18 -5
- package/build/src/protocol/read/status.js +73 -13
- package/build/src/protocol/run.d.ts +49 -7
- package/build/src/protocol/run.js +53 -25
- package/build/src/runtime/proc/line-rpc.d.ts +4 -8
- package/build/src/runtime/proc/line-rpc.js +22 -28
- package/build/src/runtime/proc/run.d.ts +23 -21
- package/build/src/runtime/proc/run.js +123 -89
- 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 +7 -1
- package/build/src/settings.js +32 -17
- package/build/src/settlement/fence.d.ts +5 -0
- package/build/src/settlement/fence.js +14 -0
- package/build/src/settlement/holder.d.ts +35 -4
- package/build/src/settlement/holder.js +127 -28
- package/build/src/settlement/settle.d.ts +9 -1
- package/build/src/settlement/settle.js +74 -37
- package/build/src/task/board.d.ts +23 -5
- package/build/src/task/board.js +17 -10
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +15 -20
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +27 -15
- package/build/src/task/index.js +57 -35
- package/build/src/task/operations.d.ts +38 -13
- package/build/src/task/operations.js +80 -46
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +5 -7
- package/build/src/task/store.js +43 -28
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/execution.d.ts +51 -0
- package/build/src/verification/execution.js +108 -0
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +24 -0
- package/build/src/world.js +136 -0
- package/package.json +8 -4
- package/build/src/akuma/activity.d.ts +0 -66
- package/build/src/akuma/activity.js +0 -139
- package/build/src/akuma/providers/claude.js +0 -305
- package/build/src/context-root.d.ts +0 -4
- package/build/src/context-root.js +0 -15
- package/build/src/git/delivery.d.ts +0 -20
- package/build/src/git/delivery.js +0 -109
- package/build/src/git/verification.d.ts +0 -14
- package/build/src/git/verification.js +0 -56
- package/build/src/protocol/read/audit.d.ts +0 -25
- package/build/src/protocol/read/audit.js +0 -39
- package/build/src/verification/producer.d.ts +0 -23
- package/build/src/verification/producer.js +0 -54
package/build/src/task/store.js
CHANGED
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { closeSync,
|
|
2
|
+
import { closeSync, fsyncSync, openSync, renameSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { lstat, mkdir, readFile, readdir, unlink } from "node:fs/promises";
|
|
3
4
|
import { dirname, relative, resolve, sep } from "node:path";
|
|
4
5
|
import { acquireSqliteTransactionLock, SqliteTransactionLockError } from "../coordination/sqlite-transaction-lock.js";
|
|
5
6
|
import { parseTaskDocument } from "./document.js";
|
|
6
7
|
import { formatTaskId, parseTaskId, taskAuthorityPath } from "./identity.js";
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
function syncTaskDirectory(path) {
|
|
9
|
+
if (process.platform === "win32")
|
|
10
|
+
return;
|
|
11
|
+
const directory = openSync(path, "r");
|
|
12
|
+
try {
|
|
13
|
+
fsyncSync(directory);
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
closeSync(directory);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function tasksDirectory(world) { return resolve(world, ".keiyaku", "tasks"); }
|
|
20
|
+
async function authorityFiles(directory) {
|
|
11
21
|
const files = [];
|
|
12
|
-
|
|
22
|
+
let entries;
|
|
23
|
+
try {
|
|
24
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (error.code === "ENOENT")
|
|
28
|
+
return [];
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
for (const entry of entries) {
|
|
13
32
|
const path = resolve(directory, entry.name);
|
|
14
33
|
if (entry.isDirectory())
|
|
15
|
-
files.push(...authorityFiles(path));
|
|
34
|
+
files.push(...await authorityFiles(path));
|
|
16
35
|
else if (entry.isFile() && entry.name.endsWith(".md"))
|
|
17
36
|
files.push(path);
|
|
18
37
|
else
|
|
@@ -26,16 +45,18 @@ function coordinateFromPath(tasksDirectory, path) {
|
|
|
26
45
|
throw new Error(`invalid Task authority path: ${path}`);
|
|
27
46
|
return parseTaskId(`task/${local.slice(0, -3).split(sep).join("/")}`);
|
|
28
47
|
}
|
|
29
|
-
export function readBoard(world) {
|
|
48
|
+
export async function readBoard(world) {
|
|
30
49
|
const directory = tasksDirectory(world);
|
|
31
|
-
const tasks = new Map()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
50
|
+
const tasks = new Map();
|
|
51
|
+
const bytes = new Map();
|
|
52
|
+
for (const path of await authorityFiles(directory)) {
|
|
53
|
+
const stat = await lstat(path);
|
|
54
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
35
55
|
throw new Error(`Task authority is not a regular file: ${path}`);
|
|
56
|
+
}
|
|
36
57
|
const coordinate = coordinateFromPath(directory, path);
|
|
37
58
|
const id = formatTaskId(coordinate);
|
|
38
|
-
const source =
|
|
59
|
+
const source = await readFile(path);
|
|
39
60
|
tasks.set(id, parseTaskDocument(source, coordinate));
|
|
40
61
|
bytes.set(id, source);
|
|
41
62
|
}
|
|
@@ -44,9 +65,9 @@ export function readBoard(world) {
|
|
|
44
65
|
function equal(left, right) {
|
|
45
66
|
return left === null || right === null ? left === right : Buffer.from(left).equals(Buffer.from(right));
|
|
46
67
|
}
|
|
47
|
-
function currentBytes(path) {
|
|
68
|
+
async function currentBytes(path) {
|
|
48
69
|
try {
|
|
49
|
-
return
|
|
70
|
+
return await readFile(path);
|
|
50
71
|
}
|
|
51
72
|
catch (error) {
|
|
52
73
|
if (error.code === "ENOENT")
|
|
@@ -54,9 +75,9 @@ function currentBytes(path) {
|
|
|
54
75
|
throw error;
|
|
55
76
|
}
|
|
56
77
|
}
|
|
57
|
-
export function replaceAuthority(input) {
|
|
78
|
+
export async function replaceAuthority(input) {
|
|
58
79
|
const parent = dirname(input.path);
|
|
59
|
-
|
|
80
|
+
await mkdir(parent, { recursive: true });
|
|
60
81
|
const temporary = resolve(parent, `.tmp-${randomBytes(8).toString("hex")}`);
|
|
61
82
|
let descriptor;
|
|
62
83
|
try {
|
|
@@ -65,34 +86,28 @@ export function replaceAuthority(input) {
|
|
|
65
86
|
fsyncSync(descriptor);
|
|
66
87
|
closeSync(descriptor);
|
|
67
88
|
descriptor = undefined;
|
|
68
|
-
if (!equal(currentBytes(input.path), input.expected))
|
|
89
|
+
if (!equal(await currentBytes(input.path), input.expected))
|
|
69
90
|
return "concurrent-modification";
|
|
70
91
|
renameSync(temporary, input.path);
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
fsyncSync(directoryDescriptor);
|
|
74
|
-
}
|
|
75
|
-
finally {
|
|
76
|
-
closeSync(directoryDescriptor);
|
|
77
|
-
}
|
|
92
|
+
syncTaskDirectory(parent);
|
|
78
93
|
return "replaced";
|
|
79
94
|
}
|
|
80
95
|
finally {
|
|
81
96
|
if (descriptor !== undefined)
|
|
82
97
|
closeSync(descriptor);
|
|
83
98
|
try {
|
|
84
|
-
|
|
99
|
+
await unlink(temporary);
|
|
85
100
|
}
|
|
86
101
|
catch { /* renamed or best effort */ }
|
|
87
102
|
}
|
|
88
103
|
}
|
|
89
104
|
function lockPath(world, id) {
|
|
90
105
|
const coordinate = parseTaskId(id);
|
|
91
|
-
return resolve(world
|
|
106
|
+
return resolve(world, ".keiyaku", "locks", "task", ...coordinate.namespace, `${coordinate.localId}.sqlite`);
|
|
92
107
|
}
|
|
93
108
|
export async function withTaskLocks(input, action) {
|
|
94
109
|
const paths = [
|
|
95
|
-
...(input.allocation ? [resolve(input.world
|
|
110
|
+
...(input.allocation ? [resolve(input.world, ".keiyaku", "locks", "task-allocation.sqlite")] : []),
|
|
96
111
|
...[...new Set(input.ids)].sort((a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b))).map((id) => lockPath(input.world, id)),
|
|
97
112
|
];
|
|
98
113
|
const held = [];
|
|
@@ -4,6 +4,7 @@ export type VerificationExecutor = "bash" | "zsh" | "pwsh";
|
|
|
4
4
|
export type VerificationDeclaration = Readonly<{
|
|
5
5
|
readonly executor: VerificationExecutor;
|
|
6
6
|
readonly script: string;
|
|
7
|
+
readonly timeoutMs?: number;
|
|
7
8
|
}>;
|
|
8
9
|
export type VerificationDefinition = Readonly<{
|
|
9
10
|
readonly segment: DocumentSegmentKey;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SnapshotId } from "../core/facts/types.js";
|
|
2
|
+
import { type HookFailure } from "../git/hooks.js";
|
|
3
|
+
import type { MaterializedScratchCandidate, WorktreeLeak } from "../git/scratch.js";
|
|
4
|
+
import type { GitRepository } from "../git/repository.js";
|
|
5
|
+
import type { Settings } from "../settings.js";
|
|
6
|
+
import type { VerificationDeclaration } from "./declaration.js";
|
|
7
|
+
type VerificationVerdict = "satisfied" | "unsatisfied";
|
|
8
|
+
export type VerificationTerminalOutcome = Readonly<{
|
|
9
|
+
kind: "terminal";
|
|
10
|
+
verdict: VerificationVerdict;
|
|
11
|
+
passed: number;
|
|
12
|
+
total: number;
|
|
13
|
+
summary?: string;
|
|
14
|
+
}>;
|
|
15
|
+
export type VerificationNonterminalOutcome = Readonly<{
|
|
16
|
+
kind: "unknown-exit";
|
|
17
|
+
}> | Readonly<{
|
|
18
|
+
kind: "cancelled";
|
|
19
|
+
}> | Readonly<{
|
|
20
|
+
kind: "spawn-error";
|
|
21
|
+
diagnostic: string;
|
|
22
|
+
}>;
|
|
23
|
+
export type VerificationExecutionStop = VerificationNonterminalOutcome | Readonly<{
|
|
24
|
+
kind: "candidate-unavailable" | "environment-failure";
|
|
25
|
+
diagnostic: string;
|
|
26
|
+
}> | Readonly<{
|
|
27
|
+
kind: "environment-failure";
|
|
28
|
+
command: number;
|
|
29
|
+
detail: HookFailure;
|
|
30
|
+
}>;
|
|
31
|
+
export type VerificationExecution = Readonly<{
|
|
32
|
+
outcome: VerificationTerminalOutcome | VerificationExecutionStop;
|
|
33
|
+
cleanup?: Readonly<{
|
|
34
|
+
phase: "destroy";
|
|
35
|
+
command: number;
|
|
36
|
+
detail: HookFailure;
|
|
37
|
+
}>;
|
|
38
|
+
leak?: WorktreeLeak;
|
|
39
|
+
}>;
|
|
40
|
+
export type ExecuteVerificationInput = Readonly<{
|
|
41
|
+
repository: GitRepository;
|
|
42
|
+
candidate: SnapshotId;
|
|
43
|
+
declarations: readonly VerificationDeclaration[];
|
|
44
|
+
environment: NodeJS.ProcessEnv;
|
|
45
|
+
materializeScratchCandidate: (repository: GitRepository, candidate: SnapshotId) => Promise<MaterializedScratchCandidate>;
|
|
46
|
+
projectSettings: (root: string) => Promise<Settings>;
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
}>;
|
|
49
|
+
/** Execute one disposable Verification attempt over the exact integration snapshot. */
|
|
50
|
+
export declare function executeVerification(input: ExecuteVerificationInput): Promise<VerificationExecution>;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { runHookCommands, worktreeHooksFrom } from "../git/hooks.js";
|
|
2
|
+
import { runProcess } from "../runtime/proc/run.js";
|
|
3
|
+
const SUMMARY_BYTES = 32 * 1024;
|
|
4
|
+
function argvFor(declaration) {
|
|
5
|
+
const args = declaration.executor === "pwsh" ? ["-Command", declaration.script] : ["-c", declaration.script];
|
|
6
|
+
return [declaration.executor, ...args];
|
|
7
|
+
}
|
|
8
|
+
function processDiagnostic(declaration, index, outcome) {
|
|
9
|
+
if (outcome.code === 0 && outcome.stdout.length === 0 && outcome.stderr.length === 0 && !outcome.truncated) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return [
|
|
13
|
+
`[${index + 1} ${declaration.executor} exit ${outcome.code}${outcome.truncated ? " output-truncated" : ""}]`,
|
|
14
|
+
...(outcome.stdout.length === 0 ? [] : [`stdout:\n${outcome.stdout}`]),
|
|
15
|
+
...(outcome.stderr.length === 0 ? [] : [`stderr:\n${outcome.stderr}`]),
|
|
16
|
+
].join("\n");
|
|
17
|
+
}
|
|
18
|
+
function appendSummary(current, diagnostic) {
|
|
19
|
+
if (diagnostic === null)
|
|
20
|
+
return current;
|
|
21
|
+
const combined = Buffer.from(current === undefined ? diagnostic : `${current}\n\n${diagnostic}`);
|
|
22
|
+
if (combined.length <= SUMMARY_BYTES)
|
|
23
|
+
return combined.toString("utf8");
|
|
24
|
+
const marker = Buffer.from("[earlier output truncated]\n");
|
|
25
|
+
let start = combined.length - (SUMMARY_BYTES - marker.length);
|
|
26
|
+
while (start < combined.length && (combined[start] & 0xc0) === 0x80)
|
|
27
|
+
start += 1;
|
|
28
|
+
return Buffer.concat([marker, combined.subarray(start)]).toString("utf8");
|
|
29
|
+
}
|
|
30
|
+
async function executeDeclarations(input) {
|
|
31
|
+
let verdict = "satisfied";
|
|
32
|
+
let passed = 0;
|
|
33
|
+
const total = input.declarations.length;
|
|
34
|
+
let summary;
|
|
35
|
+
for (const [index, declaration] of input.declarations.entries()) {
|
|
36
|
+
const outcome = await runProcess({
|
|
37
|
+
argv: argvFor(declaration),
|
|
38
|
+
cwd: input.cwd,
|
|
39
|
+
env: input.environment,
|
|
40
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
41
|
+
...(declaration.timeoutMs === undefined ? {} : { timeoutMs: declaration.timeoutMs }),
|
|
42
|
+
});
|
|
43
|
+
if (outcome.kind === "timeout") {
|
|
44
|
+
verdict = "unsatisfied";
|
|
45
|
+
summary = appendSummary(summary, `[${index + 1} ${declaration.executor} timeout after ${declaration.timeoutMs}ms]`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (outcome.kind === "spawn-error" || outcome.kind === "unknown-exit" || outcome.kind === "cancelled")
|
|
49
|
+
return outcome;
|
|
50
|
+
if (outcome.code === 0)
|
|
51
|
+
passed += 1;
|
|
52
|
+
else
|
|
53
|
+
verdict = "unsatisfied";
|
|
54
|
+
summary = appendSummary(summary, processDiagnostic(declaration, index, outcome));
|
|
55
|
+
}
|
|
56
|
+
return { kind: "terminal", verdict, passed, total, ...(summary === undefined ? {} : { summary }) };
|
|
57
|
+
}
|
|
58
|
+
/** Execute one disposable Verification attempt over the exact integration snapshot. */
|
|
59
|
+
export async function executeVerification(input) {
|
|
60
|
+
let scratch;
|
|
61
|
+
try {
|
|
62
|
+
scratch = await input.materializeScratchCandidate(input.repository, input.candidate);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return { outcome: { kind: "candidate-unavailable", diagnostic: error instanceof Error ? error.message : String(error) } };
|
|
66
|
+
}
|
|
67
|
+
let outcome;
|
|
68
|
+
let cleanup;
|
|
69
|
+
let leak = null;
|
|
70
|
+
let destroy;
|
|
71
|
+
try {
|
|
72
|
+
try {
|
|
73
|
+
const hooks = worktreeHooksFrom({ settings: await input.projectSettings(scratch.cwd) });
|
|
74
|
+
destroy = hooks.destroy;
|
|
75
|
+
const readiness = await runHookCommands(scratch.cwd, hooks.create, input.signal);
|
|
76
|
+
outcome = readiness.kind === "cancelled"
|
|
77
|
+
? { kind: "cancelled" }
|
|
78
|
+
: readiness.kind === "failed"
|
|
79
|
+
? { kind: "environment-failure", command: readiness.command, detail: readiness.failure }
|
|
80
|
+
: await executeDeclarations({
|
|
81
|
+
declarations: input.declarations,
|
|
82
|
+
cwd: scratch.cwd,
|
|
83
|
+
environment: input.environment,
|
|
84
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
outcome = { kind: "environment-failure", diagnostic: error instanceof Error ? error.message : String(error) };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
if (destroy !== undefined) {
|
|
93
|
+
const result = await runHookCommands(scratch.cwd, destroy);
|
|
94
|
+
if (result.kind === "cancelled")
|
|
95
|
+
throw new Error("scratch destroy cancelled without a signal");
|
|
96
|
+
if (result.kind === "failed")
|
|
97
|
+
cleanup = { phase: "destroy", command: result.command, detail: result.failure };
|
|
98
|
+
}
|
|
99
|
+
leak = await scratch.dispose();
|
|
100
|
+
}
|
|
101
|
+
if (outcome === undefined)
|
|
102
|
+
throw new Error("Verification ended without an outcome");
|
|
103
|
+
return {
|
|
104
|
+
outcome,
|
|
105
|
+
...(cleanup === undefined ? {} : { cleanup }),
|
|
106
|
+
...(leak === null ? {} : { leak }),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ContractId } from "./core/facts/types.js";
|
|
2
|
+
import type { GitRepository } from "./git/repository.js";
|
|
3
|
+
export declare const CONTRACT_PLACES: readonly string[];
|
|
4
|
+
export type Place = string & {
|
|
5
|
+
readonly [placeBrand]: "Place";
|
|
6
|
+
};
|
|
7
|
+
declare const placeBrand: unique symbol;
|
|
8
|
+
export type PlaceAppointment = Readonly<{
|
|
9
|
+
place: Place;
|
|
10
|
+
contract: ContractId;
|
|
11
|
+
}>;
|
|
12
|
+
export type PlaceRegister = Readonly<{
|
|
13
|
+
appointments: readonly PlaceAppointment[];
|
|
14
|
+
byPlace: ReadonlyMap<Place, PlaceAppointment>;
|
|
15
|
+
byContract: ReadonlyMap<ContractId, PlaceAppointment>;
|
|
16
|
+
}>;
|
|
17
|
+
export type ManagedWorktreeAppointment = Readonly<{
|
|
18
|
+
kind: "appointed";
|
|
19
|
+
place: Place;
|
|
20
|
+
path: string;
|
|
21
|
+
}> | Readonly<{
|
|
22
|
+
kind: "unappointed";
|
|
23
|
+
}> | Readonly<{
|
|
24
|
+
kind: "failed";
|
|
25
|
+
diagnostic: string;
|
|
26
|
+
}>;
|
|
27
|
+
export declare function placeRegisterPath(repository: GitRepository): string;
|
|
28
|
+
export declare function place(value: string): Place;
|
|
29
|
+
export declare function nextPlace(current?: Place): Place;
|
|
30
|
+
export declare function firstFreePlace(register: PlaceRegister): Place;
|
|
31
|
+
export declare function canonicalPlaceRegister(register: PlaceRegister): string;
|
|
32
|
+
export declare function decodePlaceRegister(path: string, bytes: string): PlaceRegister;
|
|
33
|
+
export declare function emptyPlaceRegister(): PlaceRegister;
|
|
34
|
+
export declare function readPlaceRegister(repository: GitRepository): Promise<PlaceRegister>;
|
|
35
|
+
export declare function appointmentFor(register: PlaceRegister, contract: ContractId): PlaceAppointment | undefined;
|
|
36
|
+
export declare function appointManagedWorktrees(repository: GitRepository, contracts: readonly ContractId[]): Promise<PlaceRegister>;
|
|
37
|
+
export declare function appointManagedWorktree(repository: GitRepository, contract: ContractId): Promise<PlaceAppointment>;
|
|
38
|
+
export declare function releaseManagedWorktrees(repository: GitRepository, contracts: readonly ContractId[]): Promise<void>;
|
|
39
|
+
export declare function releaseManagedWorktree(repository: GitRepository, contract: ContractId): Promise<void>;
|
|
40
|
+
export declare function readManagedWorktreeAppointment(repository: GitRepository, contract: ContractId, register?: PlaceRegister): Promise<ManagedWorktreeAppointment>;
|
|
41
|
+
export {};
|