@astrosheep/keiyaku 2.9.12 → 2.9.13
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 +22 -18
- package/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +1 -0
- package/build/agents/providers/claude-agent-sdk/adapter.js +2 -2
- package/build/cli/commands/akuma/akuma/handler.js +2 -1
- package/build/cli/commands/akuma/akuma/meta.js +4 -3
- package/build/cli/commands/akuma/catalog.js +2 -0
- package/build/cli/commands/akuma/list/handler.js +1 -1
- package/build/cli/commands/akuma/list/meta-list.js +12 -0
- package/build/cli/commands/akuma/list/meta-ls.js +2 -2
- package/build/cli/commands/akuma.js +5 -0
- package/build/cli/commands/contract/amend/meta.js +4 -3
- package/build/cli/commands/contract/arc/meta.js +2 -0
- package/build/cli/commands/contract/audit/handler.js +28 -2
- package/build/cli/commands/contract/audit/meta.js +4 -3
- package/build/cli/commands/contract/petition/handler.js +2 -1
- package/build/cli/commands/contract/petition/meta.js +2 -2
- package/build/cli/commands/contract/renew/handler.js +44 -3
- package/build/cli/commands/contract/renew/meta.js +5 -4
- package/build/cli/commands/metadata.js +12 -9
- package/build/cli/commands/projection/call/handler.js +1 -1
- package/build/cli/commands/projection/call/meta.js +1 -1
- package/build/cli/commands/projection/catalog.js +2 -2
- package/build/cli/commands/projection/{revive → fork}/handler.js +10 -5
- package/build/cli/commands/projection/fork/meta.js +12 -0
- package/build/cli/commands/projection/history/handler.js +46 -2
- package/build/cli/commands/projection/history/meta.js +3 -3
- package/build/cli/commands/projection/kill/meta.js +2 -2
- package/build/cli/commands/projection/status/handler.js +29 -13
- package/build/cli/commands/projection/status/meta.js +14 -3
- package/build/cli/commands/projection/tell/handler.js +8 -4
- package/build/cli/commands/projection/tell/meta.js +1 -1
- package/build/cli/commands/projection/wait/handler.js +45 -20
- package/build/cli/commands/projection/wait/meta.js +1 -1
- package/build/cli/commands/shared.js +1 -1
- package/build/cli/commands/system/catalog.js +2 -0
- package/build/cli/commands/task/add/handler.js +28 -12
- package/build/cli/commands/task/add/meta.js +18 -6
- package/build/cli/commands/task/catalog.js +2 -0
- package/build/cli/commands/task/compose/handler.js +2 -2
- package/build/cli/commands/task/compose/meta.js +2 -2
- package/build/cli/commands/task/doctor/handler.js +2 -3
- package/build/cli/commands/task/doctor/meta.js +2 -2
- package/build/cli/commands/task/done/meta.js +2 -2
- package/build/cli/commands/task/drop/handler.js +7 -2
- package/build/cli/commands/task/drop/meta.js +6 -3
- package/build/cli/commands/task/hold/meta.js +2 -2
- package/build/cli/commands/task/log/meta.js +2 -2
- package/build/cli/commands/task/ls/meta.js +2 -2
- package/build/cli/commands/task/note/handler.js +6 -0
- package/build/cli/commands/task/note/meta.js +11 -0
- package/build/cli/commands/task/resume/meta.js +2 -2
- package/build/cli/commands/task/shared.js +29 -15
- package/build/cli/commands/task/show/meta.js +2 -2
- package/build/cli/commands/task/start/meta.js +2 -2
- package/build/cli/commands/task/stop/meta.js +2 -2
- package/build/cli/commands/task/update/meta.js +3 -2
- package/build/cli/commands/verification/handler.js +43 -0
- package/build/cli/commands/verification/meta.js +13 -0
- package/build/cli/completion.js +16 -13
- package/build/cli/flags.js +43 -11
- package/build/cli/help.js +29 -30
- package/build/cli/index.js +6 -5
- package/build/cli/parse-flags.js +39 -0
- package/build/cli/parse-metadata.js +5 -2
- package/build/cli/parse-selectors.js +18 -0
- package/build/cli/parse.js +21 -8
- package/build/cli/render/arc.js +12 -3
- package/build/cli/render/audit.js +2 -2
- package/build/cli/render/call.js +4 -4
- package/build/cli/render/kanshi.js +122 -85
- package/build/cli/render/misc.js +2 -2
- package/build/cli/render/petition.js +16 -1
- package/build/cli/render/projection-history.js +17 -4
- package/build/cli/render/shared.js +5 -5
- package/build/cli/render/status-indicator.js +47 -0
- package/build/cli/render/status.js +106 -76
- package/build/cli/render/success-response.js +20 -5
- package/build/cli/render/task.js +6 -5
- package/build/cli/render/tell.js +10 -4
- package/build/cli/render/tool-command-normalization.js +137 -0
- package/build/cli/render/tool-presentation.js +2 -1
- package/build/cli/render/verification.js +23 -0
- package/build/cli/render/wait.js +101 -33
- package/build/cli/types.js +2 -1
- package/build/config/akuma-loader.js +21 -1
- package/build/config/settings/knobs.js +7 -1
- package/build/config/settings/schema.js +10 -5
- package/build/core/amend.js +102 -17
- package/build/core/arc.js +4 -4
- package/build/core/audit/candidate.js +10 -18
- package/build/core/audit/coordinates.js +12 -17
- package/build/core/audit/evidence.js +6 -4
- package/build/core/audit/facade.js +3 -3
- package/build/core/audit/report.js +1 -1
- package/build/core/bind-reconciliation.js +42 -23
- package/build/core/bind.js +182 -81
- package/build/core/call/call.js +6 -7
- package/build/core/call/context.js +43 -30
- package/build/core/call/execution.js +21 -6
- package/build/core/call/prompt.js +11 -42
- package/build/core/contract-carrier-runtime.js +209 -105
- package/build/core/contract-carrier.js +156 -73
- package/build/core/contract-view.js +42 -5
- package/build/core/contract.js +2 -1
- package/build/core/derived-replay.js +168 -35
- package/build/core/draft.js +9 -5
- package/build/core/forfeit.js +1 -1
- package/build/core/lifecycle-history.js +13 -0
- package/build/core/lifecycle-recovery.js +32 -27
- package/build/core/lifecycle-runner.js +14 -14
- package/build/core/log.js +1 -1
- package/build/core/outcome-base.js +2 -2
- package/build/core/projection/akuma-name.js +43 -0
- package/build/core/projection/generation/database.js +141 -79
- package/build/core/projection/generation/ledger.js +91 -0
- package/build/core/projection/generation/model.js +18 -13
- package/build/core/projection/generation/projection-generation-continuation.js +1 -1
- package/build/core/projection/generation/projection-generation-doorbell.js +88 -0
- package/build/core/projection/generation/projection-generation-execution.js +24 -0
- package/build/core/projection/generation/projection-generation-identity.js +4 -0
- package/build/core/projection/generation/projection-generation-launcher.js +72 -138
- package/build/core/projection/generation/projection-generation-process.js +16 -15
- package/build/core/projection/generation/projection-generation-runner.js +125 -79
- package/build/core/projection/generation/projection-generation-runtime.js +10 -61
- package/build/core/projection/generation/protocol.js +68 -0
- package/build/core/projection/generation/store.js +17 -7
- package/build/core/projection/generation/transitions.js +14 -14
- package/build/core/projection/index.js +5 -5
- package/build/core/projection/projection-core.js +6 -2
- package/build/core/projection/projection-execution-observer.js +1 -1
- package/build/core/projection/projection-history.js +7 -7
- package/build/core/projection/projection-kill.js +15 -6
- package/build/core/projection/projection-life-observer.js +8 -8
- package/build/core/projection/projection-mint.js +6 -8
- package/build/core/projection/projection-status-observation.js +77 -8
- package/build/core/projection/projection-status.js +151 -4
- package/build/core/projection/projection-wait.js +46 -27
- package/build/core/projection/projection-wake.js +27 -89
- package/build/core/projection/tell/launch-store.js +1 -1
- package/build/core/projection/tell/store.js +1 -1
- package/build/core/renew-build.js +204 -74
- package/build/core/renew-plan.js +34 -9
- package/build/core/renew-rewrite.js +56 -15
- package/build/core/renew.js +39 -35
- package/build/core/repository-ledger/accepted-fold-read.js +6 -3
- package/build/core/repository-ledger/codec.js +11 -5
- package/build/core/repository-ledger/current-state-store.js +13 -16
- package/build/core/repository-ledger/fold-repository.js +5 -6
- package/build/core/repository-ledger/identity.js +60 -0
- package/build/core/repository-ledger/inventory.js +3 -3
- package/build/core/repository-ledger/read-model.js +54 -6
- package/build/core/repository-ledger/write-transaction.js +9 -4
- package/build/core/run-control/connection-bound-close.js +41 -0
- package/build/core/run-control/detached-lease-bootstrap.js +208 -0
- package/build/core/run-control/detached-process.js +14 -0
- package/build/core/run-control/index.js +6 -0
- package/build/core/{process-group.js → run-control/process-tree.js} +1 -1
- package/build/core/run-control/runner-lease.js +172 -0
- package/build/core/{sqlite-process-lifetime-lock.js → run-control/sqlite-process-lifetime-lock.js} +4 -24
- package/build/core/seal.js +44 -32
- package/build/core/settlement/claim-delivery.js +22 -9
- package/build/core/settlement/claim.js +8 -6
- package/build/core/settlement/petition-claim-gates.js +9 -8
- package/build/core/settlement/petition-head-guard.js +5 -6
- package/build/core/settlement/petition-preview.js +21 -5
- package/build/core/settlement/petition.js +51 -17
- package/build/core/settlement/settlement.js +20 -15
- package/build/core/settlement/verdict.js +2 -2
- package/build/core/settlement/verification.js +492 -364
- package/build/core/status/board.js +184 -75
- package/build/core/status/drift.js +8 -10
- package/build/core/task/board.js +1 -0
- package/build/core/task/commands.js +25 -0
- package/build/core/task/compose.js +3 -2
- package/build/core/task/document.js +102 -39
- package/build/core/task/index.js +3 -3
- package/build/core/task/settlement-git.js +1 -4
- package/build/core/task/settlement-policy.js +27 -14
- package/build/core/task/source-board.js +1 -0
- package/build/core/task/task-bind-preparation.js +59 -9
- package/build/core/task/task-contract.js +2 -2
- package/build/core/task/task-store-repository.js +1 -0
- package/build/core/task/task.js +2 -2
- package/build/core/transcripts.js +4 -4
- package/build/core/verification-declaration.js +95 -0
- package/build/core/worktree-bootstrap.js +1 -1
- package/build/core/worktree-path.js +7 -11
- package/build/flow-error.js +9 -1
- package/build/generated/version.js +2 -2
- package/build/git/branches.js +41 -70
- package/build/git/commits.js +92 -21
- package/build/git/core.js +9 -161
- package/build/git/diff/preview.js +4 -4
- package/build/git/diff/read.js +4 -4
- package/build/git/diff/structured.js +5 -5
- package/build/git/process.js +229 -0
- package/build/git/refs.js +30 -5
- package/build/git/staging.js +39 -115
- package/build/git/streaming-batch.js +9 -16
- package/build/git/worktree.js +104 -91
- package/build/index.js +7 -0
- package/package.json +1 -1
- package/skills/keiyaku-akuma/SKILL.md +21 -20
- package/skills/keiyaku-task/SKILL.md +38 -4
- package/skills/keiyaku-workflow/SKILL.md +51 -11
- package/build/cli/commands/projection/revive/meta.js +0 -12
- package/build/core/projection/projection-life-protocol.js +0 -115
- package/build/core/projection/projection-runner-lock.js +0 -211
- package/build/core/projection/tell/database.js +0 -127
- package/build/core/settlement/verification-coordination.js +0 -305
- package/build/core/settlement/verification-supervisor.js +0 -275
package/build/core/bind.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
|
+
import { readdir } from "node:fs/promises";
|
|
3
|
+
import * as path from "node:path";
|
|
2
4
|
import { assertSettingsKnobUsable } from "../config/settings/disease.js";
|
|
3
5
|
import { loadKeiyakuSettings } from "../config/settings/loader.js";
|
|
4
6
|
import { FlowError } from "../flow-error.js";
|
|
5
|
-
import { lookupCurrentContract, readRepositoryLifecycle, } from "./repository-ledger/read-model.js";
|
|
6
|
-
import { repositoryDeliveryRef, } from "./repository-ledger/codec.js";
|
|
7
|
+
import { advanceRepositorySnapshotWithBind, lookupCurrentContract, readRepositoryLifecycle, } from "./repository-ledger/read-model.js";
|
|
8
|
+
import { REPOSITORY_LEDGER_REF, repositoryDeliveryRef, } from "./repository-ledger/codec.js";
|
|
7
9
|
import { publishBindTransaction, } from "./repository-ledger/write-transaction.js";
|
|
8
10
|
import { bindEffectiveScope } from "./repository-ledger/fold.js";
|
|
9
11
|
import { activeWorkspaceHereContracts } from "./repository-ledger/inventory.js";
|
|
12
|
+
import { repositoryLedgerHead } from "./repository-ledger/identity.js";
|
|
10
13
|
import { describeMissingBindSections, materializeBindDraft, mergeBindDraft, missingBindDraftSections, parseBindDraft, parsePartialBindDraft, renderBindDraft, renderMissingBindSectionsTemplate, } from "./draft.js";
|
|
11
|
-
import {
|
|
14
|
+
import { buildContractId, isCommissionId } from "./ids.js";
|
|
12
15
|
import { admitScopeRegistration, } from "./registry.js";
|
|
13
|
-
import { resolveDefaultBranch } from "./status/drift.js";
|
|
14
16
|
import { normalizeTargetRef } from "./target-ref.js";
|
|
15
|
-
import { previewTaskBoardForBind,
|
|
17
|
+
import { previewTaskBoardForBind, withPreparedTaskBindSnapshot, } from "./task/index.js";
|
|
16
18
|
import { stableRepoRoot } from "./worktree-path.js";
|
|
17
19
|
import { allocateWorktreePlaceFromRead, } from "./bind-workspace.js";
|
|
18
|
-
import { committedOrThrow,
|
|
20
|
+
import { committedOrThrow, reconcileBindContract, reconcileCommittedBindFromSnapshot, requiresBindRecovery } from "./bind-reconciliation.js";
|
|
19
21
|
import { allocateTaskNamespace, taskNamespaceFromScope, taskNamespaceScope } from "./task/coordinate.js";
|
|
22
|
+
import { resolveExactRefHeads } from "../git/refs.js";
|
|
23
|
+
import { runGitProcess } from "../git/core.js";
|
|
20
24
|
export { reconcileBindContract } from "./bind-reconciliation.js";
|
|
21
25
|
function randomBytesDefault() {
|
|
22
26
|
return [...crypto.randomBytes(10)];
|
|
@@ -29,6 +33,27 @@ function resolvedBootstrapPlan(settings) {
|
|
|
29
33
|
timeoutMs: settings.timeoutMs,
|
|
30
34
|
};
|
|
31
35
|
}
|
|
36
|
+
async function readPersistedTaskNamespaces(stableRoot) {
|
|
37
|
+
try {
|
|
38
|
+
const entries = await readdir(path.join(stableRoot, ".keiyaku", "tasks"), { withFileTypes: true });
|
|
39
|
+
return new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
43
|
+
return new Set();
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function observeBindRefs(stableRoot, defaultBranchOverride) {
|
|
48
|
+
const branches = defaultBranchOverride ? [defaultBranchOverride] : ["main", "master"];
|
|
49
|
+
const refs = [REPOSITORY_LEDGER_REF, ...branches.map((branch) => normalizeTargetRef(branch))];
|
|
50
|
+
const heads = await resolveExactRefHeads(stableRoot, refs);
|
|
51
|
+
const selected = branches.find((branch) => heads.get(normalizeTargetRef(branch)) !== null);
|
|
52
|
+
return {
|
|
53
|
+
ledgerHead: heads.get(REPOSITORY_LEDGER_REF) ?? null,
|
|
54
|
+
branch: selected ? { branch: selected, head: heads.get(normalizeTargetRef(selected)) } : null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
32
57
|
function bindDraftWithTaskNamespace(draft, read, persistedNamespaces) {
|
|
33
58
|
const declared = draft.scope.flatMap((term) => {
|
|
34
59
|
const namespace = taskNamespaceFromScope(term);
|
|
@@ -66,7 +91,7 @@ function makeBindEntry(input) {
|
|
|
66
91
|
...(input.taskIds ? { taskIds: [...input.taskIds] } : {}),
|
|
67
92
|
};
|
|
68
93
|
return {
|
|
69
|
-
v:
|
|
94
|
+
v: 3,
|
|
70
95
|
kind: "bind",
|
|
71
96
|
contract: input.id,
|
|
72
97
|
at: input.at,
|
|
@@ -108,24 +133,22 @@ export function composeTaskBindDraft(input) {
|
|
|
108
133
|
return materializeBindDraft(merged);
|
|
109
134
|
}
|
|
110
135
|
function validateBindAfter(read, after) {
|
|
111
|
-
const unique = new Set();
|
|
112
136
|
for (const contractId of after) {
|
|
113
|
-
if (unique.has(contractId)) {
|
|
114
|
-
throw new FlowError("INVALID_TARGET", `contract ${contractId} selected more than once by --after`);
|
|
115
|
-
}
|
|
116
|
-
unique.add(contractId);
|
|
117
137
|
if (!isCommissionId(contractId)) {
|
|
118
138
|
throw new FlowError("INVALID_TARGET", `after contract ${contractId} is not a valid contract id`);
|
|
119
139
|
}
|
|
120
140
|
const outcome = lookupCurrentContract(read, contractId);
|
|
121
141
|
if (outcome.status !== "healthy") {
|
|
122
|
-
throw new FlowError("INVALID_TARGET", `after contract ${contractId} is not a healthy
|
|
123
|
-
}
|
|
124
|
-
if (!["claimed", "forfeited"].includes(outcome.model.phase)) {
|
|
125
|
-
throw new FlowError("INVALID_TARGET", `after contract ${contractId} is not terminal`);
|
|
142
|
+
throw new FlowError("INVALID_TARGET", `after contract ${contractId} is not a healthy existing contract`);
|
|
126
143
|
}
|
|
127
144
|
}
|
|
128
145
|
}
|
|
146
|
+
function canonicalBindAfter(explicit, selected = []) {
|
|
147
|
+
return [...new Set([
|
|
148
|
+
...explicit,
|
|
149
|
+
...selected.flatMap((task) => task.needs.flatMap((need) => need.contractId === undefined ? [] : [need.contractId])),
|
|
150
|
+
])];
|
|
151
|
+
}
|
|
129
152
|
function assertContractAbsent(read, contractId) {
|
|
130
153
|
const outcome = lookupCurrentContract(read, contractId);
|
|
131
154
|
if (outcome.status === "absent")
|
|
@@ -149,10 +172,9 @@ function admitWorkspaceOccupancy(read, workspace) {
|
|
|
149
172
|
* facts and rendered the canonical draft.
|
|
150
173
|
*/
|
|
151
174
|
async function admitBindCandidate(input, draft, read) {
|
|
152
|
-
draft = bindDraftWithTaskNamespace(draft, read, await
|
|
175
|
+
draft = bindDraftWithTaskNamespace(draft, read, await readPersistedTaskNamespaces(input.cwd));
|
|
153
176
|
admitWorkspaceOccupancy(read, input.workspace);
|
|
154
177
|
const id = buildContractId({ title: draft.title, nowMs: input.nowMs, randomBytes: input.randomBytes });
|
|
155
|
-
await assertValidContractId(input.cwd, id);
|
|
156
178
|
assertContractAbsent(read, id);
|
|
157
179
|
validateBindAfter(read, input.after);
|
|
158
180
|
const provisionalEntry = makeBindEntry({
|
|
@@ -191,18 +213,20 @@ export async function previewBindContract(input) {
|
|
|
191
213
|
const isTaskBound = input.taskIds !== undefined && input.taskIds.length > 0;
|
|
192
214
|
const ordinaryDraft = !isTaskBound ? parseBindDraft(input.draft) : undefined;
|
|
193
215
|
const workspace = input.workspace ?? "here";
|
|
194
|
-
const
|
|
216
|
+
const loadedSettings = await loadKeiyakuSettings(input.cwd);
|
|
217
|
+
assertSettingsKnobUsable(loadedSettings, "defaultBranch");
|
|
218
|
+
const observed = await observeBindRefs(input.cwd, loadedSettings.knobs?.defaultBranch);
|
|
219
|
+
const defaultBranch = observed.branch;
|
|
195
220
|
if (!defaultBranch) {
|
|
196
221
|
throw new FlowError("INTERNAL_STATE", "cannot bind: no default branch");
|
|
197
222
|
}
|
|
198
223
|
const target = normalizeTargetRef(defaultBranch.branch);
|
|
199
|
-
const loadedSettings = await loadKeiyakuSettings(input.cwd);
|
|
200
224
|
let bootstrapPlan;
|
|
201
225
|
if (workspace === "worktree") {
|
|
202
226
|
assertSettingsKnobUsable(loadedSettings, "worktreeBootstrap");
|
|
203
227
|
bootstrapPlan = resolvedBootstrapPlan(loadedSettings.knobs?.worktreeBootstrap);
|
|
204
228
|
}
|
|
205
|
-
const read = await readRepositoryLifecycle(input.cwd);
|
|
229
|
+
const read = await readRepositoryLifecycle(input.cwd, { observedHead: observed.ledgerHead, signal: input.signal });
|
|
206
230
|
const randomBytes = input.randomBytes?.(0) ?? randomBytesDefault();
|
|
207
231
|
const place = workspace === "worktree" ? allocateWorktreePlaceFromRead(read, randomBytes) : undefined;
|
|
208
232
|
const taskAdmission = isTaskBound
|
|
@@ -233,18 +257,57 @@ export async function bindContract(input) {
|
|
|
233
257
|
const workspace = input.workspace ?? "here";
|
|
234
258
|
const at = new Date(input.nowMs).toISOString();
|
|
235
259
|
const after = input.after ?? [];
|
|
236
|
-
const defaultBranch = await resolveDefaultBranch(stableRoot);
|
|
237
|
-
if (!defaultBranch)
|
|
238
|
-
throw new FlowError("INTERNAL_STATE", "cannot bind: no default branch");
|
|
239
|
-
const target = normalizeTargetRef(defaultBranch.branch);
|
|
240
260
|
const publishBind = input.dependencies?.publishBind ?? publishBindTransaction;
|
|
241
|
-
const persistedTaskNamespaces = await
|
|
261
|
+
const persistedTaskNamespaces = await readPersistedTaskNamespaces(stableRoot);
|
|
242
262
|
const loadedSettings = await loadKeiyakuSettings(stableRoot);
|
|
263
|
+
assertSettingsKnobUsable(loadedSettings, "defaultBranch");
|
|
243
264
|
let bootstrapPlan;
|
|
244
265
|
if (workspace === "worktree") {
|
|
245
266
|
assertSettingsKnobUsable(loadedSettings, "worktreeBootstrap");
|
|
246
267
|
bootstrapPlan = resolvedBootstrapPlan(loadedSettings.knobs?.worktreeBootstrap);
|
|
247
268
|
}
|
|
269
|
+
const observeEntry = async () => {
|
|
270
|
+
const attemptedReplay = new Map();
|
|
271
|
+
for (;;) {
|
|
272
|
+
const observed = await observeBindRefs(stableRoot, loadedSettings.knobs?.defaultBranch);
|
|
273
|
+
if (!observed.branch) {
|
|
274
|
+
if (loadedSettings.knobs?.defaultBranch)
|
|
275
|
+
throw new FlowError("INVALID_SETTINGS", `configured defaultBranch '${loadedSettings.knobs.defaultBranch}' does not resolve`);
|
|
276
|
+
throw new FlowError("INTERNAL_STATE", "cannot bind: no default branch");
|
|
277
|
+
}
|
|
278
|
+
const read = await readRepositoryLifecycle(stableRoot, { observedHead: observed.ledgerHead, signal: input.signal });
|
|
279
|
+
const outstanding = read.contracts.filter(requiresBindRecovery);
|
|
280
|
+
if (outstanding.length === 0)
|
|
281
|
+
return { branch: observed.branch, read };
|
|
282
|
+
for (const lifecycle of outstanding) {
|
|
283
|
+
const priorAttempt = attemptedReplay.get(lifecycle.contract);
|
|
284
|
+
if (priorAttempt) {
|
|
285
|
+
if (priorAttempt.completion.status === "contained") {
|
|
286
|
+
const cause = priorAttempt.completion.cause;
|
|
287
|
+
const code = cause.code === "BIND_WORKTREE_PATH_OCCUPIED"
|
|
288
|
+
|| cause.code === "CARRIER_MATERIALIZATION_FAILED"
|
|
289
|
+
|| cause.code === "CARRIER_TARGET_UNAVAILABLE"
|
|
290
|
+
? cause.code
|
|
291
|
+
: "INTERNAL_STATE";
|
|
292
|
+
throw new FlowError(code, cause.message);
|
|
293
|
+
}
|
|
294
|
+
throw new FlowError("INTERNAL_STATE", `bind entry replay for ${lifecycle.contract} completed without advancing its pending lifecycle state`);
|
|
295
|
+
}
|
|
296
|
+
attemptedReplay.set(lifecycle.contract, await reconcileBindContract({
|
|
297
|
+
cwd: stableRoot,
|
|
298
|
+
contractId: lifecycle.contract,
|
|
299
|
+
actor: input.actor,
|
|
300
|
+
nowMs: input.nowMs,
|
|
301
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
302
|
+
...(input.createWorktree ? { createWorktree: input.createWorktree } : {}),
|
|
303
|
+
...(input.onProgress ? { onProgress: input.onProgress } : {}),
|
|
304
|
+
...(input.bootstrapRunner ? { bootstrapRunner: input.bootstrapRunner } : {}),
|
|
305
|
+
...(input.bootstrapDependencies ? { bootstrapDependencies: input.bootstrapDependencies } : {}),
|
|
306
|
+
dependencies: input.dependencies,
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
};
|
|
248
311
|
let selectedDraft;
|
|
249
312
|
let selectedPlace;
|
|
250
313
|
let selectedId;
|
|
@@ -262,7 +325,6 @@ export async function bindContract(input) {
|
|
|
262
325
|
collided.push(id);
|
|
263
326
|
continue;
|
|
264
327
|
}
|
|
265
|
-
await assertValidContractId(stableRoot, id);
|
|
266
328
|
selectedDraft = bindDraftWithTaskNamespace(draft, read, persistedTaskNamespaces);
|
|
267
329
|
selectedPlace = place;
|
|
268
330
|
selectedId = id;
|
|
@@ -273,84 +335,100 @@ export async function bindContract(input) {
|
|
|
273
335
|
let entry;
|
|
274
336
|
let admittedScopeOverlaps = [];
|
|
275
337
|
let preparedTask;
|
|
338
|
+
let preparedTaskProjectionSucceeded = false;
|
|
339
|
+
let committedHead;
|
|
340
|
+
let committedEntryObjectId;
|
|
341
|
+
let admittedRead;
|
|
276
342
|
if (isTaskBound) {
|
|
277
|
-
let
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
343
|
+
let settled;
|
|
344
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
345
|
+
let lockedRead;
|
|
346
|
+
let target;
|
|
347
|
+
const attempted = await withPreparedTaskBindSnapshot({
|
|
348
|
+
location: { mode: "git", root: stableRoot, surfaceRoot: stableRoot, gitDir: path.join(stableRoot, ".git") },
|
|
349
|
+
observeBoard: async () => {
|
|
350
|
+
const observed = await observeEntry();
|
|
351
|
+
target = normalizeTargetRef(observed.branch.branch);
|
|
352
|
+
lockedRead = observed.read;
|
|
353
|
+
admittedRead = lockedRead;
|
|
354
|
+
return { ref: target, head: observed.branch.head };
|
|
355
|
+
},
|
|
356
|
+
taskIds: input.taskIds,
|
|
357
|
+
signal: input.signal,
|
|
358
|
+
prepare: async (tasks) => {
|
|
359
|
+
return await selectCandidate(composeTaskBindDraft({ task: tasks[0], draft: input.draft }), lockedRead);
|
|
360
|
+
},
|
|
361
|
+
transact: async (prepared, taskTransaction) => {
|
|
362
|
+
if (prepared.boardRef !== target) {
|
|
363
|
+
throw new FlowError("CONCURRENT_MODIFICATION", "locked task-board ref does not match the selected bind target");
|
|
364
|
+
}
|
|
365
|
+
admitWorkspaceOccupancy(lockedRead, workspace);
|
|
366
|
+
const canonicalAfter = canonicalBindAfter(after, prepared.selected);
|
|
367
|
+
validateBindAfter(lockedRead, canonicalAfter);
|
|
368
|
+
assertContractAbsent(lockedRead, selectedId);
|
|
297
369
|
selectedPlace = workspace === "worktree"
|
|
298
|
-
? allocateWorktreePlaceFromRead(
|
|
370
|
+
? allocateWorktreePlaceFromRead(lockedRead, input.randomBytes?.(attempt) ?? randomBytesDefault())
|
|
299
371
|
: undefined;
|
|
300
372
|
entry = makeBindEntry({
|
|
301
373
|
id: selectedId, at, actor: input.actor, draft: selectedDraft, base: prepared.entryBase,
|
|
302
|
-
target, after, workspace, place: selectedPlace, bootstrap: bootstrapPlan, taskIds: prepared.taskIds,
|
|
374
|
+
target, after: canonicalAfter, workspace, place: selectedPlace, bootstrap: bootstrapPlan, taskIds: prepared.taskIds,
|
|
303
375
|
});
|
|
304
376
|
admittedScopeOverlaps = await admitScopeRegistration(stableRoot, {
|
|
305
377
|
contractId: entry.contract,
|
|
306
378
|
scope: bindEffectiveScope(entry),
|
|
307
379
|
tree: entry.data.base,
|
|
308
380
|
...(input.exclusive === undefined ? {} : { exclusive: input.exclusive }),
|
|
309
|
-
},
|
|
310
|
-
await revalidateBindAuthority({
|
|
311
|
-
cwd: stableRoot,
|
|
312
|
-
target,
|
|
313
|
-
targetHead: prepared.expectedHead,
|
|
314
|
-
deliveryRef: repositoryDeliveryRef(entry.contract),
|
|
315
|
-
});
|
|
381
|
+
}, lockedRead);
|
|
316
382
|
const written = await publishBind({
|
|
317
383
|
cwd: stableRoot,
|
|
318
384
|
entry,
|
|
319
|
-
expectedLedgerHead:
|
|
385
|
+
expectedLedgerHead: lockedRead.observedLedgerHead,
|
|
320
386
|
delivery: { ref: repositoryDeliveryRef(entry.contract), head: prepared.entryBase },
|
|
321
387
|
taskBoard: prepared.taskBoard,
|
|
322
388
|
});
|
|
323
389
|
if (written.family === "committed") {
|
|
324
390
|
try {
|
|
325
|
-
await
|
|
391
|
+
await taskTransaction.replace(prepared.taskIds.map((taskId) => {
|
|
392
|
+
const source = prepared.replay.linkedSources.find((candidate) => candidate.path.endsWith(`/${taskId}.md`) || candidate.path.endsWith(`\\${taskId}.md`));
|
|
393
|
+
if (!source)
|
|
394
|
+
throw new FlowError("INTERNAL_STATE", `prepared task bind has no source for ${taskId}`);
|
|
395
|
+
return { id: taskId, text: source.text };
|
|
396
|
+
}));
|
|
397
|
+
const staged = await runGitProcess(stableRoot, ["add", "--", ...prepared.replay.paths]);
|
|
398
|
+
if (staged.status !== 0 || staged.error)
|
|
399
|
+
throw staged.error ?? new Error(staged.stderr);
|
|
400
|
+
preparedTaskProjectionSucceeded = true;
|
|
326
401
|
}
|
|
327
402
|
catch {
|
|
328
403
|
// Authority is already committed. The ordinary derived replay
|
|
329
404
|
// below owns truthful retry/contained classification.
|
|
330
405
|
}
|
|
331
|
-
return written;
|
|
332
406
|
}
|
|
333
407
|
if (written.family === "indeterminate")
|
|
334
408
|
committedOrThrow(written, "BIND_TRANSACTION");
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
409
|
+
return written;
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
if (attempted.result.family === "committed") {
|
|
413
|
+
settled = attempted;
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (!settled)
|
|
418
|
+
throw new FlowError("CONCURRENT_MODIFICATION", "BIND_TRANSACTION_REFUSED: repository authority changed during four bind attempts");
|
|
341
419
|
preparedTask = settled.preparation;
|
|
342
|
-
committedOrThrow(settled.result, "BIND_TRANSACTION");
|
|
420
|
+
const committed = committedOrThrow(settled.result, "BIND_TRANSACTION");
|
|
421
|
+
committedHead = committed.ledgerHead;
|
|
422
|
+
committedEntryObjectId = committed.entryObjectId;
|
|
343
423
|
}
|
|
344
424
|
else {
|
|
345
425
|
let committed;
|
|
346
426
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
throw new FlowError("CONCURRENT_MODIFICATION", "bind target changed during admission");
|
|
353
|
-
}
|
|
427
|
+
const observed = await observeEntry();
|
|
428
|
+
const branch = observed.branch;
|
|
429
|
+
const target = normalizeTargetRef(branch.branch);
|
|
430
|
+
const read = observed.read;
|
|
431
|
+
admittedRead = read;
|
|
354
432
|
validateBindAfter(read, after);
|
|
355
433
|
await selectCandidate(ordinaryDraft, read);
|
|
356
434
|
entry = makeBindEntry({
|
|
@@ -363,12 +441,6 @@ export async function bindContract(input) {
|
|
|
363
441
|
tree: entry.data.base,
|
|
364
442
|
...(input.exclusive === undefined ? {} : { exclusive: input.exclusive }),
|
|
365
443
|
}, read);
|
|
366
|
-
await revalidateBindAuthority({
|
|
367
|
-
cwd: stableRoot,
|
|
368
|
-
target,
|
|
369
|
-
targetHead: branch.head,
|
|
370
|
-
deliveryRef: repositoryDeliveryRef(entry.contract),
|
|
371
|
-
});
|
|
372
444
|
const bindWrite = await publishBind({
|
|
373
445
|
cwd: stableRoot,
|
|
374
446
|
entry,
|
|
@@ -377,6 +449,8 @@ export async function bindContract(input) {
|
|
|
377
449
|
});
|
|
378
450
|
if (bindWrite.family === "committed") {
|
|
379
451
|
committed = bindWrite;
|
|
452
|
+
committedHead = bindWrite.ledgerHead;
|
|
453
|
+
committedEntryObjectId = bindWrite.entryObjectId;
|
|
380
454
|
break;
|
|
381
455
|
}
|
|
382
456
|
if (bindWrite.family === "indeterminate")
|
|
@@ -386,7 +460,33 @@ export async function bindContract(input) {
|
|
|
386
460
|
throw new FlowError("CONCURRENT_MODIFICATION", "BIND_TRANSACTION_REFUSED: repository authority changed during four bind attempts");
|
|
387
461
|
}
|
|
388
462
|
}
|
|
389
|
-
|
|
463
|
+
const repository = advanceRepositorySnapshotWithBind({
|
|
464
|
+
repository: admittedRead,
|
|
465
|
+
ledgerHead: repositoryLedgerHead(committedHead),
|
|
466
|
+
entryObjectId: committedEntryObjectId,
|
|
467
|
+
entry: entry,
|
|
468
|
+
});
|
|
469
|
+
const committedContract = lookupCurrentContract(repository, entry.contract);
|
|
470
|
+
if (committedContract.status !== "healthy") {
|
|
471
|
+
throw new FlowError("INTERNAL_STATE", `committed bind ${entry.contract} is unavailable (${committedContract.status})`);
|
|
472
|
+
}
|
|
473
|
+
const carrierTarget = entry.data.workspace === "here"
|
|
474
|
+
? { status: "available", root: stableRoot, path: `${stableRoot}/.keiyaku/KEIYAKU.md`, workspace: "here" }
|
|
475
|
+
: { status: "unavailable", workspace: "worktree", reason: `contract ${entry.contract} has no verified registered engine worktree` };
|
|
476
|
+
const snapshot = {
|
|
477
|
+
stableRoot,
|
|
478
|
+
observation: {
|
|
479
|
+
repository,
|
|
480
|
+
lifecycle: committedContract.model,
|
|
481
|
+
target: carrierTarget,
|
|
482
|
+
pins: {
|
|
483
|
+
repositoryLedgerHead: repositoryLedgerHead(committedHead),
|
|
484
|
+
target: { ref: entry.data.target, head: entry.data.base },
|
|
485
|
+
delivery: { ref: repositoryDeliveryRef(entry.contract), head: entry.data.base },
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
return await reconcileCommittedBindFromSnapshot({
|
|
390
490
|
cwd: stableRoot,
|
|
391
491
|
contractId: entry.contract,
|
|
392
492
|
actor: input.actor,
|
|
@@ -397,6 +497,7 @@ export async function bindContract(input) {
|
|
|
397
497
|
...(input.bootstrapRunner ? { bootstrapRunner: input.bootstrapRunner } : {}),
|
|
398
498
|
...(input.bootstrapDependencies ? { bootstrapDependencies: input.bootstrapDependencies } : {}),
|
|
399
499
|
...(preparedTask ? { preparedTask } : {}),
|
|
500
|
+
...(preparedTaskProjectionSucceeded ? { preparedTaskProjectionSucceeded } : {}),
|
|
400
501
|
dependencies: input.dependencies,
|
|
401
|
-
}, admittedScopeOverlaps);
|
|
502
|
+
}, admittedScopeOverlaps, snapshot);
|
|
402
503
|
}
|
package/build/core/call/call.js
CHANGED
|
@@ -8,7 +8,7 @@ import { ACTOR_IDENTITY } from "../../keiyaku.js";
|
|
|
8
8
|
import { appendDebugBlock } from "../../telemetry/debug-log.js";
|
|
9
9
|
import { logInfo } from "../../telemetry/logger.js";
|
|
10
10
|
import { withResolvedAddress } from "../addressing.js";
|
|
11
|
-
import { assertProjectionAlias,
|
|
11
|
+
import { assertProjectionAlias, observeProjectionLife, waitForProjection, } from "../projection/index.js";
|
|
12
12
|
import { normalizeFilesystemCoordinate } from "../../fs/path-coordinate.js";
|
|
13
13
|
import { requireResumableArtifact } from "../transcripts.js";
|
|
14
14
|
import { stableRepoRoot } from "../worktree-path.js";
|
|
@@ -56,7 +56,7 @@ export async function runCall(input) {
|
|
|
56
56
|
const artifactHome = await fs.realpath(reviveArtifact.storageRoot);
|
|
57
57
|
const addressed = normalizeFilesystemCoordinate(input.repo ?? input.cwd);
|
|
58
58
|
const observation = await observeGitRepository(addressed);
|
|
59
|
-
const coordinate = assertGitObservation(observation, "
|
|
59
|
+
const coordinate = assertGitObservation(observation, "fork");
|
|
60
60
|
if (coordinate === "repository") {
|
|
61
61
|
const addressedRoot = await stableRepoRoot(addressed);
|
|
62
62
|
if (addressedRoot !== artifactHome) {
|
|
@@ -74,7 +74,7 @@ export async function runCall(input) {
|
|
|
74
74
|
const title = requireText("title", input.title);
|
|
75
75
|
const task = requireText("task", input.task);
|
|
76
76
|
if (input.incognito && reviveArtifact) {
|
|
77
|
-
throw new FlowError("EMPTY_PARAM", "Parameter 'incognito' cannot be used with
|
|
77
|
+
throw new FlowError("EMPTY_PARAM", "Parameter 'incognito' cannot be used with a fork source artifact — incognito calls cannot be forked or persist conversation history.");
|
|
78
78
|
}
|
|
79
79
|
const keiyakuContext = await readCallKeiyakuContext(cwd, {
|
|
80
80
|
bare: input.bare,
|
|
@@ -92,8 +92,8 @@ export async function runCall(input) {
|
|
|
92
92
|
task,
|
|
93
93
|
context: input.context,
|
|
94
94
|
referenceFiles,
|
|
95
|
-
currentIntent: keiyakuContext.currentIntent,
|
|
96
95
|
commissioned: keiyakuContext.address.binding.kind === "commission",
|
|
96
|
+
worktree: keiyakuContext.effectiveCwd,
|
|
97
97
|
});
|
|
98
98
|
const launchSnapshot = reviveArtifact
|
|
99
99
|
? input.effort !== undefined
|
|
@@ -134,6 +134,7 @@ export async function runCall(input) {
|
|
|
134
134
|
? { kind: "repository" }
|
|
135
135
|
: { kind: "user" },
|
|
136
136
|
binding: keiyakuContext.address.binding,
|
|
137
|
+
carrier: keiyakuContext.carrier,
|
|
137
138
|
title,
|
|
138
139
|
context: input.context,
|
|
139
140
|
...(input.mode === "call" && input.alias !== undefined ? { alias: assertProjectionAlias(input.alias) } : {}),
|
|
@@ -144,7 +145,6 @@ export async function runCall(input) {
|
|
|
144
145
|
id: launched.projection.id,
|
|
145
146
|
phase: observeProjectionLife(launched.projection.dir, {
|
|
146
147
|
nowMs: Date.now(),
|
|
147
|
-
startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS,
|
|
148
148
|
}).phase,
|
|
149
149
|
...(launched.projection.alias ? { alias: launched.projection.alias } : {}),
|
|
150
150
|
...(launched.projection.previousAliasTarget ? { previousAliasTarget: launched.projection.previousAliasTarget } : {}),
|
|
@@ -206,7 +206,6 @@ export async function runCall(input) {
|
|
|
206
206
|
id: execution.projection.id,
|
|
207
207
|
phase: observeProjectionLife(execution.projection.dir, {
|
|
208
208
|
nowMs: Date.now(),
|
|
209
|
-
startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS,
|
|
210
209
|
}).phase,
|
|
211
210
|
};
|
|
212
211
|
}
|
|
@@ -222,7 +221,7 @@ export async function runCall(input) {
|
|
|
222
221
|
launchSnapshot: subagentOutcome.launchSnapshot,
|
|
223
222
|
...(responsePath ? { responsePath } : {}),
|
|
224
223
|
...(artifactId ? { artifactId } : {}),
|
|
225
|
-
...(reviveArtifact ? {
|
|
224
|
+
...(reviveArtifact ? { sourceArtifactId: reviveArtifact.artifactId } : {}),
|
|
226
225
|
projectionOwnsResponsePersistence: execution.projection !== undefined,
|
|
227
226
|
meta: {
|
|
228
227
|
...(subagentOutcome.warnings.length > 0 ? { warnings: subagentOutcome.warnings.map(renderSubagentWarning) } : {}),
|
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
2
3
|
import { FlowError } from "../../flow-error.js";
|
|
3
4
|
import { assertGitObservation, observeGitRepository } from "../../git/branches.js";
|
|
4
5
|
import { AddressResolutionError, buildResolutionAttempt, buildUncommissionedAddress, buildUncommissionedRepositoryAddress, resolveCallWorktreeAddressFromRead, resolveExplicitContractAddressFromRead, withResolvedAddress, } from "../addressing.js";
|
|
5
6
|
import { normalizeFilesystemCoordinate } from "../../fs/path-coordinate.js";
|
|
6
7
|
import { readRepositoryLifecycle, } from "../repository-ledger/read-model.js";
|
|
7
8
|
import { isTerminalState } from "../status/lifecycle.js";
|
|
9
|
+
import { verifyCarrier } from "../contract-carrier.js";
|
|
8
10
|
import { findRegisteredContractWorktreePathFromModel, stableRepoRoot, } from "../worktree-path.js";
|
|
11
|
+
import { KEIYAKU_FILE } from "../../keiyaku.js";
|
|
12
|
+
function throwCarrierDispatchRefusal(contractId, verification) {
|
|
13
|
+
let status;
|
|
14
|
+
if (verification.status === "missing") {
|
|
15
|
+
status = "missing";
|
|
16
|
+
}
|
|
17
|
+
else if (verification.status === "invalid-header") {
|
|
18
|
+
status = "incomplete-replay";
|
|
19
|
+
}
|
|
20
|
+
else if (verification.status === "identity-mismatch") {
|
|
21
|
+
status = verification.actual.contractId !== verification.expected.contractId ? "wrong-contract" : "lagging";
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
status = "modified";
|
|
25
|
+
}
|
|
26
|
+
const recoveryCommand = `keiyaku bind --contract ${contractId}`;
|
|
27
|
+
throw new FlowError("CARRIER_MATERIALIZATION_FAILED", `contract ${contractId} carrier is ${status}; recover with ${recoveryCommand}`, {
|
|
28
|
+
facts: {
|
|
29
|
+
kind: "carrier_dispatch_refusal",
|
|
30
|
+
contractId,
|
|
31
|
+
status,
|
|
32
|
+
carrierPath: verification.target,
|
|
33
|
+
recoveryCommand,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
9
37
|
export async function readCallKeiyakuContext(executionCwd, input, ports = {}) {
|
|
10
38
|
executionCwd = normalizeFilesystemCoordinate(executionCwd);
|
|
11
39
|
input.repoCwd = input.repoCwd === undefined ? undefined : normalizeFilesystemCoordinate(input.repoCwd);
|
|
@@ -148,49 +176,34 @@ export async function readCallKeiyakuContext(executionCwd, input, ports = {}) {
|
|
|
148
176
|
if (isTerminalState(address.lifecycle)) {
|
|
149
177
|
throw new FlowError("EMPTY_PARAM", `commission ${contractId} is terminal and cannot launch an Akuma`);
|
|
150
178
|
}
|
|
151
|
-
const bind = model.history[0]?.entry;
|
|
152
|
-
if (!bind || bind.kind !== "bind") {
|
|
153
|
-
throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger is missing bind entry`);
|
|
154
|
-
}
|
|
155
179
|
const effectiveCwd = model.resources.worktree
|
|
156
180
|
? await findRegisteredContractWorktreePathFromModel(ledgerCwd, model)
|
|
157
181
|
: await fs.realpath(ledgerCwd);
|
|
158
182
|
if (!effectiveCwd) {
|
|
159
183
|
throw new FlowError("INTERNAL_STATE", `contract ${contractId} has no verified registered engine worktree`);
|
|
160
184
|
}
|
|
185
|
+
const carrier = await verifyCarrier({
|
|
186
|
+
target: path.join(effectiveCwd, KEIYAKU_FILE),
|
|
187
|
+
lifecycle: model,
|
|
188
|
+
});
|
|
189
|
+
if (carrier.status !== "current")
|
|
190
|
+
throwCarrierDispatchRefusal(contractId, carrier);
|
|
161
191
|
const executionAddress = { ...address, workdir: effectiveCwd };
|
|
162
|
-
const
|
|
163
|
-
? model.intent
|
|
164
|
-
: null;
|
|
165
|
-
const currentIntent = openArc
|
|
166
|
-
? {
|
|
167
|
-
source: "arc",
|
|
168
|
-
arc: openArc.arc,
|
|
169
|
-
title: openArc.title,
|
|
170
|
-
objective: openArc.objective,
|
|
171
|
-
brief: openArc.brief ?? "",
|
|
172
|
-
}
|
|
173
|
-
: model.history.some(({ entry }) => entry.kind === "arc")
|
|
174
|
-
? undefined
|
|
175
|
-
: {
|
|
176
|
-
source: "bind",
|
|
177
|
-
arc: 0,
|
|
178
|
-
title: bind.data.title,
|
|
179
|
-
context: bind.data.context,
|
|
180
|
-
objective: bind.data.objective,
|
|
181
|
-
design: bind.data.design,
|
|
182
|
-
scope: [...model.effectiveScope],
|
|
183
|
-
criteria: [...bind.data.criteria],
|
|
184
|
-
verification: [...bind.data.verification],
|
|
185
|
-
extensions: bind.data.extensions.map((extension) => ({ ...extension })),
|
|
186
|
-
};
|
|
192
|
+
const { contractId: verifiedContractId, contractHead: verifiedContractHead, bodyDigest } = carrier.actual;
|
|
187
193
|
return {
|
|
188
194
|
activeKeiyaku: true,
|
|
189
195
|
effectiveCwd,
|
|
190
196
|
historyCwd: ledgerCwd,
|
|
191
197
|
profileCwd: effectiveCwd,
|
|
192
198
|
projectionCwd: ledgerCwd,
|
|
193
|
-
|
|
199
|
+
carrier: {
|
|
200
|
+
path: ".keiyaku/KEIYAKU.md",
|
|
201
|
+
identity: {
|
|
202
|
+
contractId: verifiedContractId,
|
|
203
|
+
contractHead: verifiedContractHead,
|
|
204
|
+
bodyDigest,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
194
207
|
address: executionAddress,
|
|
195
208
|
};
|
|
196
209
|
});
|