@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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { isBlankInput } from "./usage.js";
|
|
2
|
+
/** The one `-` reader for this invocation; a second `-` is the duplicate refusal. */
|
|
3
|
+
function selectStdin(spec, stdin, fail) {
|
|
4
|
+
if (spec.stdin === undefined)
|
|
5
|
+
fail(spec.stdinRefusal);
|
|
6
|
+
if (stdin !== undefined)
|
|
7
|
+
fail("stdin marker '-' may appear only once");
|
|
8
|
+
return spec.stdin;
|
|
9
|
+
}
|
|
10
|
+
/** A value token this surface refuses: `-`, or one of its own refused tokens. */
|
|
11
|
+
function refusedValue(kind, value, spec) {
|
|
12
|
+
if (kind === "raw-value")
|
|
13
|
+
return false;
|
|
14
|
+
return value === "-" || spec.refused?.[value] !== undefined;
|
|
15
|
+
}
|
|
16
|
+
/** The admitted value after `--name`: absent, dash-like, and blank values carry their own refusals. */
|
|
17
|
+
function optionValue(token, value, kind, spec, fail) {
|
|
18
|
+
if (value === undefined || value.startsWith("--") || refusedValue(kind, value, spec))
|
|
19
|
+
fail(`${token} requires a value`);
|
|
20
|
+
if (kind !== "raw-value" && isBlankInput(value))
|
|
21
|
+
fail(`${token} requires a nonblank value`);
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
/** One `--name` option: a boolean, a repeated value, or a single value. Returns its consumed tokens. */
|
|
25
|
+
function assignOption(option, spec, flags, fail) {
|
|
26
|
+
const { token, name, kind, value } = option;
|
|
27
|
+
if (flags[name] !== undefined && kind !== "repeat")
|
|
28
|
+
fail(`duplicate option: ${token}`);
|
|
29
|
+
if (kind === "boolean") {
|
|
30
|
+
flags[name] = true;
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
const admitted = optionValue(token, value, kind, spec, fail);
|
|
34
|
+
flags[name] = kind === "repeat" ? [...(Array.isArray(flags[name]) ? flags[name] : []), admitted] : admitted;
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One argument scan for every CLI grammar: `--name value` options, `--` positional-only mode,
|
|
39
|
+
* `-` stdin, and the surface's own refusal text. A refused token is refused in option position with
|
|
40
|
+
* its own text, and in value position as the missing-value refusal.
|
|
41
|
+
*/
|
|
42
|
+
export function scanArgs(argv, spec, fail) {
|
|
43
|
+
const flags = {};
|
|
44
|
+
const positionals = [];
|
|
45
|
+
let stdin;
|
|
46
|
+
let positionalOnly = false;
|
|
47
|
+
for (let index = 1; index < argv.length; index += 1) {
|
|
48
|
+
const token = argv[index];
|
|
49
|
+
if (!positionalOnly && token === "--") {
|
|
50
|
+
positionalOnly = true;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (!positionalOnly && spec.refused?.[token] !== undefined)
|
|
54
|
+
fail(spec.refused[token]);
|
|
55
|
+
if (!positionalOnly && token === "-") {
|
|
56
|
+
stdin = selectStdin(spec, stdin, fail);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (positionalOnly || !token.startsWith("--")) {
|
|
60
|
+
if (isBlankInput(token))
|
|
61
|
+
fail(`${spec.subject} requires a nonblank value`);
|
|
62
|
+
positionals.push(token);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const name = token.slice(2);
|
|
66
|
+
const kind = spec.flags[name];
|
|
67
|
+
if (kind === undefined)
|
|
68
|
+
fail(`option ${token} is not valid for ${spec.subject}`);
|
|
69
|
+
const reader = spec.stdinValue;
|
|
70
|
+
const value = kind === "boolean" ? undefined : argv[index + 1];
|
|
71
|
+
if (reader !== undefined && reader === name && value === "-") {
|
|
72
|
+
if (stdin !== undefined)
|
|
73
|
+
fail("stdin marker '-' may appear only once");
|
|
74
|
+
flags[name] = "";
|
|
75
|
+
stdin = reader;
|
|
76
|
+
index += 1;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
index += assignOption({ token, name, kind, value }, spec, flags, fail);
|
|
80
|
+
}
|
|
81
|
+
return { flags, positionals, ...(stdin === undefined ? {} : { stdin }) };
|
|
82
|
+
}
|
|
@@ -9,3 +9,8 @@ export declare function displayContext(): TextRenderContext;
|
|
|
9
9
|
export declare function resultContext(): TextRenderContext;
|
|
10
10
|
/** One JSON product answer, verbatim from the native value. */
|
|
11
11
|
export declare function writeJson(value: unknown): void;
|
|
12
|
+
/**
|
|
13
|
+
* One product result: JSON writes the untouched native value, text writes the rendered projection,
|
|
14
|
+
* and the native exit classifier's verdict follows.
|
|
15
|
+
*/
|
|
16
|
+
export declare function emit<Result>(output: "text" | "json", result: Result, text: () => string, code: number): number;
|
package/build/src/cli/streams.js
CHANGED
|
@@ -30,3 +30,14 @@ export function resultContext() {
|
|
|
30
30
|
export function writeJson(value) {
|
|
31
31
|
writeStdout(JSON.stringify(value));
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* One product result: JSON writes the untouched native value, text writes the rendered projection,
|
|
35
|
+
* and the native exit classifier's verdict follows.
|
|
36
|
+
*/
|
|
37
|
+
export function emit(output, result, text, code) {
|
|
38
|
+
if (output === "json")
|
|
39
|
+
writeJson(result);
|
|
40
|
+
else
|
|
41
|
+
writeStdout(text());
|
|
42
|
+
return code;
|
|
43
|
+
}
|
|
@@ -3,7 +3,7 @@ import { chmod, lstat, readFile } from "node:fs/promises";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { repairDerivedFile } from "./coordination/durable-file.js";
|
|
5
5
|
import { CONTRACT_DELIVERER_SKILL, CONTRACT_REVIEWER_SKILL, CONTRACT_ONBOARDING_SKILL, renderContractGuidance, } from "./contract-guidance.js";
|
|
6
|
-
import {
|
|
6
|
+
import { executeGit } from "./git/process.js";
|
|
7
7
|
import { worktreePath } from "./git/workspace.js";
|
|
8
8
|
import { appointmentFor, placeRegisterPath } from "./workspace-place.js";
|
|
9
9
|
import { repairNamespaceContext } from "./task/context.js";
|
|
@@ -16,6 +16,12 @@ const SEAT_SKILLS = [
|
|
|
16
16
|
["keiyaku-deliver", CONTRACT_DELIVERER_SKILL],
|
|
17
17
|
["keiyaku-review", CONTRACT_REVIEWER_SKILL],
|
|
18
18
|
];
|
|
19
|
+
const PRIMARY_GENERATED_PATHS = [".keiyaku/.gitignore"];
|
|
20
|
+
const GENERATED_PATHS = [
|
|
21
|
+
...PRIMARY_GENERATED_PATHS,
|
|
22
|
+
".keiyaku/KEIYAKU.md",
|
|
23
|
+
...SEAT_SKILLS.flatMap(([seat]) => [`.agents/skills/${seat}/.gitignore`, `.agents/skills/${seat}/SKILL.md`]),
|
|
24
|
+
];
|
|
19
25
|
export const contractFileEffectSchema = z
|
|
20
26
|
.object({
|
|
21
27
|
kind: z.literal("contract-file"),
|
|
@@ -31,23 +37,24 @@ export const contractFileLagSchema = z
|
|
|
31
37
|
diagnostic: z.string().refine((value) => value.trim() !== ""),
|
|
32
38
|
})
|
|
33
39
|
.strict();
|
|
34
|
-
async function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
async function readTrackedPaths(repository, worktree, paths) {
|
|
41
|
+
const output = await executeGit({ ...repository, effectiveCwd: worktree }, [
|
|
42
|
+
"ls-files",
|
|
43
|
+
"-z",
|
|
44
|
+
"--",
|
|
45
|
+
...paths.map((path) => `:(literal)${path}`),
|
|
46
|
+
]);
|
|
47
|
+
return new Set(output
|
|
48
|
+
.toString("utf8")
|
|
49
|
+
.split("\0")
|
|
50
|
+
.filter((path) => path !== ""));
|
|
44
51
|
}
|
|
45
52
|
function generatedPath(worktree, name) {
|
|
46
53
|
return join(worktree, ".keiyaku", name);
|
|
47
54
|
}
|
|
48
|
-
async function repair(
|
|
55
|
+
async function repair(worktree, relativePath, bytes, tracked) {
|
|
49
56
|
const path = join(worktree, relativePath);
|
|
50
|
-
if (
|
|
57
|
+
if (tracked.has(relativePath))
|
|
51
58
|
throw new Error(`generated path is tracked by Git: ${path}`);
|
|
52
59
|
const action = await repairDerivedFile(path, bytes);
|
|
53
60
|
if (relativePath === ".keiyaku/KEIYAKU.md") {
|
|
@@ -65,7 +72,7 @@ async function isKeiyakuSeatLeaf(worktree, seat) {
|
|
|
65
72
|
const stat = await lstat(sentinel).catch((error) => error.code === "ENOENT" ? undefined : Promise.reject(error));
|
|
66
73
|
return stat?.isFile() === true && !stat.isSymbolicLink() && (await readFile(sentinel, "utf8")) === SEAT_IGNORE_BYTES;
|
|
67
74
|
}
|
|
68
|
-
async function materializeSeatSkill(
|
|
75
|
+
async function materializeSeatSkill(worktree, seat, bytes, tracked) {
|
|
69
76
|
const leaf = `.agents/skills/${seat}`;
|
|
70
77
|
const skill = `${leaf}/SKILL.md`;
|
|
71
78
|
const skillPath = join(worktree, skill);
|
|
@@ -73,8 +80,8 @@ async function materializeSeatSkill(repository, worktree, seat, bytes) {
|
|
|
73
80
|
if (!(await isKeiyakuSeatLeaf(worktree, seat)) && skillExists)
|
|
74
81
|
return [];
|
|
75
82
|
return [
|
|
76
|
-
await repair(
|
|
77
|
-
await repair(
|
|
83
|
+
await repair(worktree, `${leaf}/.gitignore`, SEAT_IGNORE_BYTES, tracked),
|
|
84
|
+
await repair(worktree, skill, bytes, tracked),
|
|
78
85
|
];
|
|
79
86
|
}
|
|
80
87
|
async function materialize(repository, worktree, guidance, namespace) {
|
|
@@ -90,11 +97,14 @@ async function materialize(repository, worktree, guidance, namespace) {
|
|
|
90
97
|
},
|
|
91
98
|
],
|
|
92
99
|
});
|
|
100
|
+
const primaryWorktree = repository.primaryWorktree;
|
|
101
|
+
let tracked;
|
|
93
102
|
try {
|
|
94
|
-
|
|
103
|
+
tracked = await readTrackedPaths(repository, primaryWorktree, worktree === primaryWorktree ? GENERATED_PATHS : PRIMARY_GENERATED_PATHS);
|
|
104
|
+
effects.push(await repair(primaryWorktree, ".keiyaku/.gitignore", PRIMARY_IGNORE_BYTES, tracked));
|
|
95
105
|
}
|
|
96
106
|
catch (error) {
|
|
97
|
-
return failed(
|
|
107
|
+
return failed(primaryWorktree, join(primaryWorktree, ".keiyaku", ".gitignore"), error);
|
|
98
108
|
}
|
|
99
109
|
const stat = await lstat(worktree).catch((error) => {
|
|
100
110
|
if (error.code === "ENOENT")
|
|
@@ -114,19 +124,26 @@ async function materialize(repository, worktree, guidance, namespace) {
|
|
|
114
124
|
],
|
|
115
125
|
};
|
|
116
126
|
}
|
|
117
|
-
const scoped = { ...repository, effectiveCwd: worktree };
|
|
118
127
|
try {
|
|
119
128
|
await repairNamespaceContext(worktree, namespace);
|
|
120
129
|
}
|
|
121
130
|
catch (error) {
|
|
122
131
|
return failed(worktree, join(worktree, ".keiyaku", "namespace", "current"), error);
|
|
123
132
|
}
|
|
133
|
+
if (worktree !== primaryWorktree) {
|
|
134
|
+
try {
|
|
135
|
+
tracked = await readTrackedPaths(repository, worktree, GENERATED_PATHS);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
return failed(worktree, join(worktree, ".keiyaku", ".gitignore"), error);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
124
141
|
for (const [relativePath, bytes] of [
|
|
125
142
|
[".keiyaku/.gitignore", IGNORE_BYTES],
|
|
126
143
|
[".keiyaku/KEIYAKU.md", guidance],
|
|
127
144
|
]) {
|
|
128
145
|
try {
|
|
129
|
-
effects.push(await repair(
|
|
146
|
+
effects.push(await repair(worktree, relativePath, bytes, tracked));
|
|
130
147
|
}
|
|
131
148
|
catch (error) {
|
|
132
149
|
return failed(worktree, join(worktree, relativePath), error);
|
|
@@ -134,7 +151,7 @@ async function materialize(repository, worktree, guidance, namespace) {
|
|
|
134
151
|
}
|
|
135
152
|
for (const [seat, bytes] of SEAT_SKILLS) {
|
|
136
153
|
try {
|
|
137
|
-
effects.push(...(await materializeSeatSkill(
|
|
154
|
+
effects.push(...(await materializeSeatSkill(worktree, seat, bytes, tracked)));
|
|
138
155
|
}
|
|
139
156
|
catch (error) {
|
|
140
157
|
return failed(worktree, join(worktree, ".agents", "skills", seat), error);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { JournalEntry } from "./types.js";
|
|
2
|
-
|
|
3
|
-
export declare function decodeJournalEntry(value: unknown): JournalEntry;
|
|
2
|
+
export declare function validateEntry(value: unknown): JournalEntry;
|
|
4
3
|
export declare function encodeEntry(entry: JournalEntry): string;
|
|
5
4
|
export declare function decodeJournal(journal: string): JournalEntry[];
|
|
@@ -159,7 +159,7 @@ function validateData(kind, value) {
|
|
|
159
159
|
return termsValue(value, path);
|
|
160
160
|
case "deliver": {
|
|
161
161
|
const object = requireRecord(value, path);
|
|
162
|
-
requireKeys(object, ["tenderSnapshot", "integration", "method", "policy"], path);
|
|
162
|
+
requireKeys(object, ["tenderSnapshot", "integration", "method", "policy"], path, ["note"]);
|
|
163
163
|
const integration = requireRecord(object.integration, `${path}.integration`);
|
|
164
164
|
requireKeys(integration, ["predecessor", "snapshot", "changeId"], `${path}.integration`);
|
|
165
165
|
const method = stringValue(object.method, `${path}.method`);
|
|
@@ -168,6 +168,7 @@ function validateData(kind, value) {
|
|
|
168
168
|
const policy = requireRecord(object.policy, `${path}.policy`);
|
|
169
169
|
requireKeys(policy, ["requireBranchesToBeUpToDate"], `${path}.policy`);
|
|
170
170
|
return {
|
|
171
|
+
...(object.note === undefined ? {} : { note: stringValue(object.note, `${path}.note`) }),
|
|
171
172
|
tenderSnapshot: brandedValue(object.tenderSnapshot, `${path}.tenderSnapshot`, snapshotId),
|
|
172
173
|
integration: {
|
|
173
174
|
predecessor: brandedValue(integration.predecessor, `${path}.integration.predecessor`, snapshotId),
|
|
@@ -206,7 +207,7 @@ function validateData(kind, value) {
|
|
|
206
207
|
}
|
|
207
208
|
}
|
|
208
209
|
}
|
|
209
|
-
function validateEntry(value) {
|
|
210
|
+
export function validateEntry(value) {
|
|
210
211
|
const object = requireRecord(value, "entry");
|
|
211
212
|
requireKeys(object, ["v", "kind", "contract", "entry", "at", "data"], "entry", ["actor"]);
|
|
212
213
|
const kind = object.kind;
|
|
@@ -231,10 +232,6 @@ function validateEntry(value) {
|
|
|
231
232
|
}
|
|
232
233
|
return entry;
|
|
233
234
|
}
|
|
234
|
-
/** Validate one in-memory journal value with the persisted-fact authority. */
|
|
235
|
-
export function decodeJournalEntry(value) {
|
|
236
|
-
return validateEntry(value);
|
|
237
|
-
}
|
|
238
235
|
function canonicalValue(value) {
|
|
239
236
|
if (value === null)
|
|
240
237
|
return "null";
|
|
@@ -253,12 +250,9 @@ function canonicalValue(value) {
|
|
|
253
250
|
}
|
|
254
251
|
throw new AuthorityCorruptionError("canonical JSON accepts only JSON values");
|
|
255
252
|
}
|
|
256
|
-
function canonicalJson(value) {
|
|
257
|
-
return canonicalValue(value);
|
|
258
|
-
}
|
|
259
253
|
export function encodeEntry(entry) {
|
|
260
254
|
const validated = validateEntry(entry);
|
|
261
|
-
return `${
|
|
255
|
+
return `${canonicalValue(validated)}\n`;
|
|
262
256
|
}
|
|
263
257
|
function decodeEntry(line) {
|
|
264
258
|
if (line.includes("\r") || line.includes("\n\n"))
|
|
@@ -274,7 +268,7 @@ function decodeEntry(line) {
|
|
|
274
268
|
throw new AuthorityCorruptionError("journal entry is not valid JSON", { cause: error });
|
|
275
269
|
}
|
|
276
270
|
const entry = validateEntry(value);
|
|
277
|
-
if (
|
|
271
|
+
if (canonicalValue(value) !== body)
|
|
278
272
|
throw new AuthorityCorruptionError("journal entry is not canonical");
|
|
279
273
|
return entry;
|
|
280
274
|
}
|
|
@@ -73,6 +73,7 @@ export type BindData = Readonly<{
|
|
|
73
73
|
}>;
|
|
74
74
|
export type AmendData = ContractTerms;
|
|
75
75
|
export type DeliverData = Readonly<{
|
|
76
|
+
note?: string;
|
|
76
77
|
tenderSnapshot: SnapshotId;
|
|
77
78
|
integration: Readonly<{
|
|
78
79
|
predecessor: SnapshotId;
|
|
@@ -84,7 +85,7 @@ export type DeliverData = Readonly<{
|
|
|
84
85
|
requireBranchesToBeUpToDate: boolean;
|
|
85
86
|
}>;
|
|
86
87
|
}>;
|
|
87
|
-
|
|
88
|
+
type CurrentIntegration = DeliverData["integration"];
|
|
88
89
|
export type ReintegratedData = Readonly<{
|
|
89
90
|
predecessor: SnapshotId;
|
|
90
91
|
snapshot: SnapshotId;
|
|
@@ -118,13 +119,26 @@ type JournalEnvelope<Kind extends string, Data> = Readonly<{
|
|
|
118
119
|
export type BindEntry = JournalEnvelope<"bind", BindData>;
|
|
119
120
|
type AmendEntry = JournalEnvelope<"amend", AmendData>;
|
|
120
121
|
type DeliverEntry = JournalEnvelope<"deliver", DeliverData>;
|
|
121
|
-
|
|
122
|
+
type ReintegratedEntry = JournalEnvelope<"reintegrated", ReintegratedData>;
|
|
122
123
|
export type AttestationEntry = JournalEnvelope<"attestation", AttestationData>;
|
|
123
124
|
type ClaimedEntry = JournalEnvelope<"claimed", ClaimedData>;
|
|
124
125
|
export type ArcEntry = JournalEnvelope<"arc", ArcData>;
|
|
125
126
|
type AbandonedEntry = JournalEnvelope<"abandoned", AbandonedData>;
|
|
126
127
|
export type JournalEntry = BindEntry | AmendEntry | DeliverEntry | ReintegratedEntry | AttestationEntry | ClaimedEntry | ArcEntry | AbandonedEntry;
|
|
127
128
|
export type FactKind = JournalEntry["kind"];
|
|
129
|
+
/**
|
|
130
|
+
* The one journal-envelope constructor for every verb offering a single fact: entry identity, the
|
|
131
|
+
* invoking decision input's Contract, timestamp, and optional actor, and the verb's own payload.
|
|
132
|
+
*/
|
|
133
|
+
export declare function journalEntry<Kind extends FactKind, Input extends Readonly<{
|
|
134
|
+
contractId: ContractId;
|
|
135
|
+
at: string;
|
|
136
|
+
actor?: ActorId;
|
|
137
|
+
}>>(kind: Kind, input: Input, entry: EntryUlid, data: Extract<JournalEntry, {
|
|
138
|
+
kind: Kind;
|
|
139
|
+
}>["data"]): Extract<JournalEntry, {
|
|
140
|
+
kind: Kind;
|
|
141
|
+
}>;
|
|
128
142
|
type ContractTerminal = ClaimedEntry | AbandonedEntry;
|
|
129
143
|
export type ContractState = Readonly<{
|
|
130
144
|
id: ContractId;
|
|
@@ -64,3 +64,18 @@ export function gate(value) {
|
|
|
64
64
|
}
|
|
65
65
|
return value;
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* The one journal-envelope constructor for every verb offering a single fact: entry identity, the
|
|
69
|
+
* invoking decision input's Contract, timestamp, and optional actor, and the verb's own payload.
|
|
70
|
+
*/
|
|
71
|
+
export function journalEntry(kind, input, entry, data) {
|
|
72
|
+
return {
|
|
73
|
+
v: 1,
|
|
74
|
+
kind,
|
|
75
|
+
contract: input.contractId,
|
|
76
|
+
entry,
|
|
77
|
+
at: input.at,
|
|
78
|
+
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
79
|
+
data,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { activeContract } from "../facts/observation.js";
|
|
2
|
+
import { journalEntry } from "../facts/types.js";
|
|
2
3
|
export function decideAbandon({ input, attempt, observation, }) {
|
|
3
4
|
const id = input.contractId;
|
|
4
5
|
const current = activeContract(observation, id);
|
|
5
6
|
if ("kind" in current)
|
|
6
7
|
return { kind: "refused", refusal: current };
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
kind: "abandoned",
|
|
10
|
-
contract: id,
|
|
11
|
-
entry: attempt.entryUlids[0],
|
|
12
|
-
at: input.at,
|
|
13
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
14
|
-
data: input.note === undefined ? {} : { note: input.note },
|
|
15
|
-
};
|
|
8
|
+
const data = input.note === undefined ? {} : { note: input.note };
|
|
9
|
+
const abandoned = journalEntry("abandoned", input, attempt.entryUlids[0], data);
|
|
16
10
|
return { kind: "offer", offer: { facts: [{ contractId: id, entries: [abandoned] }] } };
|
|
17
11
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { prerequisitesReach, samePrerequisites } from "../facts/eligibility.js";
|
|
2
2
|
import { activeContract, prerequisiteStatus } from "../facts/observation.js";
|
|
3
|
+
import { journalEntry } from "../facts/types.js";
|
|
3
4
|
export function decideAmend({ input, attempt, observation, }) {
|
|
4
5
|
const id = input.contractId;
|
|
5
6
|
const current = activeContract(observation, id);
|
|
@@ -28,14 +29,6 @@ export function decideAmend({ input, attempt, observation, }) {
|
|
|
28
29
|
if (prerequisitesReach(id, data.after, observation)) {
|
|
29
30
|
return { kind: "refused", refusal: { kind: "cyclic-prerequisite", contractId: id } };
|
|
30
31
|
}
|
|
31
|
-
const entry =
|
|
32
|
-
v: 1,
|
|
33
|
-
kind: "amend",
|
|
34
|
-
contract: id,
|
|
35
|
-
entry: attempt.entryUlids[0],
|
|
36
|
-
at: input.at,
|
|
37
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
38
|
-
data,
|
|
39
|
-
};
|
|
32
|
+
const entry = journalEntry("amend", input, attempt.entryUlids[0], data);
|
|
40
33
|
return { kind: "offer", offer: { facts: [{ contractId: id, entries: [entry] }] } };
|
|
41
34
|
}
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
import { activeContract } from "../facts/observation.js";
|
|
2
|
+
import { journalEntry } from "../facts/types.js";
|
|
2
3
|
export function decideArc({ input, attempt, observation, }) {
|
|
3
4
|
const id = input.contractId;
|
|
4
5
|
const current = activeContract(observation, id);
|
|
5
6
|
if ("kind" in current)
|
|
6
7
|
return { kind: "refused", refusal: current };
|
|
7
|
-
const arc = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
at: input.at,
|
|
13
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
14
|
-
data: {
|
|
15
|
-
seq: (current.currentArc?.data.seq ?? 0) + 1,
|
|
16
|
-
title: input.data.title,
|
|
17
|
-
body: input.data.body,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
8
|
+
const arc = journalEntry("arc", input, attempt.entryUlids[0], {
|
|
9
|
+
seq: (current.currentArc?.data.seq ?? 0) + 1,
|
|
10
|
+
title: input.data.title,
|
|
11
|
+
body: input.data.body,
|
|
12
|
+
});
|
|
20
13
|
return {
|
|
21
14
|
kind: "offer",
|
|
22
15
|
offer: { facts: [{ contractId: id, entries: [arc] }] },
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { activeContract } from "../facts/observation.js";
|
|
2
|
+
import { journalEntry } from "../facts/types.js";
|
|
2
3
|
export function decideAttestation({ input, attempt, observation, }) {
|
|
3
4
|
const state = activeContract(observation, input.contractId);
|
|
4
5
|
if ("kind" in state)
|
|
@@ -8,15 +9,7 @@ export function decideAttestation({ input, attempt, observation, }) {
|
|
|
8
9
|
}
|
|
9
10
|
if (input.preparation.kind === "refused")
|
|
10
11
|
return { kind: "refused", refusal: input.preparation.refusal };
|
|
11
|
-
const attestation =
|
|
12
|
-
v: 1,
|
|
13
|
-
kind: "attestation",
|
|
14
|
-
contract: input.contractId,
|
|
15
|
-
entry: attempt.entryUlids[0],
|
|
16
|
-
at: input.at,
|
|
17
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
18
|
-
data: input.preparation.data,
|
|
19
|
-
};
|
|
12
|
+
const attestation = journalEntry("attestation", input, attempt.entryUlids[0], input.preparation.data);
|
|
20
13
|
return {
|
|
21
14
|
kind: "offer",
|
|
22
15
|
offer: { facts: [{ contractId: input.contractId, entries: [attestation] }] },
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { contractState, prerequisiteStatus } from "../facts/observation.js";
|
|
2
|
+
import { journalEntry } from "../facts/types.js";
|
|
2
3
|
export function decideBind({ input, attempt, observation, }) {
|
|
3
4
|
const id = input.contractId;
|
|
4
5
|
const current = contractState(observation, id);
|
|
@@ -13,14 +14,6 @@ export function decideBind({ input, attempt, observation, }) {
|
|
|
13
14
|
if (prerequisites === "unknown") {
|
|
14
15
|
return { kind: "refused", refusal: { kind: "unknown-prerequisite", contractId: id } };
|
|
15
16
|
}
|
|
16
|
-
const bind =
|
|
17
|
-
v: 1,
|
|
18
|
-
kind: "bind",
|
|
19
|
-
contract: id,
|
|
20
|
-
entry: attempt.entryUlids[0],
|
|
21
|
-
at: input.at,
|
|
22
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
23
|
-
data,
|
|
24
|
-
};
|
|
17
|
+
const bind = journalEntry("bind", input, attempt.entryUlids[0], data);
|
|
25
18
|
return { kind: "offer", offer: { facts: [{ contractId: id, entries: [bind] }] } };
|
|
26
19
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { activeContract, documentIsCurrent } from "../facts/observation.js";
|
|
2
|
+
import { journalEntry } from "../facts/types.js";
|
|
2
3
|
export function decideDeliver({ input, attempt, observation, }) {
|
|
3
4
|
const state = activeContract(observation, input.contractId);
|
|
4
5
|
if ("kind" in state)
|
|
@@ -11,14 +12,6 @@ export function decideDeliver({ input, attempt, observation, }) {
|
|
|
11
12
|
}
|
|
12
13
|
if (input.preparation.kind === "refused")
|
|
13
14
|
return { kind: "refused", refusal: input.preparation.refusal };
|
|
14
|
-
const deliver =
|
|
15
|
-
v: 1,
|
|
16
|
-
kind: "deliver",
|
|
17
|
-
contract: input.contractId,
|
|
18
|
-
entry: attempt.entryUlids[0],
|
|
19
|
-
at: input.at,
|
|
20
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
21
|
-
data: input.preparation.data,
|
|
22
|
-
};
|
|
15
|
+
const deliver = journalEntry("deliver", input, attempt.entryUlids[0], input.preparation.data);
|
|
23
16
|
return { kind: "offer", offer: { facts: [{ contractId: input.contractId, entries: [deliver] }] } };
|
|
24
17
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { gateReports } from "../facts/gate.js";
|
|
2
2
|
import { activeContract, contractState } from "../facts/observation.js";
|
|
3
|
+
import { journalEntry } from "../facts/types.js";
|
|
3
4
|
function unmetPrerequisites(prerequisites, observation) {
|
|
4
5
|
const unmet = [];
|
|
5
6
|
for (const contractId of prerequisites) {
|
|
@@ -43,15 +44,7 @@ export function decidePlacement({ input, attempt, observation, }) {
|
|
|
43
44
|
},
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
|
-
const claimed = {
|
|
47
|
-
v: 1,
|
|
48
|
-
kind: "claimed",
|
|
49
|
-
contract: id,
|
|
50
|
-
entry: attempt.entryUlids[0],
|
|
51
|
-
at: input.at,
|
|
52
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
53
|
-
data: { delivery: delivery.entry },
|
|
54
|
-
};
|
|
47
|
+
const claimed = journalEntry("claimed", input, attempt.entryUlids[0], { delivery: delivery.entry });
|
|
55
48
|
return {
|
|
56
49
|
kind: "offer",
|
|
57
50
|
offer: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DecideInput, OfferDecision, Preparation } from "../decide.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type ActorId, type ContractId, type ReintegratedData } from "../facts/types.js";
|
|
3
3
|
export type ReintegrateInput<Failure = never> = Readonly<{
|
|
4
4
|
contractId: ContractId;
|
|
5
5
|
actor?: ActorId;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { activeContract } from "../facts/observation.js";
|
|
2
|
+
import { journalEntry } from "../facts/types.js";
|
|
2
3
|
export function decideReintegrate({ input, attempt, observation, }) {
|
|
3
4
|
const state = activeContract(observation, input.contractId);
|
|
4
5
|
if ("kind" in state)
|
|
@@ -8,15 +9,7 @@ export function decideReintegrate({ input, attempt, observation, }) {
|
|
|
8
9
|
}
|
|
9
10
|
if (input.preparation.kind === "refused")
|
|
10
11
|
return { kind: "refused", refusal: input.preparation.refusal };
|
|
11
|
-
const reintegrated =
|
|
12
|
-
v: 1,
|
|
13
|
-
kind: "reintegrated",
|
|
14
|
-
contract: input.contractId,
|
|
15
|
-
entry: attempt.entryUlids[0],
|
|
16
|
-
at: input.at,
|
|
17
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
18
|
-
data: input.preparation.data,
|
|
19
|
-
};
|
|
12
|
+
const reintegrated = journalEntry("reintegrated", input, attempt.entryUlids[0], input.preparation.data);
|
|
20
13
|
return {
|
|
21
14
|
kind: "offer",
|
|
22
15
|
offer: { facts: [{ contractId: input.contractId, entries: [reintegrated] }] },
|
|
@@ -33,5 +33,5 @@ export declare function publishDispatch(input: Readonly<{
|
|
|
33
33
|
contractId: ContractId;
|
|
34
34
|
}>): Promise<DispatchPublication>;
|
|
35
35
|
export { dispatchAssociationSchema, NO_DISPATCH_ASSOCIATION, parseDispatchAssociation, type DispatchAssociation, } from "./association.js";
|
|
36
|
-
/** Read
|
|
37
|
-
export declare function
|
|
36
|
+
/** Read selected associations in one targeted observation, isolating per-identity decoding failures. */
|
|
37
|
+
export declare function observeDispatchAssociations(repository: GitRepository | undefined, akuIds: readonly AkuId[]): Promise<ReadonlyMap<AkuId, DispatchAssociation>>;
|
|
@@ -4,7 +4,7 @@ import { contractId } from "../core/facts/types.js";
|
|
|
4
4
|
import { parseAkuId } from "../akuma/identity.js";
|
|
5
5
|
import { appendPrivateStateSeatClose, confirmPrivateStatePublication, mergePrivateStateSeatClose, withPrivateStatePublicationSeat, } from "../git/private-state-seat.js";
|
|
6
6
|
import { GIT_FORMAT_BYTES, GIT_FORMAT_PATH, GIT_REF, readBlob, readGitPaths, updateGitTree, updateRefsAtomically, writeBlob, writeStateCommit, } from "../git/repository.js";
|
|
7
|
-
import { withGitDecodeChannel, withGitReadObservation } from "../git/read-observation.js";
|
|
7
|
+
import { withGitDecodeChannel, withGitReadObservation, withGitTargetedReadObservation, } from "../git/read-observation.js";
|
|
8
8
|
import { NO_DISPATCH_ASSOCIATION } from "./association.js";
|
|
9
9
|
const DISPATCH_ROOT = "dispatch";
|
|
10
10
|
const DISPATCH_PREFIX = `${DISPATCH_ROOT}/`;
|
|
@@ -187,18 +187,40 @@ export async function publishDispatch(input) {
|
|
|
187
187
|
}));
|
|
188
188
|
}
|
|
189
189
|
export { dispatchAssociationSchema, NO_DISPATCH_ASSOCIATION, parseDispatchAssociation, } from "./association.js";
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return NO_DISPATCH_ASSOCIATION;
|
|
190
|
+
/** Read selected associations in one targeted observation, isolating per-identity decoding failures. */
|
|
191
|
+
export async function observeDispatchAssociations(repository, akuIds) {
|
|
192
|
+
const requested = [...new Set(akuIds.map((akuId) => parseAkuId(akuId).id))];
|
|
193
|
+
const associations = new Map(requested.map((akuId) => [akuId, NO_DISPATCH_ASSOCIATION]));
|
|
194
|
+
if (repository === undefined || requested.length === 0)
|
|
195
|
+
return associations;
|
|
197
196
|
try {
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
await withGitDecodeChannel(repository, (channel) => withGitTargetedReadObservation(repository, channel, { paths: requested.map(pathFor) }, async (observation) => {
|
|
198
|
+
const entries = requested.map((akuId) => {
|
|
199
|
+
const path = pathFor(akuId);
|
|
200
|
+
return [akuId, path, observation.snapshot.paths.get(path)];
|
|
201
|
+
});
|
|
202
|
+
const blobs = await observation.readBlobs(entries.flatMap(([, , entry]) => (entry?.type === "blob" ? [entry.oid] : [])));
|
|
203
|
+
for (const [akuId, path, entry] of entries) {
|
|
204
|
+
if (entry === undefined)
|
|
205
|
+
continue;
|
|
206
|
+
try {
|
|
207
|
+
if (entry.type !== "blob")
|
|
208
|
+
corruption(`Dispatch path is not a blob: ${path}`);
|
|
209
|
+
const result = blobs.get(entry.oid);
|
|
210
|
+
if (result?.kind !== "present")
|
|
211
|
+
corruption(`missing Dispatch Git object: ${path}`);
|
|
212
|
+
associations.set(akuId, { kind: "associated", contractId: decode(path, result.bytes).contractId });
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
associations.set(akuId, { kind: "failed", diagnostic: diagnostic(error) });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}));
|
|
200
219
|
}
|
|
201
220
|
catch (error) {
|
|
202
|
-
|
|
221
|
+
const message = diagnostic(error);
|
|
222
|
+
for (const akuId of requested)
|
|
223
|
+
associations.set(akuId, { kind: "failed", diagnostic: message });
|
|
203
224
|
}
|
|
225
|
+
return associations;
|
|
204
226
|
}
|