@astrosheep/keiyaku 2.8.4 → 2.9.0
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 +35 -15
- package/build/.tsbuildinfo +1 -1
- package/build/agents/{call-terms_v2.js → call-terms.js} +12 -8
- package/build/agents/harness/control-types.js +1 -0
- package/build/agents/harness/execution-handle.js +23 -3
- package/build/agents/harness/index.js +6 -607
- package/build/agents/harness/outcome.js +141 -0
- package/build/agents/harness/projection.js +310 -0
- package/build/agents/harness/router.js +201 -0
- package/build/agents/harness/runtime.js +2 -1
- package/build/agents/{launch-snapshot_v2.js → launch-snapshot/model.js} +69 -74
- package/build/agents/launch-snapshot/resolve.js +72 -0
- package/build/agents/opencode-sdk.js +24 -3
- package/build/agents/providers/{claude-agent-sdk.js → claude-agent-sdk/adapter.js} +46 -368
- package/build/agents/providers/claude-agent-sdk/events.js +218 -0
- package/build/agents/providers/claude-agent-sdk/session.js +158 -0
- package/build/agents/providers/codex-app-server/adapter.js +347 -0
- package/build/agents/providers/codex-app-server/events.js +352 -0
- package/build/agents/providers/codex-app-server/session.js +266 -0
- package/build/agents/providers/codex-sdk.js +23 -5
- package/build/agents/providers/opencode-sdk/adapter.js +344 -0
- package/build/agents/providers/opencode-sdk/events.js +354 -0
- package/build/agents/providers/opencode-sdk/session.js +180 -0
- package/build/agents/providers/pi/adapter.js +269 -0
- package/build/agents/providers/pi/checkpoint.js +41 -0
- package/build/agents/providers/pi/events.js +282 -0
- package/build/agents/{selector_v2.js → selector.js} +8 -6
- package/build/cli/commands/akuma/akuma/handler.js +4 -0
- package/build/cli/commands/akuma/akuma/meta.js +16 -0
- package/build/cli/commands/akuma/catalog.js +8 -0
- package/build/cli/commands/akuma/list/handler.js +15 -0
- package/build/cli/commands/akuma/list/meta-ls.js +9 -0
- package/build/cli/commands/akuma/view/handler.js +34 -0
- package/build/cli/commands/akuma/view/meta.js +8 -0
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +10 -0
- package/build/cli/commands/contract/amend/meta.js +12 -0
- package/build/cli/commands/contract/arc/handler.js +9 -0
- package/build/cli/commands/contract/arc/meta.js +26 -0
- package/build/cli/commands/contract/bind/handler.js +23 -0
- package/build/cli/commands/contract/bind/meta.js +30 -0
- package/build/cli/commands/contract/catalog.js +16 -0
- package/build/cli/commands/contract/forfeit/handler.js +13 -0
- package/build/cli/commands/contract/forfeit/meta.js +12 -0
- package/build/cli/commands/contract/log/handler.js +12 -0
- package/build/cli/commands/contract/log/meta.js +12 -0
- package/build/cli/commands/contract/petition/handler.js +26 -0
- package/build/cli/commands/contract/petition/meta.js +23 -0
- package/build/cli/commands/contract/renew/handler.js +10 -0
- package/build/cli/commands/contract/renew/meta.js +17 -0
- package/build/cli/commands/projection/call/handler.js +39 -0
- package/build/cli/commands/projection/call/meta.js +9 -0
- package/build/cli/commands/projection/catalog.js +14 -0
- package/build/cli/commands/projection/kill/handler.js +35 -0
- package/build/cli/commands/projection/kill/meta.js +11 -0
- package/build/cli/commands/projection/revive/handler.js +53 -0
- package/build/cli/commands/projection/revive/meta.js +9 -0
- package/build/cli/commands/projection/status/handler.js +23 -0
- package/build/cli/commands/projection/status/meta.js +9 -0
- package/build/cli/commands/projection/tell/handler.js +34 -0
- package/build/cli/commands/projection/tell/meta.js +9 -0
- package/build/cli/commands/projection/wait/handler.js +21 -0
- package/build/cli/commands/projection/wait/meta.js +11 -0
- package/build/cli/commands/registry.js +100 -0
- package/build/cli/commands/shared.js +71 -0
- package/build/cli/commands/skills/catalog.js +6 -0
- package/build/cli/commands/skills/install/handler.js +10 -0
- package/build/cli/commands/skills/install/meta.js +9 -0
- package/build/cli/commands/skills/skills/handler.js +4 -0
- package/build/cli/commands/skills/skills/meta.js +10 -0
- package/build/cli/commands/system/catalog.js +8 -0
- package/build/cli/commands/system/completion/handler.js +10 -0
- package/build/cli/commands/system/completion/meta.js +9 -0
- package/build/cli/commands/system/dump-env/handler.js +3 -0
- package/build/cli/commands/system/dump-env/meta.js +10 -0
- package/build/cli/commands/system/guide/handler.js +4 -0
- package/build/cli/commands/system/guide/meta.js +9 -0
- package/build/cli/commands/task/add/handler.js +21 -0
- package/build/cli/commands/task/add/meta.js +8 -0
- package/build/cli/commands/task/catalog.js +22 -0
- package/build/cli/commands/task/doctor/handler.js +4 -0
- package/build/cli/commands/task/doctor/meta.js +8 -0
- package/build/cli/commands/task/done/handler.js +17 -0
- package/build/cli/commands/task/done/meta.js +8 -0
- package/build/cli/commands/task/drop/handler.js +6 -0
- package/build/cli/commands/task/drop/meta.js +8 -0
- package/build/cli/commands/task/ls/handler.js +13 -0
- package/build/cli/commands/task/ls/meta.js +8 -0
- package/build/cli/commands/task/shared.js +131 -0
- package/build/cli/commands/task/start/handler.js +6 -0
- package/build/cli/commands/task/start/meta.js +8 -0
- package/build/cli/commands/task/stop/handler.js +17 -0
- package/build/cli/commands/task/stop/meta.js +8 -0
- package/build/cli/commands/task/task/handler.js +5 -0
- package/build/cli/commands/task/task/meta.js +11 -0
- package/build/cli/commands/task/update/handler.js +18 -0
- package/build/cli/commands/task/update/meta.js +8 -0
- package/build/cli/commands/task/view/handler.js +14 -0
- package/build/cli/commands/task/view/meta.js +8 -0
- package/build/cli/completion.js +26 -27
- package/build/cli/flags.js +79 -2
- package/build/cli/help.js +27 -49
- package/build/cli/index.js +121 -374
- package/build/cli/output-stream-error-policy.js +17 -0
- package/build/cli/parse.js +159 -72
- package/build/cli/projection-address.js +5 -0
- package/build/cli/render/arc.js +1 -1
- package/build/cli/render/errors.js +4 -3
- package/build/cli/render/format.js +14 -0
- package/build/cli/render/kanshi.js +106 -0
- package/build/cli/render/petition.js +24 -1
- package/build/cli/render/projection-activity.js +5 -1
- package/build/cli/render/shared.js +2 -2
- package/build/cli/render/status.js +79 -13
- package/build/cli/render/task.js +113 -0
- package/build/cli/render/wait.js +23 -3
- package/build/cli/types.js +1 -1
- package/build/config/{akuma-loader_v2.js → akuma-loader.js} +2 -2
- package/build/config/env.js +9 -4
- package/build/config/settings/disease.js +26 -0
- package/build/config/settings/knobs.js +8 -0
- package/build/config/settings/loader.js +244 -0
- package/build/config/settings/schema.js +276 -0
- package/build/core/addressing.js +1 -1
- package/build/core/amend.js +3 -3
- package/build/core/arc.js +5 -4
- package/build/core/bind-workspace.js +123 -0
- package/build/core/bind.js +75 -155
- package/build/core/call/call.js +224 -0
- package/build/core/call/context.js +238 -0
- package/build/core/call/execution.js +217 -0
- package/build/core/call/prompt.js +42 -0
- package/build/core/call/reference.js +24 -0
- package/build/core/call-persist.js +1 -1
- package/build/core/claim-delivery.js +247 -0
- package/build/core/claim.js +39 -277
- package/build/core/context.js +2 -1
- package/build/core/{render.js → contract-view.js} +12 -140
- package/build/core/draft.js +107 -9
- package/build/core/entry.js +9 -1
- package/build/core/execution-coordinate.js +4 -20
- package/build/core/execution-pact.js +16 -31
- package/build/core/forfeit.js +35 -22
- package/build/core/hints.js +2 -2
- package/build/core/log.js +2 -2
- package/build/core/petition-claim-gates.js +8 -6
- package/build/core/petition-preview.js +97 -0
- package/build/core/petition-run.js +3 -2
- package/build/core/petition.js +39 -26
- package/build/core/projection/generation/database.js +306 -0
- package/build/core/projection/generation/identity.js +84 -0
- package/build/core/projection/generation/model.js +201 -0
- package/build/core/projection/generation/store.js +73 -0
- package/build/core/projection/generation/transitions.js +258 -0
- package/build/core/projection/heart.js +0 -307
- package/build/core/projection/tell/database.js +109 -0
- package/build/core/projection/tell/model.js +97 -0
- package/build/core/{projection-tells.js → projection/tell/store.js} +3 -158
- package/build/core/projection-activity.js +23 -2
- package/build/core/projection-core.js +2 -1
- package/build/core/projection-execution-observer.js +259 -0
- package/build/core/projection-generation-continuation.js +1 -1
- package/build/core/projection-generation-execution.js +90 -20
- package/build/core/projection-generation-launcher.js +1 -1
- package/build/core/projection-generation-runner.js +198 -4
- package/build/core/projection-identity.js +1 -1
- package/build/core/projection-kill.js +50 -17
- package/build/core/projection-life-observer.js +1 -1
- package/build/core/projection-life-protocol.js +10 -0
- package/build/core/projection-mint.js +1 -1
- package/build/core/projection-status.js +45 -32
- package/build/core/projection-wait.js +12 -2
- package/build/core/projection-wake.js +5 -2
- package/build/core/{queue_v2.js → queue.js} +2 -1
- package/build/core/registry.js +1 -1
- package/build/core/renew.js +7 -7
- package/build/core/response-artifact-catalog-sqlite.js +112 -0
- package/build/core/response-artifact-catalog.js +7 -0
- package/build/core/seal.js +44 -16
- package/build/core/status/board.js +286 -0
- package/build/core/status/drift.js +99 -0
- package/build/core/status/lifecycle.js +84 -0
- package/build/core/status/reconciliation.js +131 -0
- package/build/core/stored-agent-event.js +28 -4
- package/build/core/target-ref.js +10 -0
- package/build/core/task/board.js +175 -0
- package/build/core/task/commands.js +211 -0
- package/build/core/task/document.js +189 -0
- package/build/core/task/model.js +1 -0
- package/build/core/task/settlement-git.js +207 -0
- package/build/core/task/settlement-policy.js +82 -0
- package/build/core/task/source-board.js +84 -0
- package/build/core/task/source-model.js +1 -0
- package/build/core/task/validation.js +44 -0
- package/build/core/task-contract.js +224 -0
- package/build/core/task-doctor.js +14 -0
- package/build/core/task-git-actor.js +38 -0
- package/build/core/task-git-runtime.js +34 -0
- package/build/core/task-git-store.js +375 -0
- package/build/core/task-repository.js +1 -0
- package/build/core/task-store-repository.js +86 -0
- package/build/core/task-store.js +1 -0
- package/build/core/task-worktree.js +51 -0
- package/build/core/task.js +4 -0
- package/build/core/transcripts.js +138 -56
- package/build/core/validation.js +17 -0
- package/build/core/verdict.js +2 -2
- package/build/core/worktree-path.js +24 -6
- package/build/flow-error.js +3 -2
- package/build/generated/version.js +1 -1
- package/build/git/commits.js +3 -0
- package/build/git/diff/parsers.js +0 -94
- package/build/index.js +2 -0
- package/build/keiyaku-constants.js +2 -0
- package/build/keiyaku.js +4 -3
- package/package.json +3 -2
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +11 -6
- package/build/agents/harness/pump.js +0 -158
- package/build/agents/providers/codex-app-server.js +0 -864
- package/build/agents/providers/opencode-sdk.js +0 -363
- package/build/agents/providers/pi.js +0 -557
- package/build/config/settings.js +0 -533
- package/build/core/call.js +0 -686
- package/build/core/projection/generation.js +0 -412
- package/build/core/projection/identity.js +0 -81
- package/build/core/projection/mint.js +0 -174
- package/build/core/projection-generation-store.js +0 -707
- package/build/core/status.js +0 -539
package/build/core/bind.js
CHANGED
|
@@ -1,100 +1,27 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { assertSettingsKnobUsable, loadKeiyakuSettings } from "../config/settings.js";
|
|
2
|
+
import { assertSettingsKnobUsable } from "../config/settings/disease.js";
|
|
3
|
+
import { loadKeiyakuSettings } from "../config/settings/loader.js";
|
|
5
4
|
import { FlowError } from "../flow-error.js";
|
|
6
|
-
import {
|
|
7
|
-
import { createGit, wrapGitError } from "../git/core.js";
|
|
8
|
-
import { activeLedgerRef, appendEntry, appendWithRetry, listContractIds, readLedger } from "./ledger.js";
|
|
5
|
+
import { activeLedgerRef, appendEntry, appendWithRetry, readLedger } from "./ledger.js";
|
|
9
6
|
import { parseBindDraft } from "./draft.js";
|
|
10
7
|
import { assertValidContractId, buildContractId } from "./ids.js";
|
|
11
|
-
import { CONTRACT_PLACES } from "./places.js";
|
|
12
|
-
import { renderContractView } from "./render.js";
|
|
13
8
|
import { registerScope, releaseScope } from "./registry.js";
|
|
14
|
-
import {
|
|
9
|
+
import { resolveDefaultBranch } from "./status/drift.js";
|
|
10
|
+
import { normalizeTargetRef } from "./target-ref.js";
|
|
11
|
+
import { reconcileTaskForfeit, settleTaskBoardForBind } from "./task-contract.js";
|
|
15
12
|
import { bootstrapEntryDataFromObservation, isBootstrapSuccess, runWorktreeBootstrap, } from "./worktree-bootstrap.js";
|
|
16
|
-
import { contractWorktreePathFromBind,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
throw wrapGitError("rev-parse HEAD", error, cwd);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
async function createBranch(cwd, branch, base) {
|
|
30
|
-
const git = createGit(cwd);
|
|
31
|
-
try {
|
|
32
|
-
await git.raw(["branch", branch, base]);
|
|
33
|
-
}
|
|
34
|
-
catch (error) {
|
|
35
|
-
throw wrapGitError(`branch ${branch} ${base}`, error, cwd);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
async function defaultCreateWorktree(input) {
|
|
39
|
-
const git = createGit(input.cwd);
|
|
40
|
-
try {
|
|
41
|
-
await git.raw(["worktree", "add", input.worktreePath, input.branch]);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
throw wrapGitError(`worktree add ${input.worktreePath} ${input.branch}`, error, input.cwd);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
async function resolveTreeRoot(cwd, workspace, contractId, bind) {
|
|
48
|
-
const repoRoot = await fs.realpath(cwd);
|
|
49
|
-
if (workspace === "here")
|
|
50
|
-
return repoRoot;
|
|
51
|
-
return await contractWorktreePathFromBind(repoRoot, contractId, bind);
|
|
52
|
-
}
|
|
53
|
-
async function removeWorktree(cwd, worktreePath) {
|
|
54
|
-
const git = createGit(cwd);
|
|
55
|
-
try {
|
|
56
|
-
await git.raw(["worktree", "remove", "--force", worktreePath]);
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
throw wrapGitError(`worktree remove ${worktreePath}`, error, cwd);
|
|
13
|
+
import { contractWorktreePathFromBind, stableRepoRoot } from "./worktree-path.js";
|
|
14
|
+
import { allocateWorktreePlace, cleanupCreatedBindResources, createContractBranch, defaultCreateWorktree, materializeContractView, resolveTreeRoot, } from "./bind-workspace.js";
|
|
15
|
+
class BindLedgerCollisionError extends Error {
|
|
16
|
+
contractId;
|
|
17
|
+
constructor(contractId) {
|
|
18
|
+
super(`contract ledger already exists for ${contractId}`);
|
|
19
|
+
this.contractId = contractId;
|
|
20
|
+
this.name = "BindLedgerCollisionError";
|
|
60
21
|
}
|
|
61
22
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
await git.raw(["branch", "-D", branch]);
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
throw wrapGitError(`branch -D ${branch}`, error, cwd);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
async function cleanupCreatedResources(cwd, resources) {
|
|
72
|
-
const failures = [];
|
|
73
|
-
if (resources.keiyakuPath) {
|
|
74
|
-
try {
|
|
75
|
-
await fs.rm(resources.keiyakuPath, { force: true });
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
failures.push(`delete ${resources.keiyakuPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (resources.worktreePath) {
|
|
82
|
-
try {
|
|
83
|
-
await removeWorktree(cwd, resources.worktreePath);
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
failures.push(`remove worktree: ${error instanceof Error ? error.message : String(error)}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (resources.branch) {
|
|
90
|
-
try {
|
|
91
|
-
await deleteBranch(cwd, resources.branch);
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
failures.push(`delete branch: ${error instanceof Error ? error.message : String(error)}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return failures;
|
|
23
|
+
function randomBytesDefault() {
|
|
24
|
+
return [...crypto.randomBytes(10)];
|
|
98
25
|
}
|
|
99
26
|
async function appendBindFailedForfeit(cwd, id, actor, at) {
|
|
100
27
|
const forfeit = {
|
|
@@ -108,11 +35,18 @@ async function appendBindFailedForfeit(cwd, id, actor, at) {
|
|
|
108
35
|
by: actor,
|
|
109
36
|
},
|
|
110
37
|
};
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
38
|
+
const stableRoot = await stableRepoRoot(cwd);
|
|
39
|
+
await reconcileTaskForfeit({
|
|
40
|
+
cwd: stableRoot,
|
|
41
|
+
contractId: id,
|
|
42
|
+
publishLedger: async () => {
|
|
43
|
+
const result = await appendWithRetry(stableRoot, activeLedgerRef(id), () => forfeit, { maxRetries: 1 });
|
|
44
|
+
if (!result.ok) {
|
|
45
|
+
throw new FlowError("INTERNAL_STATE", `BIND_FAILURE_FORFEIT_FAILED: failed to append bind-failed forfeit for ${id}: ${result.reason}`);
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
},
|
|
49
|
+
});
|
|
116
50
|
}
|
|
117
51
|
async function appendBootstrapEntry(cwd, id, actor, at, data) {
|
|
118
52
|
const entry = {
|
|
@@ -151,41 +85,6 @@ function resolvedBootstrapPlan(settings) {
|
|
|
151
85
|
function bootstrapProgressLine(command) {
|
|
152
86
|
return `bootstrap » ${command.join(" ")}`;
|
|
153
87
|
}
|
|
154
|
-
async function occupiedWorktreePlaces(cwd) {
|
|
155
|
-
const occupied = new Set();
|
|
156
|
-
for (const id of await listContractIds(cwd)) {
|
|
157
|
-
const ledger = await readLedger(cwd, id);
|
|
158
|
-
if (!ledger || isTerminalState(deriveContractState(ledger.entries)))
|
|
159
|
-
continue;
|
|
160
|
-
const place = findBindEntry(ledger.entries)?.data.place;
|
|
161
|
-
if (place)
|
|
162
|
-
occupied.add(place);
|
|
163
|
-
}
|
|
164
|
-
return occupied;
|
|
165
|
-
}
|
|
166
|
-
function randomIndex(randomBytes, size) {
|
|
167
|
-
let value = 0;
|
|
168
|
-
for (const byte of randomBytes) {
|
|
169
|
-
value = (value * 256 + byte) % size;
|
|
170
|
-
}
|
|
171
|
-
return value;
|
|
172
|
-
}
|
|
173
|
-
function nextGenerationPlace(base, occupied) {
|
|
174
|
-
for (let generation = 2;; generation += 1) {
|
|
175
|
-
const candidate = `${base}${generation}`;
|
|
176
|
-
if (!occupied.has(candidate))
|
|
177
|
-
return candidate;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
async function allocateWorktreePlace(cwd, randomBytes) {
|
|
181
|
-
const occupied = await occupiedWorktreePlaces(cwd);
|
|
182
|
-
const candidates = CONTRACT_PLACES.filter((place) => !occupied.has(place));
|
|
183
|
-
if (candidates.length > 0) {
|
|
184
|
-
return candidates[randomIndex(randomBytes, candidates.length)];
|
|
185
|
-
}
|
|
186
|
-
const base = CONTRACT_PLACES[randomIndex(randomBytes, CONTRACT_PLACES.length)];
|
|
187
|
-
return nextGenerationPlace(base, occupied);
|
|
188
|
-
}
|
|
189
88
|
function makeBindEntry(input) {
|
|
190
89
|
return {
|
|
191
90
|
v: 1,
|
|
@@ -197,6 +96,8 @@ function makeBindEntry(input) {
|
|
|
197
96
|
name: input.draft.name,
|
|
198
97
|
objective: input.draft.objective,
|
|
199
98
|
scope: input.draft.scope,
|
|
99
|
+
checks: input.draft.checks,
|
|
100
|
+
extensions: input.draft.extensions,
|
|
200
101
|
base: input.base,
|
|
201
102
|
target: input.target,
|
|
202
103
|
workspace: input.workspace,
|
|
@@ -210,7 +111,6 @@ export async function bindContract(input) {
|
|
|
210
111
|
const draft = parseBindDraft(input.draft);
|
|
211
112
|
const workspace = input.workspace ?? "here";
|
|
212
113
|
const at = new Date(input.nowMs).toISOString();
|
|
213
|
-
const base = await getHead(input.cwd);
|
|
214
114
|
const defaultBranch = await resolveDefaultBranch(input.cwd);
|
|
215
115
|
if (!defaultBranch) {
|
|
216
116
|
throw new FlowError("INTERNAL_STATE", "cannot bind: no default branch");
|
|
@@ -232,30 +132,49 @@ export async function bindContract(input) {
|
|
|
232
132
|
randomBytes,
|
|
233
133
|
});
|
|
234
134
|
await assertValidContractId(input.cwd, id);
|
|
235
|
-
const entry = makeBindEntry({
|
|
236
|
-
id,
|
|
237
|
-
at,
|
|
238
|
-
actor: input.actor,
|
|
239
|
-
draft,
|
|
240
|
-
base,
|
|
241
|
-
target,
|
|
242
|
-
after: input.after ?? [],
|
|
243
|
-
workspace,
|
|
244
|
-
place,
|
|
245
|
-
bootstrap: bootstrapPlan,
|
|
246
|
-
});
|
|
247
135
|
const ref = activeLedgerRef(id);
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
136
|
+
let settlement;
|
|
137
|
+
try {
|
|
138
|
+
settlement = await settleTaskBoardForBind({
|
|
139
|
+
cwd: input.cwd,
|
|
140
|
+
...(input.taskId === undefined ? {} : { taskId: input.taskId }),
|
|
141
|
+
contractId: id,
|
|
142
|
+
publishLedger: async (base) => {
|
|
143
|
+
const entry = makeBindEntry({
|
|
144
|
+
id,
|
|
145
|
+
at,
|
|
146
|
+
actor: input.actor,
|
|
147
|
+
draft,
|
|
148
|
+
base,
|
|
149
|
+
target,
|
|
150
|
+
after: input.after ?? [],
|
|
151
|
+
workspace,
|
|
152
|
+
place,
|
|
153
|
+
bootstrap: bootstrapPlan,
|
|
154
|
+
});
|
|
155
|
+
const appended = await appendEntry(input.cwd, ref, entry, null);
|
|
156
|
+
if (!appended.ok)
|
|
157
|
+
throw new BindLedgerCollisionError(id);
|
|
158
|
+
return { entry, appended };
|
|
159
|
+
},
|
|
160
|
+
});
|
|
252
161
|
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (error instanceof BindLedgerCollisionError) {
|
|
164
|
+
collidedIds.push(id);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
const { entry, appended } = settlement.ledger;
|
|
170
|
+
const base = settlement.boardCommit;
|
|
253
171
|
const resources = { id };
|
|
254
172
|
const branch = `keiyaku/${id}`;
|
|
255
173
|
const worktreePath = await contractWorktreePathFromBind(input.cwd, id, entry);
|
|
256
174
|
const targetRoot = workspace === "here" ? input.cwd : worktreePath;
|
|
257
175
|
let ledgerHead = appended.head;
|
|
258
176
|
let bootstrapRecorded = false;
|
|
177
|
+
let registryRegistered = false;
|
|
259
178
|
try {
|
|
260
179
|
const tree = await resolveTreeRoot(input.cwd, workspace, id, entry);
|
|
261
180
|
const registration = await registerScope(input.cwd, {
|
|
@@ -266,9 +185,9 @@ export async function bindContract(input) {
|
|
|
266
185
|
at,
|
|
267
186
|
exclusive: input.exclusive,
|
|
268
187
|
});
|
|
269
|
-
|
|
188
|
+
registryRegistered = true;
|
|
270
189
|
if (workspace === "worktree") {
|
|
271
|
-
await
|
|
190
|
+
await createContractBranch(input.cwd, branch, base);
|
|
272
191
|
resources.branch = branch;
|
|
273
192
|
await (input.createWorktree ?? defaultCreateWorktree)({
|
|
274
193
|
cwd: input.cwd,
|
|
@@ -292,10 +211,11 @@ export async function bindContract(input) {
|
|
|
292
211
|
const ledger = await readLedger(input.cwd, id);
|
|
293
212
|
if (!ledger)
|
|
294
213
|
throw new FlowError("INTERNAL_STATE", `LEDGER_MISSING: ledger missing immediately after bind for ${id}`);
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
214
|
+
resources.keiyakuPath = await materializeContractView({
|
|
215
|
+
targetRoot,
|
|
216
|
+
id,
|
|
217
|
+
entries: ledger.entries,
|
|
218
|
+
});
|
|
299
219
|
return {
|
|
300
220
|
id,
|
|
301
221
|
ref,
|
|
@@ -314,7 +234,7 @@ export async function bindContract(input) {
|
|
|
314
234
|
// Non-bootstrap failure: cleanup first remains compatible with prior path,
|
|
315
235
|
// then forfeit. When bootstrap already recorded its failed fact, forfeit
|
|
316
236
|
// must precede cleanup.
|
|
317
|
-
cleanupFailures.push(...(await
|
|
237
|
+
cleanupFailures.push(...(await cleanupCreatedBindResources(input.cwd, resources)));
|
|
318
238
|
try {
|
|
319
239
|
await appendBindFailedForfeit(input.cwd, id, input.actor, at);
|
|
320
240
|
}
|
|
@@ -329,9 +249,9 @@ export async function bindContract(input) {
|
|
|
329
249
|
catch (forfeitError) {
|
|
330
250
|
cleanupFailures.push(forfeitError instanceof Error ? forfeitError.message : String(forfeitError));
|
|
331
251
|
}
|
|
332
|
-
cleanupFailures.push(...(await
|
|
252
|
+
cleanupFailures.push(...(await cleanupCreatedBindResources(input.cwd, resources)));
|
|
333
253
|
}
|
|
334
|
-
if (
|
|
254
|
+
if (registryRegistered) {
|
|
335
255
|
try {
|
|
336
256
|
await releaseScope(input.cwd, { contractId: id, actor: input.actor, at });
|
|
337
257
|
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import { selectSubagent } from "../../agents/selector.js";
|
|
3
|
+
import { applySnapshotEffort } from "../../agents/launch-snapshot/model.js";
|
|
4
|
+
import { resolveAkumaLaunchSnapshot } from "../../agents/launch-snapshot/resolve.js";
|
|
5
|
+
import { FlowError, requireText } from "../../flow-error.js";
|
|
6
|
+
import { isGitRepo } from "../../git/branches.js";
|
|
7
|
+
import { ACTOR_IDENTITY } from "../../keiyaku.js";
|
|
8
|
+
import { appendDebugBlock } from "../../telemetry/debug-log.js";
|
|
9
|
+
import { logInfo } from "../../telemetry/logger.js";
|
|
10
|
+
import { withResolvedAddress } from "../addressing.js";
|
|
11
|
+
import { assertProjectionAlias } from "../projection-alias.js";
|
|
12
|
+
import { PROJECTION_ADOPTION_TIMEOUT_MS } from "../projection-generation-launcher.js";
|
|
13
|
+
import { observeProjectionLife } from "../projection-life-observer.js";
|
|
14
|
+
import { waitForProjection } from "../projection-wait.js";
|
|
15
|
+
import { requireResumableArtifact } from "../transcripts.js";
|
|
16
|
+
import { stableRepoRoot } from "../worktree-path.js";
|
|
17
|
+
import { readCallKeiyakuContext } from "./context.js";
|
|
18
|
+
import { executeSubagent, launchSubagentGeneration, } from "./execution.js";
|
|
19
|
+
import { buildCallPrompt } from "./prompt.js";
|
|
20
|
+
import { collectCallReferenceFiles } from "./reference.js";
|
|
21
|
+
function renderSubagentWarning(warning) {
|
|
22
|
+
if (warning.reason === "retry") {
|
|
23
|
+
const status = warning.errorStatus === null ? "no response" : String(warning.errorStatus);
|
|
24
|
+
return `Provider warning: retry. attempt=${warning.attempt}, maxRetries=${warning.maxRetries}, retryDelayMs=${warning.retryDelayMs}, errorStatus=${status}`;
|
|
25
|
+
}
|
|
26
|
+
const modelTransition = warning.originalModel && warning.fallbackModel
|
|
27
|
+
? `${warning.originalModel} -> ${warning.fallbackModel}`
|
|
28
|
+
: warning.originalModel ?? warning.fallbackModel;
|
|
29
|
+
const details = [
|
|
30
|
+
modelTransition,
|
|
31
|
+
warning.direction ? `direction=${warning.direction}` : undefined,
|
|
32
|
+
warning.requestId !== undefined ? `requestId=${warning.requestId ?? "null"}` : undefined,
|
|
33
|
+
warning.signerModel ? `signerModel=${warning.signerModel}` : undefined,
|
|
34
|
+
].filter((value) => Boolean(value));
|
|
35
|
+
const summary = warning.reason === "refusal" ? "Provider warning: model fallback." : "Provider warning: overload fallback.";
|
|
36
|
+
return details.length > 0 ? `${summary} ${details.join(", ")}` : summary;
|
|
37
|
+
}
|
|
38
|
+
export async function execSubagent(agentName, prompt, cwd, options) {
|
|
39
|
+
const { outcome } = await executeSubagent(agentName, prompt, cwd, options);
|
|
40
|
+
return outcome;
|
|
41
|
+
}
|
|
42
|
+
export async function runCall(input) {
|
|
43
|
+
const { signal, agent } = input;
|
|
44
|
+
const reviveArtifact = input.reviveArtifact ? requireResumableArtifact(input.reviveArtifact) : undefined;
|
|
45
|
+
let rawCwd = input.cwd;
|
|
46
|
+
let rawRepo = input.repo;
|
|
47
|
+
if (reviveArtifact?.provenance.authority.kind === "user") {
|
|
48
|
+
if (!("workdir" in reviveArtifact.provenance.evidence)) {
|
|
49
|
+
throw new FlowError("INVALID_RESPONSE_PATH", `Invalid response artifact '${reviveArtifact.artifactId}': field 'provenance.evidence.workdir' is missing.`);
|
|
50
|
+
}
|
|
51
|
+
rawCwd = reviveArtifact.provenance.evidence.workdir;
|
|
52
|
+
rawRepo = undefined;
|
|
53
|
+
}
|
|
54
|
+
else if (reviveArtifact?.provenance.authority.kind === "repository") {
|
|
55
|
+
const artifactHome = await fs.realpath(reviveArtifact.storageRoot);
|
|
56
|
+
const addressed = input.repo ?? input.cwd;
|
|
57
|
+
if (await isGitRepo(addressed)) {
|
|
58
|
+
const addressedRoot = await stableRepoRoot(addressed);
|
|
59
|
+
if (addressedRoot !== artifactHome) {
|
|
60
|
+
throw new FlowError("INVALID_RESPONSE_PATH", `Response artifact '${reviveArtifact.artifactId}' belongs to ${artifactHome}, but the addressed repository is ${addressedRoot}.`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
rawCwd = artifactHome;
|
|
64
|
+
rawRepo = artifactHome;
|
|
65
|
+
}
|
|
66
|
+
const cwd = await fs.realpath(rawCwd);
|
|
67
|
+
const repoCwd = rawRepo ? await fs.realpath(rawRepo) : undefined;
|
|
68
|
+
const title = requireText("title", input.title);
|
|
69
|
+
const task = requireText("task", input.task);
|
|
70
|
+
if (input.incognito && reviveArtifact) {
|
|
71
|
+
throw new FlowError("EMPTY_PARAM", "Parameter 'incognito' cannot be used with 'reviveArtifact' — incognito calls cannot be revived or persist conversation history.");
|
|
72
|
+
}
|
|
73
|
+
const keiyakuContext = await readCallKeiyakuContext(cwd, {
|
|
74
|
+
bare: input.bare,
|
|
75
|
+
contractId: input.contractId,
|
|
76
|
+
contractAddressSource: input.contractAddressSource,
|
|
77
|
+
mode: input.mode ?? "call",
|
|
78
|
+
repoCwd,
|
|
79
|
+
reviveBinding: reviveArtifact?.provenance.binding,
|
|
80
|
+
});
|
|
81
|
+
return await withResolvedAddress(keiyakuContext.address, async () => {
|
|
82
|
+
const executionCwd = keiyakuContext.effectiveCwd;
|
|
83
|
+
const referenceFiles = await collectCallReferenceFiles(executionCwd, keiyakuContext);
|
|
84
|
+
const prompt = buildCallPrompt({
|
|
85
|
+
task,
|
|
86
|
+
context: input.context,
|
|
87
|
+
referenceFiles,
|
|
88
|
+
currentIntent: keiyakuContext.currentIntent,
|
|
89
|
+
});
|
|
90
|
+
const launchSnapshot = reviveArtifact
|
|
91
|
+
? input.effort !== undefined
|
|
92
|
+
? applySnapshotEffort(reviveArtifact.launchSnapshot, input.effort)
|
|
93
|
+
: reviveArtifact.launchSnapshot
|
|
94
|
+
: resolveAkumaLaunchSnapshot(await selectSubagent(agent, keiyakuContext.profileCwd), {
|
|
95
|
+
executionCwd,
|
|
96
|
+
projectRoot: keiyakuContext.profileCwd,
|
|
97
|
+
...(input.model !== undefined ? { model: input.model } : {}),
|
|
98
|
+
...(input.effort !== undefined ? { effort: input.effort } : {}),
|
|
99
|
+
});
|
|
100
|
+
const continuation = reviveArtifact
|
|
101
|
+
? {
|
|
102
|
+
session: reviveArtifact.session,
|
|
103
|
+
resumePath: reviveArtifact.absolutePath,
|
|
104
|
+
sourceArtifactId: reviveArtifact.artifactId,
|
|
105
|
+
}
|
|
106
|
+
: undefined;
|
|
107
|
+
logInfo(`[${ACTOR_IDENTITY}] Running execution for '${launchSnapshot.akuma.name}' in ${executionCwd}`, {
|
|
108
|
+
cwd: executionCwd,
|
|
109
|
+
section: "script",
|
|
110
|
+
progressOnly: true,
|
|
111
|
+
});
|
|
112
|
+
// Storage coordinate: addressed repository stable root / caller cwd.
|
|
113
|
+
// Evidence coordinate: commission worktree for bound runs; execution cwd otherwise.
|
|
114
|
+
const historyStorageCwd = keiyakuContext.historyCwd;
|
|
115
|
+
const evidenceCwd = executionCwd;
|
|
116
|
+
const executionOptions = {
|
|
117
|
+
signal,
|
|
118
|
+
continuation,
|
|
119
|
+
task,
|
|
120
|
+
launchSnapshot,
|
|
121
|
+
persistProjectionResponse: !input.incognito,
|
|
122
|
+
historyStorageCwd,
|
|
123
|
+
evidenceCwd,
|
|
124
|
+
projectionCwd: keiyakuContext.projectionCwd,
|
|
125
|
+
authority: keiyakuContext.address.repo.kind === "repository"
|
|
126
|
+
? { kind: "repository" }
|
|
127
|
+
: { kind: "user" },
|
|
128
|
+
binding: keiyakuContext.address.binding,
|
|
129
|
+
title,
|
|
130
|
+
context: input.context,
|
|
131
|
+
...(input.mode === "call" && input.alias !== undefined ? { alias: assertProjectionAlias(input.alias) } : {}),
|
|
132
|
+
};
|
|
133
|
+
if ((input.mode ?? "call") === "call") {
|
|
134
|
+
const launched = await launchSubagentGeneration(launchSnapshot.akuma.name, prompt, executionCwd, executionOptions);
|
|
135
|
+
const adoptedProjection = {
|
|
136
|
+
id: launched.projection.id,
|
|
137
|
+
phase: observeProjectionLife(launched.projection.dir, {
|
|
138
|
+
nowMs: Date.now(),
|
|
139
|
+
startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS,
|
|
140
|
+
}).phase,
|
|
141
|
+
...(launched.projection.alias ? { alias: launched.projection.alias } : {}),
|
|
142
|
+
...(launched.projection.previousAliasTarget ? { previousAliasTarget: launched.projection.previousAliasTarget } : {}),
|
|
143
|
+
};
|
|
144
|
+
input.onLaunch?.({ address: keiyakuContext.address, projection: adoptedProjection });
|
|
145
|
+
if (input.detach) {
|
|
146
|
+
return {
|
|
147
|
+
state: "launched",
|
|
148
|
+
summary: "",
|
|
149
|
+
agent: launchSnapshot.akuma.name,
|
|
150
|
+
launchSnapshot,
|
|
151
|
+
projectionOwnsResponsePersistence: true,
|
|
152
|
+
projection: adoptedProjection,
|
|
153
|
+
address: keiyakuContext.address,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const joined = await waitForProjection({
|
|
157
|
+
projectionDirectory: launched.projection.dir,
|
|
158
|
+
signal,
|
|
159
|
+
});
|
|
160
|
+
if (joined.state !== "terminal") {
|
|
161
|
+
throw new FlowError("INTERNAL_STATE", "foreground call wait ended without a terminal projection verdict");
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
state: "completed",
|
|
165
|
+
summary: joined.outcomeText || `${ACTOR_IDENTITY} completed successfully.`,
|
|
166
|
+
agent: launchSnapshot.akuma.name,
|
|
167
|
+
launchSnapshot,
|
|
168
|
+
...(joined.snapshot.responsePath ? { responsePath: joined.snapshot.responsePath } : {}),
|
|
169
|
+
...(joined.snapshot.artifactId ? { artifactId: joined.snapshot.artifactId } : {}),
|
|
170
|
+
projectionOwnsResponsePersistence: true,
|
|
171
|
+
meta: { effectivePolicy: launchSnapshot.akuma.policy },
|
|
172
|
+
projection: { id: launched.projection.id, phase: joined.snapshot.phase },
|
|
173
|
+
foregroundWait: joined,
|
|
174
|
+
address: keiyakuContext.address,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const execution = await executeSubagent(launchSnapshot.akuma.name, prompt, executionCwd, executionOptions);
|
|
178
|
+
const subagentOutcome = execution.outcome;
|
|
179
|
+
if (subagentOutcome.diagnostics.trim()) {
|
|
180
|
+
appendDebugBlock("subagent diagnostics", subagentOutcome.diagnostics, { cwd: executionCwd, section: "subagent-stderr" });
|
|
181
|
+
}
|
|
182
|
+
let projection;
|
|
183
|
+
let responsePath;
|
|
184
|
+
let artifactId;
|
|
185
|
+
if (execution.projection) {
|
|
186
|
+
responsePath = typeof execution.completionFacts?.responsePath === "string"
|
|
187
|
+
? execution.completionFacts.responsePath
|
|
188
|
+
: undefined;
|
|
189
|
+
artifactId = typeof execution.completionFacts?.artifactId === "string"
|
|
190
|
+
? execution.completionFacts.artifactId
|
|
191
|
+
: undefined;
|
|
192
|
+
try {
|
|
193
|
+
projection = {
|
|
194
|
+
id: execution.projection.id,
|
|
195
|
+
phase: observeProjectionLife(execution.projection.dir, {
|
|
196
|
+
nowMs: Date.now(),
|
|
197
|
+
startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS,
|
|
198
|
+
}).phase,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// Projection observations are best-effort and must not reverse success.
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
state: "completed",
|
|
207
|
+
summary: subagentOutcome.finalMessage || `${ACTOR_IDENTITY} completed successfully.`,
|
|
208
|
+
agent: launchSnapshot.akuma.name,
|
|
209
|
+
session: subagentOutcome.session,
|
|
210
|
+
launchSnapshot: subagentOutcome.launchSnapshot,
|
|
211
|
+
...(responsePath ? { responsePath } : {}),
|
|
212
|
+
...(artifactId ? { artifactId } : {}),
|
|
213
|
+
...(reviveArtifact ? { revivedArtifactId: reviveArtifact.artifactId } : {}),
|
|
214
|
+
projectionOwnsResponsePersistence: execution.projection !== undefined,
|
|
215
|
+
meta: {
|
|
216
|
+
...(subagentOutcome.warnings.length > 0 ? { warnings: subagentOutcome.warnings.map(renderSubagentWarning) } : {}),
|
|
217
|
+
effectivePolicy: subagentOutcome.launchSnapshot.akuma.policy,
|
|
218
|
+
},
|
|
219
|
+
...(projection ? { projection } : {}),
|
|
220
|
+
address: keiyakuContext.address,
|
|
221
|
+
...(input.incognito ? {} : { evidenceCwd }),
|
|
222
|
+
};
|
|
223
|
+
});
|
|
224
|
+
}
|