@astrosheep/keiyaku 4.5.7 → 4.5.8
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 +10 -0
- 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/opencode.js +3 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +10 -9
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +22 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +35 -96
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +28 -49
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +21 -15
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +148 -89
- package/build/src/akuma/abort.d.ts +2 -1
- package/build/src/akuma/abort.js +6 -23
- package/build/src/akuma/akuma-handle.js +4 -2
- package/build/src/akuma/akuma-observe.d.ts +2 -0
- package/build/src/akuma/akuma-observe.js +1 -0
- package/build/src/akuma/akuma-product.js +9 -7
- package/build/src/akuma/akuma.d.ts +372 -9
- package/build/src/akuma/akuma.js +31 -1
- package/build/src/akuma/allowed.d.ts +1 -1
- package/build/src/akuma/allowed.js +1 -0
- package/build/src/akuma/body.d.ts +6 -4
- package/build/src/akuma/body.js +5 -3
- package/build/src/akuma/call-request.d.ts +80 -0
- package/build/src/akuma/call-request.js +211 -0
- package/build/src/akuma/heart/facts.d.ts +6 -78
- package/build/src/akuma/heart/index.d.ts +1 -1
- package/build/src/akuma/heart/request-authority.d.ts +5 -4
- package/build/src/akuma/heart/request-authority.js +20 -34
- package/build/src/akuma/heart/request-rows.js +12 -23
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +5 -13
- package/build/src/akuma/index.d.ts +1 -1
- package/build/src/akuma/index.js +1 -1
- package/build/src/akuma/projection-read.d.ts +1 -0
- package/build/src/akuma/projection-read.js +8 -1
- package/build/src/akuma/projection.d.ts +856 -137
- package/build/src/akuma/projection.js +190 -0
- package/build/src/akuma/provider.d.ts +30 -3
- package/build/src/akuma/provider.js +104 -0
- package/build/src/akuma/providers/acp/core.d.ts +2 -2
- package/build/src/akuma/providers/acp/core.js +13 -6
- package/build/src/akuma/providers/acp/index.js +5 -4
- package/build/src/akuma/providers/claude/index.d.ts +3 -3
- package/build/src/akuma/providers/claude/index.js +16 -5
- package/build/src/akuma/providers/codex-app-server/events.js +1 -1
- package/build/src/akuma/providers/codex-app-server/index.js +18 -6
- package/build/src/akuma/providers/grok-build/index.js +5 -4
- package/build/src/akuma/providers/opencode-sdk/index.js +66 -25
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +3 -2
- package/build/src/akuma/providers/opencode-sdk/session.js +28 -11
- package/build/src/akuma/providers/pi/index.js +42 -14
- package/build/src/akuma/request-lifecycle.d.ts +3 -9
- package/build/src/akuma/request-lifecycle.js +4 -4
- package/build/src/akuma/request-rendezvous.d.ts +26 -0
- package/build/src/akuma/request-rendezvous.js +100 -0
- package/build/src/akuma/request-serve.d.ts +5 -65
- package/build/src/akuma/request-serve.js +81 -208
- package/build/src/akuma/request-wire.d.ts +109 -115
- package/build/src/akuma/request-wire.js +63 -318
- package/build/src/akuma/requests.d.ts +19 -47
- package/build/src/akuma/requests.js +51 -107
- package/build/src/akuma/turn-drive.d.ts +5 -3
- package/build/src/akuma/turn-drive.js +32 -10
- package/build/src/akuma-body.d.ts +7 -2
- package/build/src/akuma-body.js +68 -46
- package/build/src/cli/accepted.d.ts +1 -1
- package/build/src/cli/accepted.js +2 -2
- package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
- package/build/src/cli/commands/akuma-invoke.js +17 -9
- package/build/src/cli/commands/akuma.js +7 -7
- package/build/src/cli/commands/contract-invoke.d.ts +3 -2
- package/build/src/cli/commands/contract-invoke.js +26 -19
- package/build/src/cli/commands/contract.d.ts +13 -13
- package/build/src/cli/commands/contract.js +32 -17
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +1 -1
- package/build/src/cli/commands/task-invoke.d.ts +3 -0
- package/build/src/cli/commands/task-invoke.js +23 -140
- package/build/src/cli/commands/task.js +54 -20
- package/build/src/cli/invoke.js +39 -25
- package/build/src/cli/main.js +2 -1
- package/build/src/cli/parse.d.ts +2 -2
- package/build/src/cli/parse.js +37 -22
- package/build/src/cli/render/akuma-activity.d.ts +4 -1
- package/build/src/cli/render/akuma-activity.js +45 -30
- package/build/src/cli/render/akuma-tool.d.ts +5 -1
- package/build/src/cli/render/akuma.js +5 -9
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/catalog.js +80 -21
- package/build/src/cli/render/contract-observation.d.ts +2 -0
- package/build/src/cli/render/contract-observation.js +11 -0
- package/build/src/cli/render/contract.js +25 -65
- package/build/src/cli/render/kanshi-akuma.d.ts +8 -0
- package/build/src/cli/render/kanshi-akuma.js +111 -0
- package/build/src/cli/render/kanshi.js +108 -213
- package/build/src/cli/render/receipt.d.ts +1 -2
- package/build/src/cli/render/receipt.js +76 -26
- package/build/src/cli/render/refusal.js +2 -10
- package/build/src/cli/render/region.js +5 -2
- package/build/src/cli/render/settings.d.ts +1 -1
- package/build/src/cli/render/settings.js +27 -8
- package/build/src/cli/render/task.js +22 -5
- package/build/src/cli/render/terminal.d.ts +28 -0
- package/build/src/cli/render/terminal.js +65 -0
- package/build/src/cli/result.d.ts +3 -3
- package/build/src/cli/runtime.js +3 -1
- package/build/src/cli/selectors.d.ts +2 -1
- package/build/src/cli/selectors.js +4 -3
- package/build/src/cli/square-edge.js +120 -36
- package/build/src/cli/usage.js +2 -1
- package/build/src/contract-guidance.d.ts +5 -0
- package/build/src/contract-guidance.js +121 -0
- package/build/src/contract-worktree.d.ts +0 -1
- package/build/src/contract-worktree.js +32 -83
- package/build/src/coordination/sqlite-transaction-lock.d.ts +1 -0
- package/build/src/coordination/sqlite-transaction-lock.js +5 -0
- package/build/src/core/facts/codec.d.ts +2 -0
- package/build/src/core/facts/codec.js +4 -0
- package/build/src/core/verbs/placement.d.ts +6 -1
- package/build/src/core/verbs/placement.js +5 -3
- package/build/src/dispatch/index.d.ts +0 -2
- package/build/src/dispatch/index.js +54 -55
- package/build/src/git/admission.js +2 -2
- package/build/src/git/hooks.d.ts +9 -15
- package/build/src/git/hooks.js +23 -317
- package/build/src/git/nuke.d.ts +2 -1
- package/build/src/git/nuke.js +36 -18
- package/build/src/git/private-state-seat.d.ts +12 -0
- package/build/src/git/private-state-seat.js +39 -0
- package/build/src/git/process.d.ts +6 -0
- package/build/src/git/process.js +19 -7
- package/build/src/git/read-observation.js +29 -20
- package/build/src/git/reconcile.d.ts +11 -0
- package/build/src/git/reconcile.js +64 -11
- package/build/src/git/repository.d.ts +6 -2
- package/build/src/git/repository.js +8 -0
- package/build/src/git/target-placement.d.ts +1 -0
- package/build/src/git/target-placement.js +5 -0
- package/build/src/git/tender.d.ts +1 -0
- package/build/src/git/terminal-reconcile.d.ts +1 -1
- package/build/src/git/terminal-reconcile.js +22 -20
- package/build/src/git/workspace.d.ts +14 -0
- package/build/src/git/workspace.js +44 -0
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +16 -16
- package/build/src/kanshi/report.d.ts +2 -2
- package/build/src/library/address.d.ts +9 -3
- package/build/src/library/address.js +3 -2
- package/build/src/library/akuma-creation.d.ts +4 -3
- package/build/src/library/akuma-creation.js +19 -13
- package/build/src/library/audit.d.ts +1 -1
- package/build/src/library/audit.js +5 -3
- package/build/src/library/catalog.d.ts +3 -1
- package/build/src/library/catalog.js +20 -6
- package/build/src/library/composition.d.ts +371 -0
- package/build/src/library/composition.js +28 -0
- package/build/src/library/configuration.js +8 -2
- package/build/src/library/continuation.js +66 -30
- package/build/src/library/contract-bind.js +10 -2
- package/build/src/library/contract-forwarding-reconciliation-result.d.ts +96 -0
- package/build/src/library/contract-forwarding-reconciliation-result.js +83 -0
- package/build/src/library/contract-forwarding-result.d.ts +6723 -0
- package/build/src/library/contract-forwarding-result.js +521 -0
- package/build/src/library/contract-forwarding.d.ts +72 -0
- package/build/src/library/contract-forwarding.js +125 -0
- package/build/src/library/contract-handle.d.ts +36 -0
- package/build/src/library/contract-handle.js +313 -0
- package/build/src/library/contract-operations.d.ts +1044 -67
- package/build/src/library/contract-operations.js +190 -118
- package/build/src/library/contract.d.ts +11 -32
- package/build/src/library/contract.js +16 -289
- package/build/src/library/fleet-result.d.ts +1454 -0
- package/build/src/library/fleet-result.js +96 -0
- package/build/src/library/fleet.d.ts +112 -54
- package/build/src/library/fleet.js +211 -71
- package/build/src/library/input.d.ts +2 -0
- package/build/src/library/input.js +4 -0
- package/build/src/library/keiyaku.d.ts +371 -20
- package/build/src/library/keiyaku.js +8 -21
- package/build/src/library/mutation.d.ts +3 -3
- package/build/src/library/mutation.js +5 -9
- package/build/src/library/nuke.d.ts +1 -1
- package/build/src/library/nuke.js +4 -3
- package/build/src/library/reconcile.d.ts +4 -0
- package/build/src/library/reconcile.js +2 -0
- package/build/src/library/refusal.d.ts +0 -9
- package/build/src/library/refusal.js +0 -7
- package/build/src/protocol/amend.js +56 -50
- package/build/src/protocol/attempt.d.ts +2 -0
- package/build/src/protocol/attempt.js +8 -1
- package/build/src/protocol/completion.js +7 -0
- package/build/src/protocol/deliver.js +6 -2
- package/build/src/protocol/operations.d.ts +4 -1
- package/build/src/protocol/operations.js +5 -2
- package/build/src/protocol/placement.d.ts +1 -0
- package/build/src/protocol/placement.js +52 -38
- package/build/src/protocol/read/observation.d.ts +1 -4
- package/build/src/protocol/read/observation.js +2 -15
- package/build/src/protocol/reintegrate.js +62 -58
- package/build/src/protocol/review.js +5 -0
- package/build/src/protocol/run.js +17 -13
- package/build/src/runtime/proc/run.d.ts +8 -0
- package/build/src/runtime/proc/run.js +27 -0
- package/build/src/runtime/proc/termination.js +26 -22
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settlement/holder.d.ts +2 -1
- package/build/src/settlement/holder.js +15 -4
- package/build/src/settlement/settle.js +99 -33
- package/build/src/task/board.d.ts +68 -27
- package/build/src/task/board.js +31 -1
- package/build/src/task/catalog.d.ts +4 -0
- package/build/src/task/catalog.js +23 -0
- package/build/src/task/compose-language.js +33 -7
- package/build/src/task/compose-parser.d.ts +1 -1
- package/build/src/task/compose-parser.js +1 -1
- package/build/src/task/compose.js +2 -0
- package/build/src/task/index.d.ts +12 -4
- package/build/src/task/index.js +97 -16
- package/build/src/task/mutation-result.d.ts +923 -0
- package/build/src/task/mutation-result.js +140 -0
- package/build/src/task/mutation.d.ts +552 -28
- package/build/src/task/mutation.js +304 -97
- package/build/src/task/operations.d.ts +1 -4
- package/build/src/task/operations.js +0 -6
- package/build/src/task/public.d.ts +2 -0
- package/build/src/task/public.js +1 -0
- package/build/src/workspace-place.d.ts +7 -2
- package/build/src/workspace-place.js +34 -24
- package/build/src/world.d.ts +1 -0
- package/build/src/world.js +11 -0
- package/package.json +8 -6
- package/build/src/akuma/request-execution.d.ts +0 -8
- package/build/src/akuma/request-execution.js +0 -98
|
@@ -3,94 +3,18 @@ import { join } from "node:path";
|
|
|
3
3
|
import { acquireSqliteTransactionLock } from "./coordination/sqlite-transaction-lock.js";
|
|
4
4
|
import { repairDerivedFile } from "./coordination/durable-file.js";
|
|
5
5
|
import { contractId } from "./core/facts/types.js";
|
|
6
|
+
import { CONTRACT_DELIVERER_SKILL, CONTRACT_REVIEWER_SKILL, renderContractAppointment, renderContractGuidance, } from "./contract-guidance.js";
|
|
6
7
|
import { worktreeGitDirectory, worktreeRoot } from "./git/repository.js";
|
|
7
8
|
import { GitPlumbingError, runGit } from "./git/process.js";
|
|
8
9
|
import { worktreePath } from "./git/workspace.js";
|
|
9
10
|
import { appointmentFor, placeRegisterPath } from "./workspace-place.js";
|
|
10
11
|
const IGNORE_BYTES = ".gitignore\nKEIYAKU.md\n";
|
|
11
12
|
const PRIMARY_IGNORE_BYTES = "*\n!settings.json\n!tasks/\n!tasks/**\n";
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return [
|
|
18
|
-
"## Arc",
|
|
19
|
-
"",
|
|
20
|
-
"### Sequence",
|
|
21
|
-
"",
|
|
22
|
-
String(arc.seq),
|
|
23
|
-
"",
|
|
24
|
-
"### Title",
|
|
25
|
-
"",
|
|
26
|
-
arc.title.trimEnd(),
|
|
27
|
-
"",
|
|
28
|
-
"### Objective",
|
|
29
|
-
"",
|
|
30
|
-
arc.objective.trimEnd(),
|
|
31
|
-
"",
|
|
32
|
-
"### Brief",
|
|
33
|
-
"",
|
|
34
|
-
arc.brief.trimEnd(),
|
|
35
|
-
].join("\n");
|
|
36
|
-
}
|
|
37
|
-
const FULFILLMENT = [
|
|
38
|
-
"## Fulfillment",
|
|
39
|
-
"",
|
|
40
|
-
"### Appointment",
|
|
41
|
-
"",
|
|
42
|
-
"Each commission names exactly one seat: Deliverer or Reviewer.",
|
|
43
|
-
"If no seat was named, stop and ask the caller. Never infer it.",
|
|
44
|
-
"",
|
|
45
|
-
"### Worktree",
|
|
46
|
-
"",
|
|
47
|
-
"This file is a derived view of the journal-authoritative Contract. Never edit it to change the Contract.",
|
|
48
|
-
"Treat the directory containing `.keiyaku/KEIYAKU.md` as the Contract worktree root.",
|
|
49
|
-
"Read the complete Contract before acting and keep work inside that worktree.",
|
|
50
|
-
"",
|
|
51
|
-
"### Deliverer",
|
|
52
|
-
"",
|
|
53
|
-
"Re-read this file on each wake-up; it may have been updated between sessions.",
|
|
54
|
-
"Implement and verify the Objective under the Design, Region, and Criteria in this Contract.",
|
|
55
|
-
"Region is a rough intent, not a hard boundary — natural ripple outside it is fine and not a blocker.",
|
|
56
|
-
"When an Arc is active, stay within that current chapter.",
|
|
57
|
-
"If you discover a contradiction with this Contract or an unclosed point in its terms,",
|
|
58
|
-
"stop and report it before continuing.",
|
|
59
|
-
"",
|
|
60
|
-
"For work requiring three or more steps, prefer `keiyaku task -C <worktree>` to organize and manage Tasks.",
|
|
61
|
-
"Promptly update progress for Tasks already present in the current worktree.",
|
|
62
|
-
"",
|
|
63
|
-
"Deliver from this worktree. A clean worktree delivers HEAD; uncommitted work",
|
|
64
|
-
"needs `deliver --include-dirty`, which captures the final non-ignored tree and",
|
|
65
|
-
"stages or commits nothing. If deliver reports a conflict, run",
|
|
66
|
-
"`deliver --materialize-conflict`, resolve the conflicted files, stage them,",
|
|
67
|
-
"and deliver again; while the merge stays uncommitted that continuation uses",
|
|
68
|
-
"`--include-dirty`. Unresolved paths always refuse.",
|
|
69
|
-
"",
|
|
70
|
-
"### Reviewer",
|
|
71
|
-
"",
|
|
72
|
-
"Re-read this file on each wake-up; it may have been updated between sessions.",
|
|
73
|
-
"Review the complete current worktree snapshot against this Contract. Do not modify it.",
|
|
74
|
-
"Understand the original intent behind the Objective, not just its literal text.",
|
|
75
|
-
"Region is a rough intent, not a hard boundary — natural ripple outside it is not a blocker.",
|
|
76
|
-
"Compare each Criterion individually against the delivered work.",
|
|
77
|
-
"Consolidate findings by root cause — group symptoms that share an underlying issue",
|
|
78
|
-
"rather than listing each occurrence separately.",
|
|
79
|
-
"Dig to the architectural or structural root; flag it directly rather than routing around it.",
|
|
80
|
-
"If you discover a contradiction within the Contract or an unclosed point in its terms,",
|
|
81
|
-
"report it as a finding.",
|
|
82
|
-
"Report covered Criteria, findings, and missing evidence.",
|
|
83
|
-
].join("\n");
|
|
84
|
-
export function renderContractGuidance(state) {
|
|
85
|
-
return [
|
|
86
|
-
appointmentBytes(state.id).trimEnd(),
|
|
87
|
-
state.terms.document.bytes.trimEnd(),
|
|
88
|
-
...(state.currentArc === undefined ? [] : [renderArc(state.currentArc.data)]),
|
|
89
|
-
FULFILLMENT,
|
|
90
|
-
]
|
|
91
|
-
.join("\n\n")
|
|
92
|
-
.concat("\n");
|
|
93
|
-
}
|
|
13
|
+
const SEAT_IGNORE_BYTES = ".gitignore\nSKILL.md\n";
|
|
14
|
+
const SEAT_SKILLS = [
|
|
15
|
+
["keiyaku-deliver", CONTRACT_DELIVERER_SKILL],
|
|
16
|
+
["keiyaku-review", CONTRACT_REVIEWER_SKILL],
|
|
17
|
+
];
|
|
94
18
|
async function isTracked(repository, relativePath) {
|
|
95
19
|
try {
|
|
96
20
|
await runGit(repository, ["ls-files", "--error-unmatch", "--", relativePath]);
|
|
@@ -145,7 +69,7 @@ export async function releaseContractWorktree(repository, contract) {
|
|
|
145
69
|
const appointment = await readContractAppointment(repository);
|
|
146
70
|
if (appointment.kind !== "appointed" || appointment.contract !== contract)
|
|
147
71
|
return;
|
|
148
|
-
if ((await readFile(appointment.path, "utf8")) !==
|
|
72
|
+
if ((await readFile(appointment.path, "utf8")) !== renderContractAppointment(contract))
|
|
149
73
|
return;
|
|
150
74
|
try {
|
|
151
75
|
await unlink(appointment.path);
|
|
@@ -169,6 +93,23 @@ async function repair(repository, worktree, relativePath, bytes) {
|
|
|
169
93
|
}
|
|
170
94
|
return { kind: "contract-file", path, action };
|
|
171
95
|
}
|
|
96
|
+
async function isKeiyakuSeatLeaf(worktree, seat) {
|
|
97
|
+
const sentinel = join(worktree, ".agents", "skills", seat, ".gitignore");
|
|
98
|
+
const stat = await lstat(sentinel).catch((error) => error.code === "ENOENT" ? undefined : Promise.reject(error));
|
|
99
|
+
return stat?.isFile() === true && !stat.isSymbolicLink() && (await readFile(sentinel, "utf8")) === SEAT_IGNORE_BYTES;
|
|
100
|
+
}
|
|
101
|
+
async function materializeSeatSkill(repository, worktree, seat, bytes) {
|
|
102
|
+
const leaf = `.agents/skills/${seat}`;
|
|
103
|
+
const skill = `${leaf}/SKILL.md`;
|
|
104
|
+
const skillPath = join(worktree, skill);
|
|
105
|
+
const skillExists = await lstat(skillPath).catch((error) => error.code === "ENOENT" ? false : Promise.reject(error));
|
|
106
|
+
if (!(await isKeiyakuSeatLeaf(worktree, seat)) && skillExists)
|
|
107
|
+
return [];
|
|
108
|
+
return [
|
|
109
|
+
await repair(repository, worktree, `${leaf}/.gitignore`, SEAT_IGNORE_BYTES),
|
|
110
|
+
await repair(repository, worktree, skill, bytes),
|
|
111
|
+
];
|
|
112
|
+
}
|
|
172
113
|
async function materialize(repository, worktree, guidance) {
|
|
173
114
|
const effects = [];
|
|
174
115
|
const failed = (target, path, error) => ({
|
|
@@ -218,6 +159,14 @@ async function materialize(repository, worktree, guidance) {
|
|
|
218
159
|
return failed(worktree, join(worktree, relativePath), error);
|
|
219
160
|
}
|
|
220
161
|
}
|
|
162
|
+
for (const [seat, bytes] of SEAT_SKILLS) {
|
|
163
|
+
try {
|
|
164
|
+
effects.push(...(await materializeSeatSkill(scoped, worktree, seat, bytes)));
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return failed(worktree, join(worktree, ".agents", "skills", seat), error);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
221
170
|
return { effects, lag: [] };
|
|
222
171
|
}
|
|
223
172
|
export async function projectContractWorktree(repository, state, register, _onConflict) {
|
|
@@ -11,6 +11,7 @@ export declare function acquireSqliteTransactionLock(input: {
|
|
|
11
11
|
mode: SqliteTransactionLockMode;
|
|
12
12
|
timeoutMs?: number;
|
|
13
13
|
signal?: AbortSignal;
|
|
14
|
+
onContended?: () => void;
|
|
14
15
|
}): Promise<HeldSqliteTransactionLock>;
|
|
15
16
|
export declare function tryAcquireSqliteTransactionLock(input: {
|
|
16
17
|
path: string;
|
|
@@ -119,6 +119,7 @@ export async function acquireSqliteTransactionLock(input) {
|
|
|
119
119
|
}
|
|
120
120
|
const started = performance.now();
|
|
121
121
|
let cap = INITIAL_RETRY_MS;
|
|
122
|
+
let contended = false;
|
|
122
123
|
for (;;) {
|
|
123
124
|
input.signal?.throwIfAborted();
|
|
124
125
|
try {
|
|
@@ -127,6 +128,10 @@ export async function acquireSqliteTransactionLock(input) {
|
|
|
127
128
|
catch (error) {
|
|
128
129
|
if (!isBusy(error))
|
|
129
130
|
throw error;
|
|
131
|
+
if (!contended) {
|
|
132
|
+
contended = true;
|
|
133
|
+
input.onContended?.();
|
|
134
|
+
}
|
|
130
135
|
const elapsed = performance.now() - started;
|
|
131
136
|
if (input.timeoutMs !== undefined && elapsed >= input.timeoutMs) {
|
|
132
137
|
throw new SqliteTransactionLockError(`SQLite lock timed out after ${input.timeoutMs}ms: ${input.path}`, "timeout", { cause: error });
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { JournalEntry } from "./types.js";
|
|
2
|
+
/** Validate one in-memory journal value with the persisted-fact authority. */
|
|
3
|
+
export declare function decodeJournalEntry(value: unknown): JournalEntry;
|
|
2
4
|
export declare function encodeEntry(entry: JournalEntry): string;
|
|
3
5
|
export declare function decodeJournal(journal: string): JournalEntry[];
|
|
@@ -235,6 +235,10 @@ function validateEntry(value) {
|
|
|
235
235
|
}
|
|
236
236
|
return entry;
|
|
237
237
|
}
|
|
238
|
+
/** Validate one in-memory journal value with the persisted-fact authority. */
|
|
239
|
+
export function decodeJournalEntry(value) {
|
|
240
|
+
return validateEntry(value);
|
|
241
|
+
}
|
|
238
242
|
function canonicalValue(value) {
|
|
239
243
|
if (value === null)
|
|
240
244
|
return "null";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type GateReport } from "../facts/gate.js";
|
|
1
2
|
import type { ActorId, ContractId } from "../facts/types.js";
|
|
2
3
|
import type { DecideInput, OfferDecision } from "../decide.js";
|
|
3
4
|
type PlacementInput = Readonly<{
|
|
@@ -10,8 +11,12 @@ export type UnmetPrerequisite = Readonly<{
|
|
|
10
11
|
state: "missing" | "active" | "abandoned";
|
|
11
12
|
}>;
|
|
12
13
|
export type PlacementRefusal = Readonly<{
|
|
13
|
-
kind: "contract-missing" | "delivery-missing" | "terminal"
|
|
14
|
+
kind: "contract-missing" | "delivery-missing" | "terminal";
|
|
14
15
|
contractId: ContractId;
|
|
16
|
+
}> | Readonly<{
|
|
17
|
+
kind: "gates-unsatisfied";
|
|
18
|
+
contractId: ContractId;
|
|
19
|
+
unmet: readonly GateReport[];
|
|
15
20
|
}> | Readonly<{
|
|
16
21
|
kind: "prerequisites-unsatisfied";
|
|
17
22
|
contractId: ContractId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { gateReports } from "../facts/gate.js";
|
|
2
2
|
import { activeContract, contractState } from "../facts/observation.js";
|
|
3
3
|
function unmetPrerequisites(prerequisites, observation) {
|
|
4
4
|
const unmet = [];
|
|
@@ -30,8 +30,10 @@ export function decidePlacement({ input, attempt, observation, }) {
|
|
|
30
30
|
if (unmet.length > 0) {
|
|
31
31
|
return { kind: "refused", refusal: { kind: "prerequisites-unsatisfied", contractId: id, unmet } };
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const gates = gateReports(current);
|
|
34
|
+
if (!gates.satisfied) {
|
|
35
|
+
const unmetGates = gates.reports.filter((report) => report.current.kind !== "attested" || report.current.verdict !== "satisfied");
|
|
36
|
+
return { kind: "refused", refusal: { kind: "gates-unsatisfied", contractId: id, unmet: unmetGates } };
|
|
35
37
|
}
|
|
36
38
|
const claimed = {
|
|
37
39
|
v: 1,
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { join } from "node:path";
|
|
3
2
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
4
3
|
import { contractId } from "../core/facts/types.js";
|
|
5
4
|
import { parseAkuId } from "../akuma/identity.js";
|
|
6
|
-
import {
|
|
7
|
-
import { GIT_FORMAT_BYTES, GIT_FORMAT_PATH, GIT_REF, readBlob, readGitPaths, updateGitTree, updateRefsAtomically, writeBlob,
|
|
5
|
+
import { confirmPrivateStatePublication, withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
|
|
6
|
+
import { GIT_FORMAT_BYTES, GIT_FORMAT_PATH, GIT_REF, readBlob, readGitPaths, updateGitTree, updateRefsAtomically, writeBlob, writeStateCommit, } from "../git/repository.js";
|
|
8
7
|
import { withGitDecodeChannel, withGitReadObservation } from "../git/read-observation.js";
|
|
9
8
|
const DISPATCH_ROOT = "dispatch";
|
|
10
9
|
const DISPATCH_PREFIX = `${DISPATCH_ROOT}/`;
|
|
11
10
|
const DISPATCH_SUFFIX = ".json";
|
|
12
|
-
const MAX_ATTEMPTS = 3;
|
|
13
11
|
function pathFor(akuId) {
|
|
14
12
|
return `${DISPATCH_PREFIX}${createHash("sha256").update(akuId).digest("hex")}${DISPATCH_SUFFIX}`;
|
|
15
13
|
}
|
|
@@ -125,57 +123,58 @@ export async function publishDispatch(input) {
|
|
|
125
123
|
const owner = contractId(input.contractId);
|
|
126
124
|
const intended = { akuId, contractId: owner, dispatchedAt: new Date().toISOString() };
|
|
127
125
|
const path = pathFor(akuId);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (observed
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
126
|
+
return await withPrivateStatePublicationSeat(input.repository, async (seat) => {
|
|
127
|
+
const snapshot = await readGitPaths(input.repository, [path]);
|
|
128
|
+
const current = await dispatchFromSnapshot(input.repository, snapshot, akuId);
|
|
129
|
+
if (current !== null) {
|
|
130
|
+
if (current.contractId === owner)
|
|
131
|
+
confirmPrivateStatePublication(seat);
|
|
132
|
+
return current.contractId === owner
|
|
133
|
+
? { kind: "dispatched", dispatch: current }
|
|
134
|
+
: { kind: "failed", failure: { kind: "conflict", current } };
|
|
135
|
+
}
|
|
136
|
+
const changes = new Map();
|
|
137
|
+
if (snapshot.commit === null) {
|
|
138
|
+
changes.set(GIT_FORMAT_PATH, { oid: await writeBlob(input.repository, GIT_FORMAT_BYTES) });
|
|
139
|
+
}
|
|
140
|
+
changes.set(path, { oid: await writeBlob(input.repository, bytesFor(intended)) });
|
|
141
|
+
const tree = await updateGitTree(input.repository, snapshot.tree, changes);
|
|
142
|
+
const commit = await writeStateCommit({
|
|
143
|
+
repository: input.repository,
|
|
144
|
+
tree,
|
|
145
|
+
parent: snapshot.commit,
|
|
146
|
+
message: `dispatch ${akuId}`,
|
|
147
|
+
at: intended.dispatchedAt,
|
|
148
|
+
});
|
|
149
|
+
const publication = await updateRefsAtomically(input.repository, [
|
|
150
|
+
{
|
|
151
|
+
ref: GIT_REF,
|
|
152
|
+
newOid: commit,
|
|
153
|
+
expectedOid: snapshot.commit,
|
|
154
|
+
},
|
|
155
|
+
]);
|
|
156
|
+
if (publication.kind === "published") {
|
|
157
|
+
confirmPrivateStatePublication(seat);
|
|
158
|
+
return { kind: "dispatched", dispatch: intended };
|
|
159
|
+
}
|
|
160
|
+
const observed = await observedPublication(input.repository, akuId, owner);
|
|
161
|
+
if (observed !== null) {
|
|
162
|
+
if (observed.kind === "dispatched")
|
|
163
|
+
confirmPrivateStatePublication(seat);
|
|
164
|
+
return observed;
|
|
165
|
+
}
|
|
166
|
+
if (publication.kind === "non-published") {
|
|
167
|
+
const fresh = await readGitPaths(input.repository, [path]);
|
|
168
|
+
if (fresh.commit === snapshot.commit) {
|
|
169
|
+
return {
|
|
170
|
+
kind: "failed",
|
|
171
|
+
failure: { kind: "publication-failed", diagnostic: diagnostic(publication.error) },
|
|
172
|
+
};
|
|
174
173
|
}
|
|
175
174
|
}
|
|
176
|
-
return {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
175
|
+
return {
|
|
176
|
+
kind: "failed",
|
|
177
|
+
failure: { kind: "publication-failed", diagnostic: "Dispatch publication outcome is unknown" },
|
|
178
|
+
};
|
|
179
|
+
});
|
|
181
180
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { decodeJournal, encodeEntry } from "../core/facts/codec.js";
|
|
2
|
-
import { GIT_FORMAT_BYTES, GIT_FORMAT_PATH, GIT_REF, updateGitTreeFromFrozenDirectories, updateRefsAtomically, writeBlob,
|
|
2
|
+
import { GIT_FORMAT_BYTES, GIT_FORMAT_PATH, GIT_REF, updateGitTreeFromFrozenDirectories, updateRefsAtomically, writeBlob, writeStateCommit, } from "./repository.js";
|
|
3
3
|
import { contractJournalPath, contractJournalPaths, gitObjectIdForSnapshot, mintContractHead, mintSnapshotId, } from "./identity.js";
|
|
4
4
|
import { validPath } from "./tree.js";
|
|
5
5
|
const CONTRACT_JOURNAL_PATH = /^contracts\/(?:active|terminal)\/[0-9a-f]{2}\/[0-9a-f]{2}\/[0-9a-f]{60}\.jsonl$/u;
|
|
@@ -86,7 +86,7 @@ async function buildOffer(repository, admission, appends, companions) {
|
|
|
86
86
|
async function publishOffer(repository, admission, target, changes, assertions) {
|
|
87
87
|
const { snapshot } = admission;
|
|
88
88
|
const gitTree = await updateGitTreeFromFrozenDirectories(repository, snapshot.tree, admission.treeDirectories, changes);
|
|
89
|
-
const gitCommit = mintSnapshotId(await
|
|
89
|
+
const gitCommit = mintSnapshotId(await writeStateCommit({
|
|
90
90
|
repository,
|
|
91
91
|
tree: gitTree,
|
|
92
92
|
parent: snapshot.commit,
|
package/build/src/git/hooks.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type HookCommand = Readonly<{
|
|
2
|
+
name: string;
|
|
2
3
|
argv: readonly string[];
|
|
3
4
|
timeoutMs: number;
|
|
4
5
|
}>;
|
|
@@ -25,18 +26,10 @@ export type WorktreeHookLag = Readonly<{
|
|
|
25
26
|
phase: HookPhase;
|
|
26
27
|
path: string;
|
|
27
28
|
command: number;
|
|
29
|
+
name: string;
|
|
28
30
|
failure: HookFailure;
|
|
29
31
|
}>;
|
|
30
|
-
type HookPhase = "create" | "destroy";
|
|
31
|
-
export declare function hookMarkerPath(administrationDirectory: string): string;
|
|
32
|
-
export type WorktreeHookMarkerObservation = Readonly<{
|
|
33
|
-
kind: "absent" | "pending" | "ok";
|
|
34
|
-
}> | Readonly<{
|
|
35
|
-
kind: "failed";
|
|
36
|
-
diagnostic: string;
|
|
37
|
-
}>;
|
|
38
|
-
/** Read the durable hook marker without executing commands or taking locks. */
|
|
39
|
-
export declare function observeWorktreeHookMarker(administrationDirectory: string): Promise<WorktreeHookMarkerObservation>;
|
|
32
|
+
export type HookPhase = "create" | "destroy";
|
|
40
33
|
export type HookCommandRun = Readonly<{
|
|
41
34
|
kind: "ok";
|
|
42
35
|
}> | Readonly<{
|
|
@@ -48,8 +41,9 @@ export type HookCommandRun = Readonly<{
|
|
|
48
41
|
}>;
|
|
49
42
|
/** Execute an ordered command list without lifecycle state. Scratch owns this policy. */
|
|
50
43
|
export declare function runHookCommands(worktree: string, commands: readonly HookCommand[], signal?: AbortSignal): Promise<HookCommandRun>;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
export
|
|
44
|
+
export type HookPhaseRun = Readonly<{
|
|
45
|
+
lag: WorktreeHookLag | null;
|
|
46
|
+
runs: readonly string[];
|
|
47
|
+
}>;
|
|
48
|
+
export declare function runCreateHooks(worktree: string, hooks: WorktreeHooks): Promise<HookPhaseRun>;
|
|
49
|
+
export declare function runDestroyHooks(worktree: string, hooks: WorktreeHooks): Promise<HookPhaseRun>;
|