@astrosheep/keiyaku 2.9.2 → 2.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +13 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +25 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +47 -4
- package/build/agents/harness/projection.js +42 -59
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +50 -53
- package/build/agents/providers/codex-app-server/events.js +67 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +8 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/arc/handler.js +7 -1
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +34 -7
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/petition/handler.js +4 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +5 -4
- package/build/cli/commands/metadata.js +58 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +7 -2
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/task/add/handler.js +5 -13
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/ls/handler.js +3 -5
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/update/handler.js +4 -8
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +19 -3
- package/build/cli/help.js +4 -11
- package/build/cli/index.js +57 -83
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/parse-flags.js +14 -5
- package/build/cli/parse-metadata.js +3 -3
- package/build/cli/parse-selectors.js +1 -1
- package/build/cli/parse.js +21 -0
- package/build/cli/projection-address.js +7 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +55 -12
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +3 -0
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +37 -14
- package/build/cli/render/success-response.js +77 -0
- package/build/cli/render/task.js +54 -14
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +58 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +38 -36
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +1 -1
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +135 -18
- package/build/core/arc.js +19 -67
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +21 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +20 -3
- package/build/core/draft.js +123 -16
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +2 -38
- package/build/core/projection/generation/model.js +42 -1
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +19 -49
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +5 -3
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +18 -3
- package/build/core/projection/generation/store.js +2 -2
- package/build/core/projection/generation/transitions.js +1 -1
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +14 -19
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +2 -57
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +1 -1
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +98 -25
- package/build/core/projection/projection-terminal-failure.js +104 -0
- package/build/core/projection/projection-wait.js +278 -0
- package/build/core/projection/projection-wake.js +203 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +426 -99
- package/build/core/scope.js +143 -66
- package/build/core/seal.js +139 -35
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +9 -14
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +22 -18
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +1 -1
- package/build/core/{petition.js → settlement/petition.js} +12 -10
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +295 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/status/board.js +24 -23
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +3 -0
- package/build/core/task/board.js +40 -4
- package/build/core/task/commands.js +30 -21
- package/build/core/task/index.js +12 -0
- package/build/core/task/settlement-git.js +157 -65
- package/build/core/task/settlement-policy.js +54 -24
- package/build/core/task/task-contract.js +370 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +92 -29
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +5 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +5 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +85 -39
- package/build/fs/durability.js +27 -0
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +3 -3
- package/build/keiyaku.js +2 -36
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +3 -2
- package/skills/keiyaku-akuma/SKILL.md +10 -6
- package/skills/keiyaku-task/SKILL.md +1 -1
- package/skills/keiyaku-workflow/SKILL.md +25 -4
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
package/build/core/arc.js
CHANGED
|
@@ -2,63 +2,18 @@ import * as fs from "node:fs/promises";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { requireText, FlowError } from "../flow-error.js";
|
|
4
4
|
import { getCurrentBranch, requireGitRepository } from "../git/branches.js";
|
|
5
|
-
import {
|
|
5
|
+
import { assertCleanTrackedWorkingTree } from "../git/worktree.js";
|
|
6
6
|
import { KEIYAKU_FILE, ACTOR_IDENTITY } from "../keiyaku.js";
|
|
7
|
-
import { buildDirtyWorktreeArtifactHint } from "./hints.js";
|
|
8
7
|
import { normalizeInlineTitle } from "./markdown/titles.js";
|
|
9
|
-
import { parseCommandMarkdown, requireMarkdownTextSection, requireMarkdownTitle, } from "./command-
|
|
8
|
+
import { parseCommandMarkdown, requireMarkdownTextSection, requireMarkdownTitle, } from "./command-markdown.js";
|
|
10
9
|
import { resolveContractAddress, withResolvedAddress } from "./addressing.js";
|
|
11
10
|
import { activeLedgerRef, appendWithRetry, readLedger } from "./ledger.js";
|
|
12
|
-
import {
|
|
11
|
+
import { refreshContractView } from "./contract-view.js";
|
|
13
12
|
import { findOpenArc, getMaxArc, sealCurrentArc } from "./seal.js";
|
|
14
13
|
import { deriveContractState, isTerminalState } from "./status/lifecycle.js";
|
|
15
14
|
import { resolveDefaultBranch } from "./status/drift.js";
|
|
16
15
|
import { persistResponseHistory } from "./transcripts.js";
|
|
17
|
-
|
|
18
|
-
const KEIYAKU_ARTIFACT_DIR_PREFIX = ".keiyaku/";
|
|
19
|
-
function normalizePathForDirtyMatch(cwd, filePath) {
|
|
20
|
-
const normalizedPath = filePath.trim();
|
|
21
|
-
if (!normalizedPath)
|
|
22
|
-
return "";
|
|
23
|
-
const repoRelativePath = path.isAbsolute(normalizedPath) ? path.relative(cwd, normalizedPath) : normalizedPath;
|
|
24
|
-
const platformNormalizedPath = path.normalize(repoRelativePath.replace(/[\\/]+/g, path.sep));
|
|
25
|
-
return platformNormalizedPath.split(path.sep).join("/").replace(/^\.\/+/, "").replace(/^\/+/, "");
|
|
26
|
-
}
|
|
27
|
-
function pathSegments(normalizedPath) {
|
|
28
|
-
return normalizedPath.split("/").filter((segment) => segment.length > 0 && segment !== ".");
|
|
29
|
-
}
|
|
30
|
-
function matchesIgnorePattern(filePath, ignorePattern) {
|
|
31
|
-
const patternSegments = pathSegments(ignorePattern);
|
|
32
|
-
const fileSegments = pathSegments(filePath);
|
|
33
|
-
return patternSegments.length > 0
|
|
34
|
-
&& fileSegments.length >= patternSegments.length
|
|
35
|
-
&& patternSegments.every((segment, index) => fileSegments[index] === segment);
|
|
36
|
-
}
|
|
37
|
-
export function filterDirtyFilesByAllowlist(cwd, dirtyFiles, ignorePatterns) {
|
|
38
|
-
const ignoredPaths = Array.from(new Set((ignorePatterns ?? []).map((pattern) => normalizePathForDirtyMatch(cwd, pattern)).filter(Boolean)));
|
|
39
|
-
return {
|
|
40
|
-
dirtyFiles: dirtyFiles.filter((file) => {
|
|
41
|
-
const normalizedFilePath = normalizePathForDirtyMatch(cwd, file.path);
|
|
42
|
-
return !ignoredPaths.some((ignoredPath) => matchesIgnorePattern(normalizedFilePath, ignoredPath));
|
|
43
|
-
}),
|
|
44
|
-
ignoredPaths,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
export function filterBlockingDirtyFiles(dirtyFiles) {
|
|
48
|
-
return dirtyFiles.filter((file) => file.category !== DIRTY_FILE_CATEGORY.untracked);
|
|
49
|
-
}
|
|
50
|
-
export async function assertCleanWorkingTree(cwd, ignorePatterns) {
|
|
51
|
-
const blockingDirtyFiles = filterBlockingDirtyFiles(await getDirtyFiles(cwd));
|
|
52
|
-
const { dirtyFiles } = filterDirtyFilesByAllowlist(cwd, blockingDirtyFiles, ignorePatterns);
|
|
53
|
-
if (dirtyFiles.length === 0)
|
|
54
|
-
return;
|
|
55
|
-
const hasDirtyKeiyakuArtifacts = dirtyFiles.some((file) => normalizePathForDirtyMatch(cwd, file.path).startsWith(KEIYAKU_ARTIFACT_DIR_PREFIX));
|
|
56
|
-
const shown = dirtyFiles.slice(0, DIRTY_WORKTREE_LIST_LIMIT);
|
|
57
|
-
const list = shown.map((file) => ` ${renderDirtyFileStatusLine(file)}`).join("\n");
|
|
58
|
-
const overflowCount = dirtyFiles.length - shown.length;
|
|
59
|
-
const overflowLine = overflowCount > 0 ? `\n ... (+${overflowCount} more)` : "";
|
|
60
|
-
throw new FlowError("DIRTY_WORKTREE", `Uncommitted changes detected in working tree:\n${list}${overflowLine}\n\nBlocking changes must be committed or stashed before proceeding.`, hasDirtyKeiyakuArtifacts ? { hints: [buildDirtyWorktreeArtifactHint()] } : undefined);
|
|
61
|
-
}
|
|
16
|
+
import { resolveContractDeliveryCwd } from "./worktree-path.js";
|
|
62
17
|
export function buildArcViews(entries) {
|
|
63
18
|
const arcs = new Map();
|
|
64
19
|
for (const entry of entries) {
|
|
@@ -96,25 +51,20 @@ function assertArcOpenable(contractId, entries) {
|
|
|
96
51
|
throw new FlowError("INTERNAL_STATE", `contract ${contractId} cannot open arc from state ${state.state}`);
|
|
97
52
|
}
|
|
98
53
|
}
|
|
99
|
-
async function renderUpdatedContract(cwd, contractId) {
|
|
100
|
-
const ledger = await readLedger(cwd, contractId);
|
|
101
|
-
if (!ledger) {
|
|
102
|
-
throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger disappeared before render`);
|
|
103
|
-
}
|
|
104
|
-
await fs.writeFile(path.join(cwd, KEIYAKU_FILE), renderContractView({ id: contractId, entries: ledger.entries }), "utf8");
|
|
105
|
-
}
|
|
106
54
|
export async function openArc(input) {
|
|
107
55
|
const title = requireText("title", input.title);
|
|
108
56
|
const objective = requireText("objective", input.objective);
|
|
109
57
|
const brief = requireText("brief", input.brief);
|
|
58
|
+
const renderCwd = input.renderCwd ?? input.cwd;
|
|
110
59
|
const ledger = await readLedger(input.cwd, input.contractId);
|
|
111
60
|
if (!ledger) {
|
|
112
61
|
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} not found or not active`);
|
|
113
62
|
}
|
|
114
63
|
assertArcOpenable(input.contractId, ledger.entries);
|
|
64
|
+
// Seal capture needs delivery HEAD; ledger append may use hub or delivery (shared refs).
|
|
115
65
|
const sealed = await sealCurrentArc({
|
|
116
|
-
cwd:
|
|
117
|
-
renderCwd
|
|
66
|
+
cwd: renderCwd,
|
|
67
|
+
renderCwd,
|
|
118
68
|
contractId: input.contractId,
|
|
119
69
|
sealedBy: "arc",
|
|
120
70
|
nowMs: input.nowMs,
|
|
@@ -140,7 +90,7 @@ export async function openArc(input) {
|
|
|
140
90
|
if (!result.ok || arcNumber === 0) {
|
|
141
91
|
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} active ledger disappeared during arc`);
|
|
142
92
|
}
|
|
143
|
-
await
|
|
93
|
+
await refreshContractView({ ledgerCwd: input.cwd, renderCwd, contractId: input.contractId });
|
|
144
94
|
return { contractId: input.contractId, arc: arcNumber, ledgerHead: result.head, sealed };
|
|
145
95
|
}
|
|
146
96
|
export function buildArcInput(content, cwd, waivePaths = [], contractId, contractAddressSource) {
|
|
@@ -162,11 +112,13 @@ async function readBranchLabels(cwd) {
|
|
|
162
112
|
}
|
|
163
113
|
export async function arcKeiyaku(input) {
|
|
164
114
|
await requireGitRepository(input.cwd, "arc");
|
|
165
|
-
const address = await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
115
|
+
const address = input.address ?? await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
166
116
|
return await withResolvedAddress(address, async () => {
|
|
167
|
-
|
|
117
|
+
const contractId = address.binding.commissionId;
|
|
118
|
+
const renderCwd = await resolveContractDeliveryCwd(input.cwd, contractId);
|
|
119
|
+
await assertCleanTrackedWorkingTree(renderCwd);
|
|
168
120
|
try {
|
|
169
|
-
await fs.access(path.join(
|
|
121
|
+
await fs.access(path.join(renderCwd, KEIYAKU_FILE));
|
|
170
122
|
}
|
|
171
123
|
catch {
|
|
172
124
|
throw new FlowError("MISSING_PROTOCOL_FILES", `missing protocol file for current keiyaku (${KEIYAKU_FILE})`);
|
|
@@ -174,9 +126,9 @@ export async function arcKeiyaku(input) {
|
|
|
174
126
|
const title = normalizeInlineTitle(requireText("title", input.title));
|
|
175
127
|
const objective = requireText("objective", input.objective);
|
|
176
128
|
const brief = requireText("brief", input.brief);
|
|
177
|
-
const contractId = address.binding.commissionId;
|
|
178
129
|
const opened = await openArc({
|
|
179
130
|
cwd: input.cwd,
|
|
131
|
+
renderCwd,
|
|
180
132
|
contractId,
|
|
181
133
|
actor: ACTOR_IDENTITY,
|
|
182
134
|
nowMs: Date.now(),
|
|
@@ -185,11 +137,10 @@ export async function arcKeiyaku(input) {
|
|
|
185
137
|
brief,
|
|
186
138
|
waivePaths: input.waivePaths,
|
|
187
139
|
});
|
|
188
|
-
const { currentBranch, baseBranch } = await readBranchLabels(
|
|
140
|
+
const { currentBranch, baseBranch } = await readBranchLabels(renderCwd);
|
|
189
141
|
const summary = opened.sealed
|
|
190
142
|
? `a${opened.sealed.arc} sealed; a${opened.arc} open: ${title}.`
|
|
191
143
|
: `a${opened.arc} open: ${title}.`;
|
|
192
|
-
const diff = opened.sealed?.incrementalDiff ?? "working tree untouched";
|
|
193
144
|
let responsePath;
|
|
194
145
|
let artifactId;
|
|
195
146
|
try {
|
|
@@ -202,7 +153,7 @@ export async function arcKeiyaku(input) {
|
|
|
202
153
|
brief,
|
|
203
154
|
ledgerCommit: opened.ledgerHead,
|
|
204
155
|
summary,
|
|
205
|
-
|
|
156
|
+
emptyDiffLabel: "working tree untouched",
|
|
206
157
|
...(opened.sealed ? { sealed: opened.sealed } : {}),
|
|
207
158
|
});
|
|
208
159
|
responsePath = persisted.responsePath;
|
|
@@ -217,7 +168,8 @@ export async function arcKeiyaku(input) {
|
|
|
217
168
|
currentBranch,
|
|
218
169
|
baseBranch,
|
|
219
170
|
commit: opened.ledgerHead,
|
|
220
|
-
|
|
171
|
+
// CLI/render synthesizes public face bytes from sealed typed facts.
|
|
172
|
+
diff: "",
|
|
221
173
|
summary,
|
|
222
174
|
title,
|
|
223
175
|
objective,
|
package/build/core/bind.js
CHANGED
|
@@ -3,12 +3,12 @@ import { assertSettingsKnobUsable } from "../config/settings/disease.js";
|
|
|
3
3
|
import { loadKeiyakuSettings } from "../config/settings/loader.js";
|
|
4
4
|
import { FlowError } from "../flow-error.js";
|
|
5
5
|
import { activeLedgerRef, appendEntry, appendWithRetry, readLedger } from "./ledger.js";
|
|
6
|
-
import { parseBindDraft } from "./draft.js";
|
|
6
|
+
import { describeMissingBindSections, materializeBindDraft, mergeBindDraft, missingBindDraftSections, parseBindDraft, parsePartialBindDraft, renderMissingBindSectionsTemplate, } from "./draft.js";
|
|
7
7
|
import { assertValidContractId, buildContractId } from "./ids.js";
|
|
8
8
|
import { registerScope, releaseScope } from "./registry.js";
|
|
9
9
|
import { resolveDefaultBranch } from "./status/drift.js";
|
|
10
10
|
import { normalizeTargetRef } from "./target-ref.js";
|
|
11
|
-
import { reconcileTaskForfeit, settleTaskBoardForBind } from "./task
|
|
11
|
+
import { reconcileTaskForfeit, settleTaskBoardForBind } from "./task/index.js";
|
|
12
12
|
import { bootstrapEntryDataFromObservation, isBootstrapSuccess, runWorktreeBootstrap, } from "./worktree-bootstrap.js";
|
|
13
13
|
import { contractWorktreePathFromBind, stableRepoRoot } from "./worktree-path.js";
|
|
14
14
|
import { allocateWorktreePlace, cleanupCreatedBindResources, createContractBranch, defaultCreateWorktree, materializeContractView, resolveTreeRoot, } from "./bind-workspace.js";
|
|
@@ -107,8 +107,40 @@ function makeBindEntry(input) {
|
|
|
107
107
|
},
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
|
+
function taskBindDefaults(task) {
|
|
111
|
+
const defaults = { name: task.title };
|
|
112
|
+
const objective = task.body.trim();
|
|
113
|
+
if (objective.length > 0)
|
|
114
|
+
defaults.objective = objective;
|
|
115
|
+
return defaults;
|
|
116
|
+
}
|
|
117
|
+
function incompleteTaskBindError(taskId, missing) {
|
|
118
|
+
const coordinate = taskId;
|
|
119
|
+
const template = renderMissingBindSectionsTemplate(missing);
|
|
120
|
+
const message = [
|
|
121
|
+
`task ${coordinate} carries no ${describeMissingBindSections(missing)}`,
|
|
122
|
+
`» keiyaku bind --task ${coordinate} <<'KEIYAKU'`,
|
|
123
|
+
template,
|
|
124
|
+
"KEIYAKU",
|
|
125
|
+
].join("\n");
|
|
126
|
+
return new FlowError("BIND_TASK_INCOMPLETE", message);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Section-level merge for `bind --task`: task title/body are name/objective
|
|
130
|
+
* defaults; stdin partial markdown sections override. Missing required sections
|
|
131
|
+
* fail with a paste-ready partial heredoc template.
|
|
132
|
+
*/
|
|
133
|
+
export function composeTaskBindDraft(input) {
|
|
134
|
+
const merged = mergeBindDraft(taskBindDefaults(input.task), parsePartialBindDraft(input.draft));
|
|
135
|
+
const missing = missingBindDraftSections(merged);
|
|
136
|
+
if (missing.length > 0) {
|
|
137
|
+
throw incompleteTaskBindError(input.task.id, missing);
|
|
138
|
+
}
|
|
139
|
+
return materializeBindDraft(merged);
|
|
140
|
+
}
|
|
110
141
|
export async function bindContract(input) {
|
|
111
|
-
const
|
|
142
|
+
const isTaskBound = input.taskIds !== undefined && input.taskIds.length > 0;
|
|
143
|
+
const ordinaryDraft = !isTaskBound ? parseBindDraft(input.draft) : undefined;
|
|
112
144
|
const workspace = input.workspace ?? "here";
|
|
113
145
|
const at = new Date(input.nowMs).toISOString();
|
|
114
146
|
const defaultBranch = await resolveDefaultBranch(input.cwd);
|
|
@@ -126,47 +158,60 @@ export async function bindContract(input) {
|
|
|
126
158
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
127
159
|
const randomBytes = input.randomBytes?.(attempt) ?? randomBytesDefault();
|
|
128
160
|
const place = workspace === "worktree" ? await allocateWorktreePlace(input.cwd, randomBytes) : undefined;
|
|
129
|
-
const id = buildContractId({
|
|
130
|
-
name: draft.name,
|
|
131
|
-
nowMs: input.nowMs,
|
|
132
|
-
randomBytes,
|
|
133
|
-
});
|
|
134
|
-
await assertValidContractId(input.cwd, id);
|
|
135
|
-
const ref = activeLedgerRef(id);
|
|
136
161
|
let settlement;
|
|
137
162
|
try {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
163
|
+
const prepare = async (draft) => {
|
|
164
|
+
const id = buildContractId({ name: draft.name, nowMs: input.nowMs, randomBytes });
|
|
165
|
+
await assertValidContractId(input.cwd, id);
|
|
166
|
+
const ref = activeLedgerRef(id);
|
|
167
|
+
return {
|
|
168
|
+
contractId: id,
|
|
169
|
+
publishLedger: async (base) => {
|
|
170
|
+
const entry = makeBindEntry({
|
|
171
|
+
id,
|
|
172
|
+
at,
|
|
173
|
+
actor: input.actor,
|
|
174
|
+
draft,
|
|
175
|
+
base,
|
|
176
|
+
target,
|
|
177
|
+
after: input.after ?? [],
|
|
178
|
+
workspace,
|
|
179
|
+
place,
|
|
180
|
+
bootstrap: bootstrapPlan,
|
|
181
|
+
});
|
|
182
|
+
const appended = await appendEntry(input.cwd, ref, entry, null);
|
|
183
|
+
if (!appended.ok)
|
|
184
|
+
throw new BindLedgerCollisionError(id);
|
|
185
|
+
return { entry, appended };
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
settlement = !isTaskBound
|
|
190
|
+
? await (async () => {
|
|
191
|
+
const prepared = await prepare(ordinaryDraft);
|
|
192
|
+
return settleTaskBoardForBind({ cwd: input.cwd, signal: input.signal, ...prepared });
|
|
193
|
+
})()
|
|
194
|
+
: await (async () => {
|
|
195
|
+
return settleTaskBoardForBind({
|
|
196
|
+
cwd: input.cwd,
|
|
197
|
+
taskIds: input.taskIds,
|
|
198
|
+
signal: input.signal,
|
|
199
|
+
prepare: async (tasks) => prepare(composeTaskBindDraft({ task: tasks[0], draft: input.draft })),
|
|
154
200
|
});
|
|
155
|
-
|
|
156
|
-
if (!appended.ok)
|
|
157
|
-
throw new BindLedgerCollisionError(id);
|
|
158
|
-
return { entry, appended };
|
|
159
|
-
},
|
|
160
|
-
});
|
|
201
|
+
})();
|
|
161
202
|
}
|
|
162
203
|
catch (error) {
|
|
163
204
|
if (error instanceof BindLedgerCollisionError) {
|
|
164
|
-
|
|
205
|
+
// The selected task's locked snapshot chose this attempted identity.
|
|
206
|
+
// Record the concrete id only when preparation reached publication.
|
|
207
|
+
collidedIds.push(error.contractId);
|
|
165
208
|
continue;
|
|
166
209
|
}
|
|
167
210
|
throw error;
|
|
168
211
|
}
|
|
169
212
|
const { entry, appended } = settlement.ledger;
|
|
213
|
+
const id = settlement.contractId;
|
|
214
|
+
const ref = activeLedgerRef(id);
|
|
170
215
|
const base = settlement.boardCommit;
|
|
171
216
|
const resources = { id };
|
|
172
217
|
const branch = `keiyaku/${id}`;
|
|
@@ -179,7 +224,7 @@ export async function bindContract(input) {
|
|
|
179
224
|
const tree = await resolveTreeRoot(input.cwd, workspace, id, entry);
|
|
180
225
|
const registration = await registerScope(input.cwd, {
|
|
181
226
|
contractId: id,
|
|
182
|
-
scope:
|
|
227
|
+
scope: entry.data.scope,
|
|
183
228
|
tree,
|
|
184
229
|
actor: input.actor,
|
|
185
230
|
at,
|
|
@@ -219,11 +264,13 @@ export async function bindContract(input) {
|
|
|
219
264
|
return {
|
|
220
265
|
id,
|
|
221
266
|
ref,
|
|
267
|
+
target,
|
|
268
|
+
place: workspace === "worktree" ? entry.data.place ?? null : null,
|
|
222
269
|
branch: workspace === "worktree" ? branch : undefined,
|
|
223
270
|
worktreePath: targetRoot,
|
|
224
271
|
workspace,
|
|
225
272
|
ledgerHead,
|
|
226
|
-
|
|
273
|
+
scopeOverlaps: registration.overlaps,
|
|
227
274
|
};
|
|
228
275
|
}
|
|
229
276
|
catch (error) {
|
package/build/core/call/call.js
CHANGED
|
@@ -8,10 +8,8 @@ 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 } from "../projection
|
|
12
|
-
import {
|
|
13
|
-
import { observeProjectionLife } from "../projection-life-observer.js";
|
|
14
|
-
import { waitForProjection } from "../projection-wait.js";
|
|
11
|
+
import { assertProjectionAlias, PROJECTION_ADOPTION_TIMEOUT_MS, observeProjectionLife, waitForProjection, } from "../projection/index.js";
|
|
12
|
+
import { normalizeFilesystemCoordinate } from "../../fs/path-coordinate.js";
|
|
15
13
|
import { requireResumableArtifact } from "../transcripts.js";
|
|
16
14
|
import { stableRepoRoot } from "../worktree-path.js";
|
|
17
15
|
import { readCallKeiyakuContext } from "./context.js";
|
|
@@ -23,6 +21,9 @@ function renderSubagentWarning(warning) {
|
|
|
23
21
|
const status = warning.errorStatus === null ? "no response" : String(warning.errorStatus);
|
|
24
22
|
return `Provider warning: retry. attempt=${warning.attempt}, maxRetries=${warning.maxRetries}, retryDelayMs=${warning.retryDelayMs}, errorStatus=${status}`;
|
|
25
23
|
}
|
|
24
|
+
if (warning.reason === "rate-limit") {
|
|
25
|
+
return "Provider warning: rate limit exhausted.";
|
|
26
|
+
}
|
|
26
27
|
const modelTransition = warning.originalModel && warning.fallbackModel
|
|
27
28
|
? `${warning.originalModel} -> ${warning.fallbackModel}`
|
|
28
29
|
: warning.originalModel ?? warning.fallbackModel;
|
|
@@ -42,18 +43,18 @@ export async function execSubagent(agentName, prompt, cwd, options) {
|
|
|
42
43
|
export async function runCall(input) {
|
|
43
44
|
const { signal, agent } = input;
|
|
44
45
|
const reviveArtifact = input.reviveArtifact ? requireResumableArtifact(input.reviveArtifact) : undefined;
|
|
45
|
-
let rawCwd = input.cwd;
|
|
46
|
-
let rawRepo = input.repo;
|
|
46
|
+
let rawCwd = normalizeFilesystemCoordinate(input.cwd);
|
|
47
|
+
let rawRepo = input.repo === undefined ? undefined : normalizeFilesystemCoordinate(input.repo);
|
|
47
48
|
if (reviveArtifact?.provenance.authority.kind === "user") {
|
|
48
49
|
if (!("workdir" in reviveArtifact.provenance.evidence)) {
|
|
49
50
|
throw new FlowError("INVALID_RESPONSE_PATH", `Invalid response artifact '${reviveArtifact.artifactId}': field 'provenance.evidence.workdir' is missing.`);
|
|
50
51
|
}
|
|
51
|
-
rawCwd = reviveArtifact.provenance.evidence.workdir;
|
|
52
|
+
rawCwd = normalizeFilesystemCoordinate(reviveArtifact.provenance.evidence.workdir);
|
|
52
53
|
rawRepo = undefined;
|
|
53
54
|
}
|
|
54
55
|
else if (reviveArtifact?.provenance.authority.kind === "repository") {
|
|
55
56
|
const artifactHome = await fs.realpath(reviveArtifact.storageRoot);
|
|
56
|
-
const addressed = input.repo ?? input.cwd;
|
|
57
|
+
const addressed = normalizeFilesystemCoordinate(input.repo ?? input.cwd);
|
|
57
58
|
const observation = await observeGitRepository(addressed);
|
|
58
59
|
const coordinate = assertGitObservation(observation, "revive");
|
|
59
60
|
if (coordinate === "repository") {
|
|
@@ -91,6 +92,7 @@ export async function runCall(input) {
|
|
|
91
92
|
context: input.context,
|
|
92
93
|
referenceFiles,
|
|
93
94
|
currentIntent: keiyakuContext.currentIntent,
|
|
95
|
+
commissioned: keiyakuContext.address.binding.kind === "commission",
|
|
94
96
|
});
|
|
95
97
|
const launchSnapshot = reviveArtifact
|
|
96
98
|
? input.effort !== undefined
|
|
@@ -146,7 +148,11 @@ export async function runCall(input) {
|
|
|
146
148
|
...(launched.projection.alias ? { alias: launched.projection.alias } : {}),
|
|
147
149
|
...(launched.projection.previousAliasTarget ? { previousAliasTarget: launched.projection.previousAliasTarget } : {}),
|
|
148
150
|
};
|
|
149
|
-
input.onLaunch?.({
|
|
151
|
+
input.onLaunch?.({
|
|
152
|
+
address: keiyakuContext.address,
|
|
153
|
+
projection: adoptedProjection,
|
|
154
|
+
akumaName: launchSnapshot.akuma.name,
|
|
155
|
+
});
|
|
150
156
|
if (input.detach) {
|
|
151
157
|
return {
|
|
152
158
|
state: "launched",
|
|
@@ -3,10 +3,11 @@ import { FlowError } from "../../flow-error.js";
|
|
|
3
3
|
import { assertGitObservation, observeGitRepository } from "../../git/branches.js";
|
|
4
4
|
import { createGit, wrapGitError } from "../../git/core.js";
|
|
5
5
|
import { AddressResolutionError, buildResolutionAttempt, buildUncommissionedAddress, buildUncommissionedRepositoryAddress, resolveContractAddress, withResolvedAddress, } from "../addressing.js";
|
|
6
|
+
import { normalizeFilesystemCoordinate } from "../../fs/path-coordinate.js";
|
|
6
7
|
import { findOpenArcView } from "../arc.js";
|
|
7
8
|
import { readLedger } from "../ledger.js";
|
|
8
9
|
import { deriveContractState, isTerminalState } from "../status/lifecycle.js";
|
|
9
|
-
import {
|
|
10
|
+
import { contractWorktreePathFromBind, stableRepoRoot } from "../worktree-path.js";
|
|
10
11
|
async function findWorktreePathForContract(cwd, contractId) {
|
|
11
12
|
const git = createGit(cwd);
|
|
12
13
|
let output;
|
|
@@ -47,6 +48,8 @@ async function resolveWorkspaceCwd(cwd, contractId, bind) {
|
|
|
47
48
|
return worktreePath;
|
|
48
49
|
}
|
|
49
50
|
export async function readCallKeiyakuContext(executionCwd, input) {
|
|
51
|
+
executionCwd = normalizeFilesystemCoordinate(executionCwd);
|
|
52
|
+
input.repoCwd = input.repoCwd === undefined ? undefined : normalizeFilesystemCoordinate(input.repoCwd);
|
|
50
53
|
const ledgerCandidate = input.repoCwd ?? executionCwd;
|
|
51
54
|
const ledgerObservation = await observeGitRepository(ledgerCandidate);
|
|
52
55
|
if (ledgerObservation.capability === "unknown")
|
|
@@ -136,7 +139,7 @@ export async function readCallKeiyakuContext(executionCwd, input) {
|
|
|
136
139
|
},
|
|
137
140
|
}));
|
|
138
141
|
}
|
|
139
|
-
if (input.bare) {
|
|
142
|
+
if (input.bare || !input.contractId) {
|
|
140
143
|
return {
|
|
141
144
|
activeKeiyaku: false,
|
|
142
145
|
effectiveCwd: executionCwd,
|
|
@@ -150,55 +153,7 @@ export async function readCallKeiyakuContext(executionCwd, input) {
|
|
|
150
153
|
}),
|
|
151
154
|
};
|
|
152
155
|
}
|
|
153
|
-
|
|
154
|
-
if (input.contractId) {
|
|
155
|
-
address = await resolveContractAddress(ledgerCwd, input.contractId, input.contractAddressSource);
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
const executionObservation = await observeGitRepository(executionCwd);
|
|
159
|
-
if (executionObservation.capability === "unknown")
|
|
160
|
-
throw executionObservation.error;
|
|
161
|
-
if (executionObservation.capability === "available" && executionObservation.coordinate === "repository") {
|
|
162
|
-
const executionRepo = await stableRepoRoot(executionCwd);
|
|
163
|
-
if (input.repoCwd && executionRepo !== ledgerCwd) {
|
|
164
|
-
const presented = await contractPresentedByWorktree(executionCwd);
|
|
165
|
-
if (presented) {
|
|
166
|
-
throw new FlowError("EMPTY_PARAM", `cross-repository contract-worktree addressing is pending: -C presents @${presented} from ${executionRepo}, but --repo selects ${ledgerCwd}`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
const presented = await contractPresentedByWorktree(executionCwd);
|
|
171
|
-
if (presented) {
|
|
172
|
-
address = await resolveContractAddress(ledgerCwd, presented, "worktree-presented");
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (!address) {
|
|
178
|
-
try {
|
|
179
|
-
address = await resolveContractAddress(ledgerCwd);
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
if (error instanceof AddressResolutionError
|
|
183
|
-
&& error.code === "EMPTY_PARAM"
|
|
184
|
-
&& error.attempt.expected === "commission"
|
|
185
|
-
&& error.attempt.candidates.length === 0) {
|
|
186
|
-
return {
|
|
187
|
-
activeKeiyaku: false,
|
|
188
|
-
effectiveCwd: executionCwd,
|
|
189
|
-
historyCwd: ledgerCwd,
|
|
190
|
-
profileCwd: ledgerCwd,
|
|
191
|
-
projectionCwd: ledgerCwd,
|
|
192
|
-
address: buildUncommissionedRepositoryAddress({
|
|
193
|
-
stableRoot: ledgerCwd,
|
|
194
|
-
workdir: executionCwd,
|
|
195
|
-
binding: "unbound",
|
|
196
|
-
}),
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
throw error;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
156
|
+
const address = await resolveContractAddress(ledgerCwd, input.contractId, input.contractAddressSource);
|
|
202
157
|
return await withResolvedAddress(address, async () => {
|
|
203
158
|
const contractId = address.binding.commissionId;
|
|
204
159
|
const ledger = await readLedger(ledgerCwd, contractId);
|
|
@@ -3,14 +3,14 @@ import { createAbortError, restoreOutcome, SubagentFailure, } from "../../agents
|
|
|
3
3
|
import { resolveAkumaLaunchSnapshot } from "../../agents/launch-snapshot/resolve.js";
|
|
4
4
|
import { selectSubagent } from "../../agents/selector.js";
|
|
5
5
|
import { FlowError } from "../../flow-error.js";
|
|
6
|
-
import { assertProjectionAlias, moveProjectionAlias } from "../projection
|
|
7
|
-
import { projectionDir } from "../projection
|
|
8
|
-
import { createProjectionExecutionId } from "../projection
|
|
9
|
-
import { PROJECTION_ADOPTION_TIMEOUT_MS, startProjectionGeneration } from "../projection
|
|
10
|
-
import { openProjectionGenerationStore, openProjectionGenerationStoreReadOnly, } from "../projection/
|
|
11
|
-
import { observeProjectionLife } from "../projection
|
|
12
|
-
import { mintProjection, mintRepositoryProjection } from "../projection
|
|
13
|
-
import { waitForProjection } from "../projection
|
|
6
|
+
import { assertProjectionAlias, moveProjectionAlias } from "../projection/index.js";
|
|
7
|
+
import { projectionDir } from "../projection/index.js";
|
|
8
|
+
import { createProjectionExecutionId } from "../projection/index.js";
|
|
9
|
+
import { PROJECTION_ADOPTION_TIMEOUT_MS, startProjectionGeneration } from "../projection/index.js";
|
|
10
|
+
import { openProjectionGenerationStore, openProjectionGenerationStoreReadOnly, } from "../projection/index.js";
|
|
11
|
+
import { observeProjectionLife } from "../projection/index.js";
|
|
12
|
+
import { mintProjection, mintRepositoryProjection } from "../projection/index.js";
|
|
13
|
+
import { waitForProjection } from "../projection/index.js";
|
|
14
14
|
export function readCurrentGenerationOrThrow(projectionDirectory) {
|
|
15
15
|
const store = openProjectionGenerationStoreReadOnly(projectionDirectory);
|
|
16
16
|
try {
|
|
@@ -148,7 +148,7 @@ export async function buildCallConfig(agentName, prompt, cwd, options) {
|
|
|
148
148
|
};
|
|
149
149
|
const minted = options.authority.kind === "repository"
|
|
150
150
|
? await mintRepositoryProjection({ ...mintInput, authority: { kind: "repository" } })
|
|
151
|
-
: mintProjection({ ...mintInput, authority: { kind: "user" } });
|
|
151
|
+
: await mintProjection({ ...mintInput, authority: { kind: "user" } });
|
|
152
152
|
const executionId = createProjectionExecutionId();
|
|
153
153
|
const launchFacts = JSON.parse(JSON.stringify({
|
|
154
154
|
executionId,
|
|
@@ -184,20 +184,19 @@ export async function buildCallConfig(agentName, prompt, cwd, options) {
|
|
|
184
184
|
}
|
|
185
185
|
const previousAliasTarget = options.alias === undefined
|
|
186
186
|
? undefined
|
|
187
|
-
: moveProjectionAlias(options.projectionCwd ?? cwd, assertProjectionAlias(options.alias), minted.id);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
? previousAliasTarget
|
|
195
|
-
: undefined;
|
|
196
|
-
}
|
|
197
|
-
catch {
|
|
198
|
-
return undefined;
|
|
187
|
+
: await moveProjectionAlias(options.projectionCwd ?? cwd, assertProjectionAlias(options.alias), minted.id);
|
|
188
|
+
let previousAliasTargetStillRunning;
|
|
189
|
+
if (previousAliasTarget !== undefined) {
|
|
190
|
+
try {
|
|
191
|
+
const phase = observeProjectionLife(await projectionDir(options.projectionCwd ?? cwd, previousAliasTarget), { nowMs: Date.now(), startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS }).phase;
|
|
192
|
+
if (phase === "minting" || phase === "active" || phase === "quiescent") {
|
|
193
|
+
previousAliasTargetStillRunning = previousAliasTarget;
|
|
199
194
|
}
|
|
200
|
-
}
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
previousAliasTargetStillRunning = undefined;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
201
200
|
return {
|
|
202
201
|
id: minted.id,
|
|
203
202
|
dir: minted.dir,
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { ACTOR_IDENTITY } from "../../keiyaku.js";
|
|
2
|
+
const COMMISSIONED_DELIVERY_BOUNDARY = [
|
|
3
|
+
"Delivery boundary: edit and test only inside this linked contract worktree.",
|
|
4
|
+
"Leave source changes uncommitted as a dirty working tree, then report changed files and checks run.",
|
|
5
|
+
"Do not run git add, git commit, or any command that writes Git metadata. A refused Git metadata write is not a failed delivery.",
|
|
6
|
+
"The host coordinator reviews and commits accepted bytes, then continues arc, renew, or petition settlement.",
|
|
7
|
+
].join(" ");
|
|
2
8
|
export function buildCallPrompt(input) {
|
|
3
9
|
const references = [...new Set((input.referenceFiles ?? []).map((file) => file.trim()).filter(Boolean))];
|
|
4
10
|
if (input.currentIntent?.source === "arc") {
|
|
@@ -9,6 +15,7 @@ export function buildCallPrompt(input) {
|
|
|
9
15
|
`Title: ${arc.title}`,
|
|
10
16
|
`Objective: ${arc.objective}`,
|
|
11
17
|
`Brief:\n${arc.brief}`,
|
|
18
|
+
COMMISSIONED_DELIVERY_BOUNDARY,
|
|
12
19
|
"",
|
|
13
20
|
`Task:\n${input.task}`,
|
|
14
21
|
`Context:\n${input.context?.trim() || "(none provided)"}`,
|
|
@@ -30,13 +37,19 @@ export function buildCallPrompt(input) {
|
|
|
30
37
|
`Scope:\n${bind.scope.map((value) => `- ${value}`).join("\n")}`,
|
|
31
38
|
`Checks:\n${bind.checks.map((value) => `- ${value}`).join("\n")}`,
|
|
32
39
|
extensionsBlock,
|
|
40
|
+
COMMISSIONED_DELIVERY_BOUNDARY,
|
|
33
41
|
`Task:\n${input.task}`,
|
|
34
42
|
trimmedContext ? `Context:\n${trimmedContext}` : "",
|
|
35
43
|
references.length > 0 ? `Reference files:\n${references.map((file) => `- ${file}`).join("\n")}` : "",
|
|
36
44
|
"Provide the final result for the caller/main agent.",
|
|
37
45
|
].filter(Boolean).join("\n\n");
|
|
38
46
|
}
|
|
39
|
-
return [
|
|
47
|
+
return [
|
|
48
|
+
input.task,
|
|
49
|
+
input.context?.trim() ?? "",
|
|
50
|
+
input.commissioned ? COMMISSIONED_DELIVERY_BOUNDARY : "",
|
|
51
|
+
references.length > 0 ? `Reference files:\n${references.map((file) => `- ${file}`).join("\n")}` : "",
|
|
52
|
+
]
|
|
40
53
|
.filter(Boolean)
|
|
41
54
|
.join("\n\n");
|
|
42
55
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { FlowError } from "../flow-error.js";
|
|
2
|
+
import { parseMarkdownListSection, parseMarkdownStructure } from "./markdown/sections.js";
|
|
3
|
+
import { KeiyakuParseError } from "./markdown/types.js";
|
|
4
|
+
import { normalizeSectionTitle } from "./markdown/titles.js";
|
|
5
|
+
export function parseCommandMarkdown(content) {
|
|
6
|
+
try {
|
|
7
|
+
const parsed = parseMarkdownStructure(content);
|
|
8
|
+
const sections = new Map();
|
|
9
|
+
for (const [key, lines] of parsed.sections.entries()) {
|
|
10
|
+
sections.set(key, lines.join("\n").trim());
|
|
11
|
+
}
|
|
12
|
+
return { title: parsed.title, sections };
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error instanceof KeiyakuParseError) {
|
|
16
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", error.message, { cause: error });
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function requireMarkdownTextSection(parts, name) {
|
|
22
|
+
const normalized = normalizeSectionTitle(name);
|
|
23
|
+
const value = parts.sections.get(normalized)?.trim();
|
|
24
|
+
if (!value) {
|
|
25
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", `missing required section: ## ${name}`);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
export function requireMarkdownListSection(parts, name) {
|
|
30
|
+
const text = requireMarkdownTextSection(parts, name);
|
|
31
|
+
const items = parseMarkdownListSection(text)
|
|
32
|
+
.map((item) => item.trim())
|
|
33
|
+
.filter((item) => item.length > 0);
|
|
34
|
+
if (items.length === 0) {
|
|
35
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", `missing required section: ## ${name}`);
|
|
36
|
+
}
|
|
37
|
+
return items;
|
|
38
|
+
}
|
|
39
|
+
export function requireMarkdownTitle(parts) {
|
|
40
|
+
const title = parts.title?.trim();
|
|
41
|
+
if (!title) {
|
|
42
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", "missing required title: # Title");
|
|
43
|
+
}
|
|
44
|
+
return title;
|
|
45
|
+
}
|