@astrosheep/keiyaku 1.0.0 → 1.0.2

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.
Files changed (123) hide show
  1. package/README.md +73 -56
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms_v2.js +103 -0
  4. package/build/agents/harness/activity-values.js +54 -0
  5. package/build/agents/harness/event-channel.js +55 -20
  6. package/build/agents/harness/events.js +47 -1
  7. package/build/agents/harness/execution-handle.js +292 -61
  8. package/build/agents/harness/index.js +103 -121
  9. package/build/agents/harness/pump.js +36 -47
  10. package/build/agents/harness/runtime.js +3 -0
  11. package/build/agents/launch-snapshot_v2.js +348 -0
  12. package/build/agents/opencode-sdk.js +42 -169
  13. package/build/agents/providers/claude-agent-sdk.js +240 -79
  14. package/build/agents/providers/codex-app-server.js +280 -72
  15. package/build/agents/providers/codex-sdk.js +159 -41
  16. package/build/agents/providers/event-type-tail.js +16 -0
  17. package/build/agents/providers/opencode-sdk.js +165 -59
  18. package/build/agents/providers/pi.js +254 -42
  19. package/build/agents/selector_v2.js +122 -0
  20. package/build/cli/commands/akuma.js +120 -42
  21. package/build/cli/completion.js +6 -7
  22. package/build/cli/flags.js +36 -10
  23. package/build/cli/help.js +42 -26
  24. package/build/cli/index.js +225 -93
  25. package/build/cli/parse.js +194 -75
  26. package/build/cli/projection-address.js +11 -0
  27. package/build/cli/render/address.js +88 -0
  28. package/build/cli/render/arc.js +10 -10
  29. package/build/cli/render/call.js +59 -0
  30. package/build/cli/render/compact-text.js +3 -0
  31. package/build/cli/render/errors.js +4 -2
  32. package/build/cli/render/format.js +6 -0
  33. package/build/cli/render/line-width.js +70 -0
  34. package/build/cli/render/misc.js +7 -4
  35. package/build/cli/render/petition.js +4 -3
  36. package/build/cli/render/projection-activity.js +201 -0
  37. package/build/cli/render/shared.js +46 -12
  38. package/build/cli/render/status.js +59 -10
  39. package/build/cli/render/tool-ledger-rollup.js +74 -0
  40. package/build/cli/render/tool-presentation.js +97 -0
  41. package/build/cli/render/wait.js +229 -0
  42. package/build/cli/skills-install.js +42 -24
  43. package/build/cli/subagent-guard.js +1 -1
  44. package/build/config/akuma-loader_v2.js +222 -0
  45. package/build/config/env-keys.js +0 -4
  46. package/build/config/env.js +0 -6
  47. package/build/config/settings.js +325 -12
  48. package/build/core/addressing.js +224 -0
  49. package/build/core/amend.js +30 -47
  50. package/build/core/arc.js +68 -60
  51. package/build/core/bind.js +105 -25
  52. package/build/core/call-persist.js +69 -0
  53. package/build/core/call.js +658 -0
  54. package/build/core/claim.js +72 -44
  55. package/build/core/command-io.js +19 -19
  56. package/build/core/context.js +11 -36
  57. package/build/core/draft.js +2 -3
  58. package/build/core/entry.js +101 -6
  59. package/build/core/execution-coordinate.js +62 -0
  60. package/build/core/execution-pact.js +141 -0
  61. package/build/core/forfeit.js +2 -3
  62. package/build/core/hints.js +10 -10
  63. package/build/core/ids.js +6 -0
  64. package/build/core/ledger.js +16 -1
  65. package/build/core/petition-claim-gates.js +14 -12
  66. package/build/core/petition-claim.js +1 -0
  67. package/build/core/petition-run.js +6 -2
  68. package/build/core/petition.js +63 -21
  69. package/build/core/places.js +106 -13
  70. package/build/core/projection/generation.js +412 -0
  71. package/build/core/projection/heart.js +316 -0
  72. package/build/core/projection/identity.js +81 -0
  73. package/build/core/projection/leash.js +87 -0
  74. package/build/core/projection/mint.js +154 -0
  75. package/build/core/projection-activity.js +219 -0
  76. package/build/core/projection-coordinate.js +35 -0
  77. package/build/core/projection-core.js +69 -463
  78. package/build/core/projection-generation-continuation.js +31 -0
  79. package/build/core/projection-generation-execution.js +148 -0
  80. package/build/core/projection-generation-identity.js +17 -0
  81. package/build/core/projection-generation-launcher.js +90 -0
  82. package/build/core/projection-generation-process.js +43 -0
  83. package/build/core/projection-generation-runner.js +144 -0
  84. package/build/core/projection-generation-runtime.js +15 -0
  85. package/build/core/projection-generation-store.js +707 -0
  86. package/build/core/projection-identity.js +11 -0
  87. package/build/core/projection-life-observer.js +87 -0
  88. package/build/core/projection-life-protocol.js +95 -0
  89. package/build/core/projection-mint.js +96 -24
  90. package/build/core/projection-runner-lock.js +230 -0
  91. package/build/core/projection-status.js +207 -107
  92. package/build/core/projection-tells.js +401 -0
  93. package/build/core/projection-wait.js +155 -0
  94. package/build/core/projection-wake.js +109 -231
  95. package/build/core/queue_v2.js +342 -0
  96. package/build/core/registry.js +6 -3
  97. package/build/core/render.js +63 -1
  98. package/build/core/renew.js +80 -53
  99. package/build/core/scope.js +186 -137
  100. package/build/core/seal.js +16 -19
  101. package/build/core/status.js +88 -25
  102. package/build/core/stored-agent-event.js +101 -0
  103. package/build/core/transcripts.js +214 -228
  104. package/build/core/verdict.js +27 -15
  105. package/build/core/worktree-bootstrap.js +187 -0
  106. package/build/core/worktree-path.js +72 -18
  107. package/build/flow-error.js +4 -6
  108. package/build/generated/version.js +1 -1
  109. package/build/git/branches.js +6 -1
  110. package/build/index.js +8 -5
  111. package/build/keiyaku.js +1 -3
  112. package/package.json +6 -5
  113. package/skills/keiyaku/SKILL.md +6 -47
  114. package/skills/keiyaku-akuma/SKILL.md +75 -0
  115. package/build/agents/effective-policy.js +0 -32
  116. package/build/agents/index.js +0 -114
  117. package/build/agents/selector.js +0 -28
  118. package/build/cli/render/summon.js +0 -17
  119. package/build/cli/render/tell.js +0 -11
  120. package/build/config/akuma-loader.js +0 -268
  121. package/build/core/queue.js +0 -73
  122. package/build/core/summon-persist.js +0 -73
  123. package/build/core/summon.js +0 -377
@@ -1,73 +0,0 @@
1
- import { isFlowError } from "../flow-error.js";
2
- import { appendDebugLog } from "../telemetry/debug-log.js";
3
- import { logWarn } from "../telemetry/logger.js";
4
- import { runSummon } from "./summon.js";
5
- import { persistResponseHistory } from "./transcripts.js";
6
- import { getCurrentBranch } from "../git/branches.js";
7
- import { MISSING_HEAD_PATTERNS, NOT_GIT_REPOSITORY_PATTERNS, errorContainsAnyPattern } from "../git/core.js";
8
- import { getLatestCommitHash } from "../git/staging.js";
9
- import { isErrnoException } from "../errno.js";
10
- function isMissingPathError(error) {
11
- return isErrnoException(error) && error.code === "ENOENT";
12
- }
13
- function isBenignHistoryBranchLookupError(error) {
14
- return ((isFlowError(error) && error.code === "DETACHED_HEAD") ||
15
- isMissingPathError(error) ||
16
- errorContainsAnyPattern(error, NOT_GIT_REPOSITORY_PATTERNS));
17
- }
18
- function isBenignHistoryCommitLookupError(error) {
19
- return (isMissingPathError(error) ||
20
- errorContainsAnyPattern(error, NOT_GIT_REPOSITORY_PATTERNS) ||
21
- errorContainsAnyPattern(error, MISSING_HEAD_PATTERNS));
22
- }
23
- export async function runSummonAndPersist(input) {
24
- const result = await runSummon(input);
25
- if (input.incognito) {
26
- return { result };
27
- }
28
- let responsePath;
29
- let historyBranch;
30
- try {
31
- historyBranch = await getCurrentBranch(input.cwd);
32
- }
33
- catch (error) {
34
- if (!isBenignHistoryBranchLookupError(error)) {
35
- throw error;
36
- }
37
- historyBranch = undefined;
38
- }
39
- let commitHash;
40
- try {
41
- commitHash = await getLatestCommitHash(input.cwd);
42
- }
43
- catch (error) {
44
- if (!isBenignHistoryCommitLookupError(error)) {
45
- throw error;
46
- }
47
- commitHash = undefined;
48
- }
49
- try {
50
- responsePath = await persistResponseHistory({
51
- cwd: input.cwd,
52
- tool: "summon",
53
- title: input.title,
54
- task: input.task,
55
- context: input.context,
56
- response: result.summary,
57
- session: result.session,
58
- subagentName: result.agent,
59
- branch: historyBranch,
60
- commit: commitHash,
61
- effectivePolicy: result.meta?.effectivePolicy,
62
- });
63
- }
64
- catch (historyError) {
65
- const historyErrorMessage = historyError instanceof Error ? historyError.message : String(historyError);
66
- logWarn(`Failed to persist summon response: ${historyErrorMessage}`, { cwd: input.cwd, section: "script" });
67
- appendDebugLog(`tool summon response persistence failed: ${historyErrorMessage}`, {
68
- cwd: input.cwd,
69
- section: "script",
70
- });
71
- }
72
- return { result, responsePath };
73
- }
@@ -1,377 +0,0 @@
1
- import * as fs from "fs/promises";
2
- import * as path from "path";
3
- import { ACTOR_IDENTITY, BASE_RULES_FILE, KEIYAKU_FILE, isSubagentProvider } from "../keiyaku.js";
4
- import { isErrnoException } from "../errno.js";
5
- import { FlowError, requireText } from "../flow-error.js";
6
- import { isGitRepo } from "../git/branches.js";
7
- import { createGit, wrapGitError } from "../git/core.js";
8
- import { selectSubagent } from "../agents/selector.js";
9
- import { buildSummonTerms, createAbortError } from "../agents/index.js";
10
- import { resolveEffectiveCodexSdkProfile } from "../agents/effective-policy.js";
11
- import { resume, summon } from "../agents/harness/index.js";
12
- import { mintProjection } from "./projection-mint.js";
13
- import { createProjectionExecutionId, latestGenerationLaunch, publishGenerationLaunch, publishGenerationResult, publishVerdict, readAdmissionLock, releaseAdmissionLockOwned } from "./projection-core.js";
14
- import { CODEX_MODEL_REASONING_EFFORT_CONFIG_KEY } from "../keiyaku.js";
15
- import { initializeConfig } from "../config/env.js";
16
- import { resolveSummonResumePath } from "./transcripts.js";
17
- import { appendDebugBlock } from "../telemetry/debug-log.js";
18
- import { logInfo } from "../telemetry/logger.js";
19
- import { SubagentFailure } from "../agents/types.js";
20
- import { resolveCurrentContractId } from "./context.js";
21
- import { readLedger } from "./ledger.js";
22
- import { findOpenArcView } from "./arc.js";
23
- import { deriveContractState } from "./status.js";
24
- import { contractWorktreePathFromBind } from "./worktree-path.js";
25
- export function buildSummonPrompt(input) {
26
- const references = [...new Set((input.referenceFiles ?? []).map((file) => file.trim()).filter(Boolean))];
27
- if (!input.arc) {
28
- return [input.task, input.context?.trim() ?? "", references.length > 0 ? `Reference files:\n${references.map((file) => `- ${file}`).join("\n")}` : ""]
29
- .filter(Boolean)
30
- .join("\n\n");
31
- }
32
- const arc = input.arc;
33
- return [
34
- `You are a summoned ${ACTOR_IDENTITY} working inside open arc a${arc.arc}.`,
35
- "Stay within the arc scope and do the requested work directly.",
36
- `Title: ${arc.title}`,
37
- `Objective: ${arc.objective}`,
38
- `Brief:\n${arc.brief}`,
39
- "",
40
- `Task:\n${input.task}`,
41
- `Context:\n${input.context?.trim() || "(none provided)"}`,
42
- references.length > 0 ? `Reference files:\n${references.map((file) => `- ${file}`).join("\n")}` : "",
43
- "Provide the final result for the caller/main agent.",
44
- ].filter(Boolean).join("\n\n");
45
- }
46
- function renderSubagentWarning(warning) {
47
- const modelTransition = warning.originalModel && warning.fallbackModel
48
- ? `${warning.originalModel} -> ${warning.fallbackModel}`
49
- : warning.originalModel ?? warning.fallbackModel;
50
- const details = [
51
- modelTransition,
52
- warning.direction ? `direction=${warning.direction}` : undefined,
53
- warning.requestId !== undefined ? `requestId=${warning.requestId ?? "null"}` : undefined,
54
- warning.signerModel ? `signerModel=${warning.signerModel}` : undefined,
55
- ].filter((value) => Boolean(value));
56
- const summary = warning.reason === "refusal" ? "Provider warning: model fallback." : "Provider warning: overload fallback.";
57
- return details.length > 0 ? `${summary} ${details.join(", ")}` : summary;
58
- }
59
- async function fileExists(cwd, relativePath) {
60
- try {
61
- await fs.access(path.join(cwd, relativePath));
62
- return true;
63
- }
64
- catch (error) {
65
- if (isErrnoException(error) && error.code === "ENOENT") {
66
- return false;
67
- }
68
- throw error;
69
- }
70
- }
71
- async function collectSummonReferenceFiles(cwd, input) {
72
- const candidates = [
73
- ...(input.activeKeiyaku ? [KEIYAKU_FILE] : []),
74
- BASE_RULES_FILE,
75
- ];
76
- const existing = await Promise.all(candidates.map(async (file) => ({ file, exists: await fileExists(cwd, file) })));
77
- return existing.filter((entry) => entry.exists).map((entry) => entry.file);
78
- }
79
- async function findWorktreePathForContract(cwd, contractId) {
80
- const git = createGit(cwd);
81
- let output;
82
- try {
83
- output = await git.raw(["worktree", "list", "--porcelain"]);
84
- }
85
- catch (error) {
86
- throw wrapGitError("worktree list --porcelain", error, cwd);
87
- }
88
- let currentPath;
89
- for (const line of output.split(/\r?\n/)) {
90
- if (line.startsWith("worktree ")) {
91
- currentPath = line.slice("worktree ".length);
92
- continue;
93
- }
94
- if (line === `branch refs/heads/keiyaku/${contractId}`) {
95
- return currentPath;
96
- }
97
- }
98
- return undefined;
99
- }
100
- async function resolveWorkspaceCwd(cwd, contractId, bind) {
101
- const repoRoot = cwd;
102
- if (bind.data.workspace === "here")
103
- return repoRoot;
104
- const listedWorktreePath = await findWorktreePathForContract(cwd, contractId);
105
- const worktreePath = listedWorktreePath ?? await contractWorktreePathFromBind(repoRoot, contractId, bind);
106
- let stat;
107
- try {
108
- stat = await fs.stat(worktreePath);
109
- }
110
- catch (error) {
111
- throw new FlowError("INTERNAL_STATE", `contract ${contractId} worktree not found at ${worktreePath}`, { cause: error });
112
- }
113
- if (!stat.isDirectory()) {
114
- throw new FlowError("INTERNAL_STATE", `contract ${contractId} worktree path is not a directory: ${worktreePath}`);
115
- }
116
- return worktreePath;
117
- }
118
- async function readSummonKeiyakuContext(cwd, bare = false) {
119
- if (bare)
120
- return { activeKeiyaku: false, effectiveCwd: cwd };
121
- const isRepo = await isGitRepo(cwd);
122
- if (!isRepo) {
123
- return { activeKeiyaku: false, effectiveCwd: cwd };
124
- }
125
- const resolution = await resolveCurrentContractId(cwd);
126
- if (resolution.status === "none")
127
- return { activeKeiyaku: false, effectiveCwd: cwd };
128
- const contractId = resolution.contractId;
129
- const ledger = await readLedger(cwd, contractId);
130
- if (!ledger) {
131
- throw new FlowError("INTERNAL_STATE", `contract ${contractId} not found or not active`);
132
- }
133
- const state = deriveContractState(ledger.entries);
134
- if (state.state === "corrupt") {
135
- throw new FlowError("INTERNAL_STATE", `contract ${contractId} is corrupt at entry ${state.at}: ${state.reason}`);
136
- }
137
- const bind = ledger.entries.find((entry) => entry.kind === "bind");
138
- if (!bind) {
139
- throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger is missing bind entry`);
140
- }
141
- const effectiveCwd = await resolveWorkspaceCwd(cwd, contractId, bind);
142
- const openArc = findOpenArcView(ledger.entries);
143
- return {
144
- activeKeiyaku: true,
145
- effectiveCwd,
146
- openArc: openArc ?? undefined,
147
- };
148
- }
149
- export async function execSubagent(agentName, prompt, cwd, options = {}) {
150
- const config = await buildSummonConfig(agentName, prompt, cwd, options);
151
- const projection = options.resume
152
- ? resume({
153
- ...config,
154
- session: options.resume.session,
155
- resumePath: options.resume.resumePath,
156
- })
157
- : summon(config);
158
- const outcome = await projection.outcome;
159
- switch (outcome.status) {
160
- case "completed":
161
- return outcome;
162
- case "dismissed":
163
- throw createAbortError("subagent exec cancelled by client");
164
- case "failed": {
165
- const error = outcome.error;
166
- if (!error) {
167
- throw new FlowError("SUBAGENT_EXEC_ERROR", "Subagent exec failed without an error payload.");
168
- }
169
- throw new FlowError(error.code, error.message, {
170
- cause: new SubagentFailure(error.code, error.message, {
171
- timeoutMs: error.timeoutMs,
172
- exitCode: error.exitCode,
173
- output: outcome.output,
174
- diagnostics: outcome.diagnostics,
175
- }),
176
- });
177
- }
178
- }
179
- throw new FlowError("INTERNAL_STATE", "Unhandled subagent outcome state.");
180
- }
181
- async function buildSummonConfig(agentName, prompt, cwd, options) {
182
- const selected = options.selected ?? await selectSubagent(agentName, cwd);
183
- const withModel = options.model ? { ...selected.profile, model: options.model } : selected.profile;
184
- if (selected.profile.provider !== "codex-sdk" && (selected.profile.accessPolicy !== undefined || selected.profile.networkPolicy !== undefined || selected.profile.webSearchPolicy !== undefined)) {
185
- throw new FlowError("UNSUPPORTED_POLICY", `Provider '${selected.profile.provider}' does not support Akuma policy fields.`);
186
- }
187
- const effectiveProfile = options.config && (selected.profile.provider === "codex-sdk" || selected.profile.provider === "codex-app-server")
188
- ? { ...withModel, config: options.config }
189
- : withModel;
190
- if (options.effort && effectiveProfile.provider === "opencode-sdk") {
191
- throw new FlowError("UNSUPPORTED_EFFORT_OVERRIDE", `Provider 'opencode-sdk' does not support effort override '${options.effort}'.`);
192
- }
193
- const effortProfile = options.effort
194
- ? effectiveProfile.provider === "claude-agent-sdk"
195
- ? { ...effectiveProfile, effort: options.effort }
196
- : effectiveProfile.provider === "codex-sdk"
197
- ? { ...effectiveProfile, effort: options.effort }
198
- : effectiveProfile.provider === "codex-app-server"
199
- ? { ...effectiveProfile, config: { ...(effectiveProfile.config ?? {}), [CODEX_MODEL_REASONING_EFFORT_CONFIG_KEY]: options.effort } }
200
- : effectiveProfile.provider === "pi"
201
- ? { ...effectiveProfile, thinkingLevel: options.effort === "max" ? "xhigh" : options.effort }
202
- : effectiveProfile
203
- : effectiveProfile;
204
- const resolvedProfile = effortProfile.provider === "codex-sdk"
205
- ? resolveEffectiveCodexSdkProfile(effectiveProfile, cwd, {
206
- ...(options.model ? { model: options.model } : {}),
207
- ...(options.effort ? { effort: options.effort } : {}),
208
- })
209
- : effortProfile;
210
- // Mint projection directory for supervisor pump.
211
- const slug = agentName.replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
212
- let mintedDir;
213
- let projectionExecutionId;
214
- try {
215
- const minted = mintProjection({
216
- cwd,
217
- slug,
218
- pid: process.pid,
219
- akuma: agentName,
220
- provider: resolvedProfile.provider,
221
- ...(resolvedProfile.provider === "codex-sdk" ? { effectivePolicy: resolvedProfile.effectivePolicy } : {}),
222
- nowMs: Date.now(),
223
- });
224
- mintedDir = minted.dir;
225
- projectionExecutionId = createProjectionExecutionId();
226
- publishGenerationLaunch(mintedDir, {
227
- version: 1,
228
- executionId: projectionExecutionId,
229
- createdAt: new Date().toISOString(),
230
- launchedBy: "summon",
231
- inputs: {
232
- prompt,
233
- task: options.task ?? prompt,
234
- model: resolvedProfile.model,
235
- profile: agentName,
236
- // This is the immutable provider/profile snapshot. The wake path must
237
- // not be changed by later catalog or settings edits.
238
- profileData: resolvedProfile,
239
- cwd,
240
- akumaBody: selected.definition.body,
241
- ...(resolvedProfile.provider === "codex-sdk" || resolvedProfile.provider === "codex-app-server" ? { config: resolvedProfile.config } : {}),
242
- },
243
- });
244
- }
245
- catch {
246
- // If minting fails (e.g., EACCES), continue without supervisor.
247
- }
248
- return buildSummonTerms(resolvedProfile, prompt, cwd, {
249
- signal: options.signal,
250
- timeoutMs: options.timeoutMs,
251
- idleTimeoutMs: options.idleTimeoutMs,
252
- projectionDir: mintedDir,
253
- projectionExecutionId,
254
- // Selection is rooted in this canonical execution cwd, so the selected body is too.
255
- akumaBody: selected.definition.body,
256
- });
257
- }
258
- /** Internal wake entrypoint: reconstruct one persisted generation in its original projection. */
259
- export async function runProjectionGeneration(projectionDirectory) {
260
- const launch = latestGenerationLaunch(projectionDirectory);
261
- if (!launch)
262
- throw new FlowError("INTERNAL_STATE", "projection has no generation launch record");
263
- const executionId = launch.executionId;
264
- try {
265
- const input = launch.inputs;
266
- const profile = typeof input.profile === "string" ? input.profile : undefined;
267
- const prompt = typeof input.prompt === "string" ? input.prompt : undefined;
268
- const cwd = typeof input.cwd === "string" ? input.cwd : undefined;
269
- if (!profile || !prompt || !cwd)
270
- throw new FlowError("INTERNAL_STATE", "generation launch is missing profile, prompt, or cwd");
271
- // Hidden wake must recreate the exact runtime environment before term construction.
272
- initializeConfig(process.env, cwd);
273
- const durableProfile = input.profileData && typeof input.profileData === "object" && !Array.isArray(input.profileData)
274
- ? input.profileData
275
- : undefined;
276
- const durableBody = typeof input.akumaBody === "string" ? input.akumaBody : undefined;
277
- let effective;
278
- let akumaBody;
279
- if (durableProfile && durableBody !== undefined) {
280
- if (typeof durableProfile.provider !== "string" || !isSubagentProvider(durableProfile.provider)) {
281
- throw new FlowError("INTERNAL_STATE", "generation launch immutable profileData has an invalid provider");
282
- }
283
- effective = durableProfile;
284
- akumaBody = durableBody;
285
- }
286
- else {
287
- // Compatibility only for legacy launches that predate the complete immutable snapshot.
288
- const selected = await selectSubagent(profile, cwd);
289
- const model = typeof input.model === "string" ? input.model : undefined;
290
- const withModel = model ? { ...selected.profile, model } : selected.profile;
291
- const config = input.config && typeof input.config === "object" && !Array.isArray(input.config)
292
- ? input.config
293
- : undefined;
294
- effective = config && (withModel.provider === "codex-sdk" || withModel.provider === "codex-app-server")
295
- ? { ...withModel, config }
296
- : withModel;
297
- akumaBody = durableBody ?? selected.definition.body;
298
- }
299
- const terms = buildSummonTerms(effective, prompt, cwd, {
300
- projectionDir: projectionDirectory,
301
- projectionExecutionId: executionId,
302
- akumaBody,
303
- });
304
- const session = input.session;
305
- const resumePath = typeof input.resumePath === "string" ? input.resumePath : undefined;
306
- const projection = session && resumePath
307
- ? resume({ ...terms, session: session, resumePath })
308
- : summon(terms);
309
- await projection.outcome;
310
- }
311
- catch (error) {
312
- const detail = error instanceof Error ? error.message : String(error);
313
- // A child that failed to acquire admission must be entirely silent: it may
314
- // be a duplicate wake and cannot publish over the winner's ledger.
315
- const admission = readAdmissionLock(projectionDirectory);
316
- if (admission?.executionId === executionId) {
317
- publishGenerationResult(projectionDirectory, {
318
- version: 1,
319
- executionId,
320
- status: "failed",
321
- createdAt: new Date().toISOString(),
322
- detail,
323
- });
324
- publishVerdict(projectionDirectory, "failed", Date.now(), detail);
325
- releaseAdmissionLockOwned(projectionDirectory, executionId);
326
- }
327
- throw error;
328
- }
329
- }
330
- export async function runSummon(input) {
331
- const { signal, agent, resumePath } = input;
332
- const rawCwd = input.cwd;
333
- const cwd = await fs.realpath(rawCwd);
334
- requireText("title", input.title);
335
- const task = requireText("task", input.task);
336
- if (input.incognito && resumePath) {
337
- throw new FlowError("EMPTY_PARAM", "Parameter 'incognito' cannot be used with 'resumePath' — incognito summons do not resume or persist conversation history.");
338
- }
339
- const keiyakuContext = await readSummonKeiyakuContext(cwd, input.bare);
340
- const executionCwd = keiyakuContext.effectiveCwd;
341
- const referenceFiles = await collectSummonReferenceFiles(executionCwd, keiyakuContext);
342
- const prompt = buildSummonPrompt({
343
- task,
344
- context: input.context,
345
- referenceFiles,
346
- arc: keiyakuContext.openArc,
347
- });
348
- const resumePathResolution = resumePath ? await resolveSummonResumePath({ cwd: rawCwd, resumePath }) : undefined;
349
- const selectedSubagent = resumePathResolution
350
- ? await selectSubagent(resumePathResolution.subagentName, executionCwd)
351
- : await selectSubagent(agent, executionCwd);
352
- const resume = resumePath && resumePathResolution
353
- ? { ...resumePathResolution, resumePath }
354
- : undefined;
355
- logInfo(`[${ACTOR_IDENTITY}] Running execution for '${selectedSubagent.name}' in ${executionCwd}`, {
356
- cwd: executionCwd,
357
- section: "script",
358
- progressOnly: true,
359
- });
360
- const subagentOutcome = await execSubagent(selectedSubagent.name, prompt, executionCwd, {
361
- signal,
362
- resume,
363
- model: input.model,
364
- effort: input.effort,
365
- task,
366
- selected: selectedSubagent,
367
- });
368
- if (subagentOutcome.diagnostics.trim()) {
369
- appendDebugBlock("subagent diagnostics", subagentOutcome.diagnostics, { cwd: executionCwd, section: "subagent-stderr" });
370
- }
371
- return {
372
- summary: subagentOutcome.finalMessage || `${ACTOR_IDENTITY} completed successfully.`,
373
- agent: selectedSubagent.name,
374
- session: subagentOutcome.session,
375
- ...(subagentOutcome.warnings.length > 0 || subagentOutcome.effectivePolicy ? { meta: { ...(subagentOutcome.warnings.length > 0 ? { warnings: subagentOutcome.warnings.map(renderSubagentWarning) } : {}), ...(subagentOutcome.effectivePolicy ? { effectivePolicy: subagentOutcome.effectivePolicy } : {}) } } : {}),
376
- };
377
- }