@astrosheep/keiyaku 2.9.11 → 2.9.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/README.md +79 -85
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms.js +1 -0
  4. package/build/agents/providers/claude-agent-sdk/adapter.js +17 -4
  5. package/build/cli/commands/akuma/akuma/handler.js +2 -1
  6. package/build/cli/commands/akuma/akuma/meta.js +4 -3
  7. package/build/cli/commands/akuma/catalog.js +2 -0
  8. package/build/cli/commands/akuma/list/handler.js +1 -1
  9. package/build/cli/commands/akuma/list/meta-list.js +12 -0
  10. package/build/cli/commands/akuma/list/meta-ls.js +2 -2
  11. package/build/cli/commands/akuma.js +5 -0
  12. package/build/cli/commands/contract/amend/meta.js +4 -3
  13. package/build/cli/commands/contract/arc/meta.js +2 -0
  14. package/build/cli/commands/contract/audit/handler.js +28 -2
  15. package/build/cli/commands/contract/audit/meta.js +4 -3
  16. package/build/cli/commands/contract/bind/meta.js +4 -4
  17. package/build/cli/commands/contract/petition/handler.js +2 -1
  18. package/build/cli/commands/contract/petition/meta.js +2 -2
  19. package/build/cli/commands/contract/renew/handler.js +44 -3
  20. package/build/cli/commands/contract/renew/meta.js +5 -4
  21. package/build/cli/commands/metadata.js +14 -10
  22. package/build/cli/commands/projection/call/handler.js +1 -1
  23. package/build/cli/commands/projection/call/meta.js +1 -1
  24. package/build/cli/commands/projection/catalog.js +2 -2
  25. package/build/cli/commands/projection/{revive → fork}/handler.js +10 -5
  26. package/build/cli/commands/projection/fork/meta.js +12 -0
  27. package/build/cli/commands/projection/history/handler.js +46 -2
  28. package/build/cli/commands/projection/history/meta.js +3 -3
  29. package/build/cli/commands/projection/kill/handler.js +4 -5
  30. package/build/cli/commands/projection/kill/meta.js +2 -2
  31. package/build/cli/commands/projection/status/handler.js +29 -13
  32. package/build/cli/commands/projection/status/meta.js +14 -3
  33. package/build/cli/commands/projection/tell/handler.js +8 -4
  34. package/build/cli/commands/projection/tell/meta.js +1 -1
  35. package/build/cli/commands/projection/wait/handler.js +45 -20
  36. package/build/cli/commands/projection/wait/meta.js +1 -1
  37. package/build/cli/commands/shared.js +2 -2
  38. package/build/cli/commands/system/catalog.js +2 -0
  39. package/build/cli/commands/task/add/handler.js +28 -12
  40. package/build/cli/commands/task/add/meta.js +18 -6
  41. package/build/cli/commands/task/catalog.js +4 -0
  42. package/build/cli/commands/task/compose/handler.js +18 -0
  43. package/build/cli/commands/task/compose/meta.js +10 -0
  44. package/build/cli/commands/task/doctor/handler.js +2 -3
  45. package/build/cli/commands/task/doctor/meta.js +2 -2
  46. package/build/cli/commands/task/done/meta.js +2 -2
  47. package/build/cli/commands/task/drop/handler.js +7 -2
  48. package/build/cli/commands/task/drop/meta.js +6 -3
  49. package/build/cli/commands/task/hold/meta.js +2 -2
  50. package/build/cli/commands/task/log/meta.js +2 -2
  51. package/build/cli/commands/task/ls/meta.js +2 -2
  52. package/build/cli/commands/task/note/handler.js +6 -0
  53. package/build/cli/commands/task/note/meta.js +11 -0
  54. package/build/cli/commands/task/resume/meta.js +2 -2
  55. package/build/cli/commands/task/shared.js +29 -15
  56. package/build/cli/commands/task/show/meta.js +2 -2
  57. package/build/cli/commands/task/start/meta.js +2 -2
  58. package/build/cli/commands/task/stop/meta.js +2 -2
  59. package/build/cli/commands/task/update/meta.js +3 -2
  60. package/build/cli/commands/verification/handler.js +43 -0
  61. package/build/cli/commands/verification/meta.js +13 -0
  62. package/build/cli/completion.js +16 -13
  63. package/build/cli/flags.js +48 -12
  64. package/build/cli/help.js +29 -30
  65. package/build/cli/index.js +14 -8
  66. package/build/cli/parse-flags.js +60 -21
  67. package/build/cli/parse-metadata.js +10 -4
  68. package/build/cli/parse-selectors.js +22 -4
  69. package/build/cli/parse.js +43 -30
  70. package/build/cli/projection-address.js +7 -7
  71. package/build/cli/render/arc.js +12 -3
  72. package/build/cli/render/audit.js +2 -2
  73. package/build/cli/render/call.js +4 -4
  74. package/build/cli/render/kanshi.js +122 -85
  75. package/build/cli/render/misc.js +2 -2
  76. package/build/cli/render/petition.js +16 -1
  77. package/build/cli/render/projection-history.js +17 -4
  78. package/build/cli/render/shared.js +5 -5
  79. package/build/cli/render/status-indicator.js +47 -0
  80. package/build/cli/render/status.js +106 -76
  81. package/build/cli/render/success-response.js +20 -5
  82. package/build/cli/render/task.js +33 -5
  83. package/build/cli/render/tell.js +10 -4
  84. package/build/cli/render/tool-command-normalization.js +137 -0
  85. package/build/cli/render/tool-presentation.js +2 -1
  86. package/build/cli/render/verification.js +23 -0
  87. package/build/cli/render/wait.js +101 -33
  88. package/build/cli/types.js +2 -1
  89. package/build/config/akuma-loader.js +21 -1
  90. package/build/config/settings/knobs.js +7 -1
  91. package/build/config/settings/schema.js +10 -5
  92. package/build/core/addressing.js +3 -3
  93. package/build/core/amend.js +102 -17
  94. package/build/core/arc.js +4 -4
  95. package/build/core/audit/candidate.js +10 -18
  96. package/build/core/audit/coordinates.js +12 -17
  97. package/build/core/audit/evidence.js +6 -4
  98. package/build/core/audit/facade.js +3 -3
  99. package/build/core/audit/report.js +1 -1
  100. package/build/core/bind-reconciliation.js +42 -23
  101. package/build/core/bind.js +182 -81
  102. package/build/core/call/call.js +6 -7
  103. package/build/core/call/context.js +46 -33
  104. package/build/core/call/execution.js +21 -6
  105. package/build/core/call/prompt.js +11 -42
  106. package/build/core/contract-carrier-runtime.js +209 -105
  107. package/build/core/contract-carrier.js +156 -73
  108. package/build/core/contract-view.js +43 -6
  109. package/build/core/contract.js +2 -1
  110. package/build/core/derived-replay.js +168 -35
  111. package/build/core/draft.js +60 -27
  112. package/build/core/forfeit.js +1 -1
  113. package/build/core/lifecycle-history.js +13 -0
  114. package/build/core/lifecycle-recovery.js +32 -27
  115. package/build/core/lifecycle-runner.js +14 -14
  116. package/build/core/log.js +1 -1
  117. package/build/core/outcome-base.js +2 -2
  118. package/build/core/projection/akuma-name.js +43 -0
  119. package/build/core/projection/generation/database.js +141 -79
  120. package/build/core/projection/generation/ledger.js +91 -0
  121. package/build/core/projection/generation/model.js +19 -14
  122. package/build/core/projection/generation/projection-generation-continuation.js +1 -1
  123. package/build/core/projection/generation/projection-generation-doorbell.js +88 -0
  124. package/build/core/projection/generation/projection-generation-execution.js +24 -0
  125. package/build/core/projection/generation/projection-generation-identity.js +4 -0
  126. package/build/core/projection/generation/projection-generation-launcher.js +72 -138
  127. package/build/core/projection/generation/projection-generation-process.js +16 -15
  128. package/build/core/projection/generation/projection-generation-runner.js +132 -76
  129. package/build/core/projection/generation/projection-generation-runtime.js +10 -61
  130. package/build/core/projection/generation/protocol.js +68 -0
  131. package/build/core/projection/generation/store.js +17 -7
  132. package/build/core/projection/generation/transitions.js +24 -14
  133. package/build/core/projection/index.js +5 -5
  134. package/build/core/projection/projection-core.js +6 -2
  135. package/build/core/projection/projection-execution-observer.js +1 -1
  136. package/build/core/projection/projection-history.js +8 -8
  137. package/build/core/projection/projection-kill.js +20 -10
  138. package/build/core/projection/projection-life-observer.js +8 -8
  139. package/build/core/projection/projection-mint.js +6 -8
  140. package/build/core/projection/projection-status-observation.js +77 -8
  141. package/build/core/projection/projection-status.js +151 -4
  142. package/build/core/projection/projection-wait.js +48 -29
  143. package/build/core/projection/projection-wake.js +28 -88
  144. package/build/core/projection/tell/launch-store.js +1 -1
  145. package/build/core/projection/tell/store.js +1 -1
  146. package/build/core/renew-build.js +204 -74
  147. package/build/core/renew-plan.js +34 -9
  148. package/build/core/renew-rewrite.js +56 -15
  149. package/build/core/renew.js +39 -35
  150. package/build/core/repository-ledger/accepted-fold-read.js +6 -3
  151. package/build/core/repository-ledger/claim-evidence.js +1 -1
  152. package/build/core/repository-ledger/codec.js +11 -5
  153. package/build/core/repository-ledger/current-state-store.js +464 -349
  154. package/build/core/repository-ledger/fold-repository.js +5 -6
  155. package/build/core/repository-ledger/identity.js +60 -0
  156. package/build/core/repository-ledger/inventory.js +3 -3
  157. package/build/core/repository-ledger/read-model.js +57 -9
  158. package/build/core/repository-ledger/write-transaction.js +24 -17
  159. package/build/core/run-control/connection-bound-close.js +41 -0
  160. package/build/core/run-control/detached-lease-bootstrap.js +208 -0
  161. package/build/core/run-control/detached-process.js +14 -0
  162. package/build/core/run-control/index.js +6 -0
  163. package/build/core/{process-group.js → run-control/process-tree.js} +1 -1
  164. package/build/core/run-control/runner-lease.js +172 -0
  165. package/build/core/run-control/sqlite-process-lifetime-lock.js +174 -0
  166. package/build/core/seal.js +44 -32
  167. package/build/core/settlement/claim-delivery.js +22 -9
  168. package/build/core/settlement/claim.js +8 -6
  169. package/build/core/settlement/petition-claim-gates.js +9 -8
  170. package/build/core/settlement/petition-head-guard.js +5 -6
  171. package/build/core/settlement/petition-preview.js +21 -5
  172. package/build/core/settlement/petition.js +51 -17
  173. package/build/core/settlement/settlement.js +20 -15
  174. package/build/core/settlement/verdict.js +2 -2
  175. package/build/core/settlement/verification.js +492 -364
  176. package/build/core/status/board.js +184 -75
  177. package/build/core/status/drift.js +8 -10
  178. package/build/core/task/board.js +1 -0
  179. package/build/core/task/commands.js +25 -0
  180. package/build/core/task/compose.js +328 -0
  181. package/build/core/task/document.js +102 -39
  182. package/build/core/task/index.js +4 -3
  183. package/build/core/task/settlement-git.js +70 -30
  184. package/build/core/task/settlement-policy.js +27 -14
  185. package/build/core/task/source-board.js +1 -0
  186. package/build/core/task/task-bind-preparation.js +59 -9
  187. package/build/core/task/task-contract.js +2 -2
  188. package/build/core/task/task-git-store.js +1 -0
  189. package/build/core/task/task-store-repository.js +2 -0
  190. package/build/core/task/task.js +2 -2
  191. package/build/core/transcripts.js +4 -4
  192. package/build/core/verification-declaration.js +95 -0
  193. package/build/core/worktree-bootstrap.js +1 -1
  194. package/build/core/worktree-path.js +7 -11
  195. package/build/flow-error.js +15 -2
  196. package/build/generated/version.js +2 -2
  197. package/build/git/branches.js +41 -70
  198. package/build/git/commits.js +92 -21
  199. package/build/git/core.js +9 -161
  200. package/build/git/diff/preview.js +4 -4
  201. package/build/git/diff/read.js +4 -4
  202. package/build/git/diff/structured.js +5 -5
  203. package/build/git/process.js +229 -0
  204. package/build/git/refs.js +30 -5
  205. package/build/git/staging.js +39 -115
  206. package/build/git/streaming-batch.js +9 -16
  207. package/build/git/worktree.js +104 -91
  208. package/build/index.js +7 -0
  209. package/package.json +2 -2
  210. package/skills/keiyaku-akuma/SKILL.md +27 -21
  211. package/skills/keiyaku-task/SKILL.md +61 -5
  212. package/skills/keiyaku-workflow/SKILL.md +81 -26
  213. package/build/cli/commands/projection/revive/meta.js +0 -12
  214. package/build/core/projection/projection-life-protocol.js +0 -115
  215. package/build/core/projection/projection-runner-lock.js +0 -382
  216. package/build/core/projection/tell/database.js +0 -127
  217. package/build/core/settlement/verification-coordination.js +0 -305
  218. package/build/core/settlement/verification-supervisor.js +0 -275
@@ -19,6 +19,7 @@ export function buildCallTerms(snapshot, prompt, cwd, options) {
19
19
  maxCaptureChars: registration.maxCaptureChars(runtimeConfig),
20
20
  signal: options.signal,
21
21
  ...(options.initialTurn !== undefined ? { initialTurn: options.initialTurn } : {}),
22
+ ...(options.carrier !== undefined ? { carrier: options.carrier } : {}),
22
23
  };
23
24
  // Live registry only admits CallTerms-producing contributions; the open
24
25
  // registration surface returns structural RegistrationCallTerms.
@@ -3,7 +3,7 @@ import { SUBAGENT_SESSION_VERSION } from "../../session.js";
3
3
  import { createProjectionDriver } from "../../harness/execution-handle.js";
4
4
  import { exactLaunchInputReceipts } from "../../harness/control-types.js";
5
5
  import { createProviderFailure } from "../../harness/provider-adapter.js";
6
- import { buildSubagentEnv, createAbortError, emitProviderEvidence, linkAbortSignal, sha256Utf8 } from "../../harness/runtime.js";
6
+ import { awaitProviderAbortSettlement, buildSubagentEnv, createAbortError, emitProviderEvidence, linkAbortSignal, sha256Utf8 } from "../../harness/runtime.js";
7
7
  import { claudeIngressDisposition, emitClaudeThoughts, emitClaudeToolResults, emitClaudeToolStarts, emitClaudeUsage, extractAssistantMessage, extractAssistantMessageId, extractAssistantMessageModel, extractOverloadFallbackWarning, extractResultText, extractResumeToken, isClaudeApiRetryEvent, isClaudeModelRefusalFallbackEvent, isClaudeModelRefusalNoFallbackEvent, mapClaudeApiRetryWarning, } from "./events.js";
8
8
  import { CLAUDE_AGENT_SDK_PROVIDER, createPushableUserMessageStream, toClaudeUserMessage, } from "./session.js";
9
9
  function toClaudeSdkEffort(effort) {
@@ -19,6 +19,10 @@ async function loadClaudeAgentSdk(loader) {
19
19
  export async function startClaudeAgentSdk(prompt, cwd, options) {
20
20
  const sessionId = options.sessionId?.trim();
21
21
  let liveQuery;
22
+ let queryAbortController;
23
+ let runStarted = false;
24
+ let settleRun;
25
+ const runSettled = new Promise((resolve) => { settleRun = resolve; });
22
26
  let pendingEvidenceDiagnostics = 0;
23
27
  let builderDiagnostic = () => {
24
28
  pendingEvidenceDiagnostics += 1;
@@ -117,9 +121,13 @@ export async function startClaudeAgentSdk(prompt, cwd, options) {
117
121
  queryActive = false;
118
122
  const abortError = createAbortError(`${CLAUDE_AGENT_SDK_PROVIDER} exec cancelled by client`);
119
123
  if (mode === "force") {
124
+ queryAbortController?.abort(abortError);
120
125
  inputStream?.end(abortError);
121
126
  rejectPendingEnqueueWaiters(abortError);
122
127
  liveQuery?.close();
128
+ if (runStarted) {
129
+ await awaitProviderAbortSettlement(CLAUDE_AGENT_SDK_PROVIDER, runSettled, "forced query teardown did not settle");
130
+ }
123
131
  return;
124
132
  }
125
133
  try {
@@ -131,8 +139,12 @@ export async function startClaudeAgentSdk(prompt, cwd, options) {
131
139
  liveQuery?.close();
132
140
  inputStream?.end(abortError);
133
141
  rejectPendingEnqueueWaiters(abortError);
142
+ if (runStarted) {
143
+ await awaitProviderAbortSettlement(CLAUDE_AGENT_SDK_PROVIDER, runSettled, "graceful query teardown did not settle");
144
+ }
134
145
  },
135
146
  async run(builder) {
147
+ runStarted = true;
136
148
  builderDiagnostic = (text) => builder.emit({ type: "diagnostic", text });
137
149
  emitTurnStarted = () => builder.emit({ type: "turn", phase: "started" });
138
150
  while (pendingEvidenceDiagnostics > 0) {
@@ -140,7 +152,7 @@ export async function startClaudeAgentSdk(prompt, cwd, options) {
140
152
  builderDiagnostic("provider evidence callback failed");
141
153
  }
142
154
  const sdk = await loadClaudeAgentSdk(options.loader);
143
- const queryAbortController = new AbortController();
155
+ queryAbortController = new AbortController();
144
156
  const unlinkBuilderAbort = linkAbortSignal(builder.signal, queryAbortController, () => undefined);
145
157
  const unlinkOuterAbort = linkAbortSignal(options.signal, queryAbortController, () => undefined);
146
158
  try {
@@ -150,7 +162,7 @@ export async function startClaudeAgentSdk(prompt, cwd, options) {
150
162
  // Claude's source pull is the provider-native launch-input fact.
151
163
  // The adapter records its coordinate before asking heart to reduce
152
164
  // the exact attributed receipt.
153
- const fence = { kind: "ordinal", ordinal: 0 };
165
+ const fence = { kind: "ordinal", ordinal: completedResultOrdinal + 1 };
154
166
  await options.onLaunchAdmission?.({ fence, tellIds: options.launchTellIds ?? [] });
155
167
  const admissions = (options.listLaunchAdmissions?.() ?? []).filter((admission) => (admission.fence.kind === "ordinal" && admission.fence.ordinal === fence.ordinal));
156
168
  for (const receipt of exactLaunchInputReceipts("seen", fence, admissions))
@@ -310,7 +322,7 @@ export async function startClaudeAgentSdk(prompt, cwd, options) {
310
322
  }
311
323
  // Sync checkpoint: claim inbox tells and deliver them via steer control.
312
324
  options.onSyncCheckpoint?.({ enqueue }, checkpoint);
313
- const admissions = (options.listLaunchAdmissions?.() ?? []).filter((admission) => (admission.fence.kind === "ordinal" && admission.fence.ordinal < checkpoint.fence.ordinal));
325
+ const admissions = (options.listLaunchAdmissions?.() ?? []).filter((admission) => (admission.fence.kind === "ordinal" && admission.fence.ordinal <= checkpoint.fence.ordinal));
314
326
  for (const receipt of exactLaunchInputReceipts("consumed", checkpoint.fence, admissions))
315
327
  options.onTellReceipt?.(receipt);
316
328
  options.onTellReceipt?.({ stage: "consumed", correlation: { kind: "fence", fence: checkpoint.fence } });
@@ -375,6 +387,7 @@ export async function startClaudeAgentSdk(prompt, cwd, options) {
375
387
  inputStream.end(endError);
376
388
  }
377
389
  rejectPendingEnqueueWaiters(endError);
390
+ settleRun();
378
391
  }
379
392
  },
380
393
  });
@@ -1,4 +1,5 @@
1
1
  import { missingSubcommandError } from "../../../missing-subcommand.js";
2
+ import { AKUMA_SUBCOMMANDS } from "../../../types.js";
2
3
  export const handler = async () => {
3
- throw missingSubcommandError("akuma", ["ls", "show"]);
4
+ throw missingSubcommandError("akuma", AKUMA_SUBCOMMANDS);
4
5
  };
@@ -1,16 +1,17 @@
1
+ import { AKUMA_SUBCOMMANDS } from "../../../types.js";
1
2
  export const meta = {
2
3
  command: "akuma",
3
4
  summary: "Inspect Akuma profiles",
4
- usage: ["keiyaku akuma ls|show"],
5
+ usage: ["keiyaku akuma list|show"],
5
6
  stdin: { mode: "argument" },
6
7
  flags: [],
7
8
  purpose: "Inspect configured helper profiles.",
8
- subcommands: ["ls", "show"],
9
+ subcommands: AKUMA_SUBCOMMANDS,
9
10
  notes: [
10
11
  "Define user profiles in <KEIYAKU_HOME>/akuma/<name>.md.",
11
12
  "Define project profiles in .keiyaku/akuma/<name>.md.",
12
13
  "See README Configuration for the Markdown frontmatter format.",
13
14
  ],
14
- examples: ["keiyaku akuma ls", "keiyaku akuma show akuma-codex"],
15
+ examples: ["keiyaku akuma list", "keiyaku akuma show akuma-codex"],
15
16
  completionRank: 6,
16
17
  };
@@ -1,8 +1,10 @@
1
1
  import { meta as akumaMeta } from "./akuma/meta.js";
2
+ import { meta as listMeta } from "./list/meta-list.js";
2
3
  import { meta as lsMeta } from "./list/meta-ls.js";
3
4
  import { meta as showMeta } from "./show/meta.js";
4
5
  export const akumaCatalog = [
5
6
  { meta: akumaMeta, load: () => import("./akuma/handler.js") },
7
+ { meta: listMeta, load: () => import("./list/handler.js") },
6
8
  { meta: lsMeta, load: () => import("./list/handler.js") },
7
9
  { meta: showMeta, load: () => import("./show/handler.js") },
8
10
  ];
@@ -5,7 +5,7 @@ import { textResponse } from "../../../render/shared.js";
5
5
  import { projectDirectory } from "../../shared.js";
6
6
  import { renderAkumaList } from "../../akuma.js";
7
7
  export const handler = async (_stdin, flags) => {
8
- const cwd = await projectDirectory(flags, "akuma ls");
8
+ const cwd = await projectDirectory(flags, "akuma list");
9
9
  const loaded = await loadKeiyakuSettings(cwd);
10
10
  // Role markers need settings pointers; catalog consumers keep legacy agents disease actionable.
11
11
  assertSettingsKnobUsable(loaded, "agents");
@@ -0,0 +1,12 @@
1
+ export const meta = {
2
+ command: "akuma list",
3
+ summary: "List Akuma profiles",
4
+ usage: ["keiyaku akuma list [-C|--cwd DIR] [--repo DIR]"],
5
+ stdin: { mode: "argument" },
6
+ flags: ["cwd", "repo"],
7
+ purpose: "List configured helper profiles.",
8
+ notes: [
9
+ "`keiyaku akuma ls` is a short alias.",
10
+ "Project profiles override user profiles, which override builtins.",
11
+ ],
12
+ };
@@ -1,9 +1,9 @@
1
1
  export const meta = {
2
2
  command: "akuma ls",
3
- summary: "List Akuma profiles",
3
+ summary: "Alias for akuma list",
4
4
  usage: ["keiyaku akuma ls [-C|--cwd DIR] [--repo DIR]"],
5
5
  stdin: { mode: "argument" },
6
6
  flags: ["cwd", "repo"],
7
- purpose: "List configured helper profiles.",
7
+ purpose: "Short alias for the canonical `keiyaku akuma list` command.",
8
8
  notes: ["Project profiles override user profiles, which override builtins."],
9
9
  };
@@ -112,10 +112,13 @@ function chooseCallHintName(validNames, settings) {
112
112
  export function renderAkumaList(catalog, providerInstances, settings) {
113
113
  const lines = ["Available Akumas:", ""];
114
114
  const validNames = [];
115
+ const hasCustomSelectedCandidate = Object.values(catalog.selected).some((candidate) => candidate.source !== "builtin");
115
116
  for (const name of Object.keys(catalog.selected).sort((a, b) => a.localeCompare(b))) {
116
117
  const candidate = catalog.selected[name];
117
118
  if (candidate === undefined)
118
119
  continue;
120
+ if (hasCustomSelectedCandidate && candidate.source === "builtin")
121
+ continue;
119
122
  const resolved = resolveAkumaInspection(candidate, providerInstances);
120
123
  const markers = formatRoleMarkers(settings, resolved.name);
121
124
  if (resolved.status === "invalid") {
@@ -130,6 +133,8 @@ export function renderAkumaList(catalog, providerInstances, settings) {
130
133
  }
131
134
  }
132
135
  for (const shadow of catalog.shadows) {
136
+ if (hasCustomSelectedCandidate && shadow.source === "builtin")
137
+ continue;
133
138
  lines.push(`- ${shadow.name} [${shadow.source}] (shadowed by ${shadow.shadowedBy})`);
134
139
  }
135
140
  const hintName = chooseCallHintName(validNames, settings);
@@ -2,11 +2,12 @@ export const meta = {
2
2
  command: "amend",
3
3
  summary: "Record an amendment",
4
4
  usage: [
5
+ "keiyaku amend [-C|--cwd DIR] [--repo DIR] [--contract ADDR] --append-scope PATTERN [--append-scope PATTERN ...]",
5
6
  "keiyaku amend [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--append-scope PATTERN] - < amendment.md",
6
- "keiyaku @addr amend [-C|--cwd DIR] [--repo DIR] [--append-scope PATTERN] - < amendment.md",
7
+ "keiyaku @addr amend [-C|--cwd DIR] [--repo DIR] [--append-scope PATTERN] [-] < amendment.md",
7
8
  ],
8
- stdin: { mode: "document", selector: { kind: "positional", index: 0, required: true, rejectBlank: true } },
9
+ stdin: { mode: "document", selector: { kind: "positional", index: 0, required: false, rejectBlank: true } },
9
10
  flags: ["cwd", "repo", "contract", "append-scope"],
10
- purpose: "Append a prose amendment and one optional ordered scope-pattern delta from --append-scope or Scope Append.",
11
+ purpose: "Append narrative Markdown or ordered scope patterns. --append-scope is sufficient without Markdown; ## Replace Verifications replaces contract-only Verification declarations, with - (none) to clear them.",
11
12
  completionRank: 8,
12
13
  };
@@ -21,6 +21,8 @@ export const meta = {
21
21
  "An empty seal is valid.",
22
22
  "The command does not create delivery commits.",
23
23
  "The first explicit arc seals a0; later arcs seal the previous open explicit arc.",
24
+ "Use arcs only for stages of one delivery and final settlement; an arc has no independent Scope, claim, or settlement.",
25
+ "--append-scope adds to the cumulative contract Scope, not an arc-local Scope.",
24
26
  ],
25
27
  completionRank: 1,
26
28
  };
@@ -1,13 +1,39 @@
1
1
  import { auditContract } from "../../../../core/audit.js";
2
2
  import { resolveContractAddress, withResolvedAddress } from "../../../../core/addressing.js";
3
+ import { FlowError } from "../../../../flow-error.js";
3
4
  import { buildAuditConstructionFailure, buildAuditResponse } from "../../../render/audit.js";
4
5
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
6
+ export function assertAuditPresentationOptions(options) {
7
+ if (options.skipDiffBody && options.diffBudgetBytes !== undefined) {
8
+ throw new FlowError("INVALID_USAGE", "audit --skip-diff-body cannot be used with --diff-budget");
9
+ }
10
+ if (options.skipDiffBody && options.json) {
11
+ throw new FlowError("INVALID_USAGE", "audit --skip-diff-body cannot be used with --json");
12
+ }
13
+ }
14
+ /** Shared ordinary audit pipeline for direct audit and renew's post-renew composition. */
15
+ export async function runAuditCommand(options) {
16
+ assertAuditPresentationOptions(options);
17
+ return withResolvedAddress(options.address, async () => {
18
+ return buildAuditResponse(await auditContract({
19
+ cwd: options.cwd,
20
+ address: options.address,
21
+ diffBudgetBytes: options.skipDiffBody ? 0 : options.diffBudgetBytes,
22
+ signal: options.signal,
23
+ }), options.json === true);
24
+ });
25
+ }
5
26
  export const handler = async (_stdin, flags, signal) => {
6
27
  try {
7
28
  const cwd = await repositoryDirectory(flags, "audit");
8
29
  const address = await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
9
- return await withResolvedAddress(address, async () => {
10
- return buildAuditResponse(await auditContract({ cwd, address, diffBudgetBytes: flags.auditDiffBudgetBytes, signal }), flags.json === true);
30
+ return await runAuditCommand({
31
+ cwd,
32
+ address,
33
+ diffBudgetBytes: flags.auditDiffBudgetBytes,
34
+ skipDiffBody: flags.auditSkipDiffBody,
35
+ json: flags.json,
36
+ signal,
11
37
  });
12
38
  }
13
39
  catch (error) {
@@ -2,14 +2,15 @@ export const meta = {
2
2
  command: "audit",
3
3
  summary: "Read settlement facts from one pinned delivery candidate",
4
4
  usage: [
5
- "keiyaku audit [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--diff-budget BYTES] [--json]",
6
- "keiyaku @<id> audit [--diff-budget BYTES] [--json]",
5
+ "keiyaku audit [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--diff-budget BYTES|--skip-diff-body] [--json]",
6
+ "keiyaku @<id> audit [--diff-budget BYTES|--skip-diff-body] [--json]",
7
7
  ],
8
8
  stdin: { mode: "argument" },
9
- flags: ["cwd", "repo", "contract", "diff-budget", "json"],
9
+ flags: ["cwd", "repo", "contract", "diff-budget", "skip-diff-body", "json"],
10
10
  purpose: "Inspect one pinned delivery candidate, report settlement facts, and recheck its coordinates without mutating the source repository.",
11
11
  notes: [
12
12
  "Audit never invokes an Akuma or settles the contract.",
13
+ "--skip-diff-body suppresses only human raw-hunk presentation; it cannot be combined with --diff-budget or --json.",
13
14
  "Exit 0 means the report was constructed; exit 1 carries a typed construction cause.",
14
15
  ],
15
16
  completionRank: 9,
@@ -5,7 +5,7 @@ export const meta = {
5
5
  "keiyaku @<full-contract-id> bind [-C|--cwd DIR] [--repo DIR]",
6
6
  "keiyaku bind --contract <full-contract-id> [-C|--cwd DIR] [--repo DIR]",
7
7
  "keiyaku bind [-C|--cwd DIR] [--repo DIR] [--task ID]... [- < contract.md]",
8
- "keiyaku bind [-C|--cwd DIR] [--repo DIR] [--task ID]... --title TEXT --context TEXT --objective TEXT --design TEXT --scope GLOB --criteria CRITERION [--verification DECLARATION] [--dry-run]",
8
+ "keiyaku bind [-C|--cwd DIR] [--repo DIR] [--task ID]... --title TEXT --context TEXT --objective TEXT --design TEXT --scope GLOB [--scope GLOB]... --criteria CRITERION [--verification DECLARATION] [--dry-run]",
9
9
  ],
10
10
  stdin: { mode: "document", selector: { kind: "positional", index: 0, required: false, rejectBlank: false } },
11
11
  flags: ["cwd", "repo", "contract", "after", "exclusive", "draft-only", "title", "context", "objective", "design", "scope", "criteria", "verification", "task", "dry-run"],
@@ -21,7 +21,7 @@ export const meta = {
21
21
  "## Objective",
22
22
  "<what the commission should accomplish>",
23
23
  "",
24
- "## Design",
24
+ "## Design & Approach",
25
25
  "<settled blueprint>",
26
26
  "",
27
27
  "## Scope",
@@ -54,7 +54,7 @@ export const meta = {
54
54
  "## Objective",
55
55
  "<what the commission should accomplish>",
56
56
  "",
57
- "## Design",
57
+ "## Design & Approach",
58
58
  "<settled blueprint>",
59
59
  "",
60
60
  "## Scope",
@@ -75,7 +75,7 @@ export const meta = {
75
75
  "## Context",
76
76
  "<established facts and constraints>",
77
77
  "",
78
- "## Design",
78
+ "## Design & Approach",
79
79
  "<settled blueprint>",
80
80
  "",
81
81
  "## Scope",
@@ -18,11 +18,12 @@ export const handler = async (stdin, flags, signal) => {
18
18
  const address = await resolveExistingContractAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
19
19
  return await withResolvedAddress(address, async () => {
20
20
  if (flags.dryRun) {
21
- const input = buildPetitionClaimInput({ cwd, contractId: address.binding.commissionId, stdin, signal });
21
+ const input = buildPetitionClaimInput({ cwd, contractId: address.binding.commissionId, stdin, signal, appendScope: flags.appendScope });
22
22
  return buildPetitionPreviewResponse(await previewPetition({
23
23
  cwd,
24
24
  contractId: address.binding.commissionId,
25
25
  oath: input.oath,
26
+ appendScope: input.appendScope,
26
27
  signal,
27
28
  }), flags.json === true);
28
29
  }
@@ -1,6 +1,6 @@
1
1
  export const meta = {
2
2
  command: "petition",
3
- summary: "Run or preview the gated settlement pipeline",
3
+ summary: "Settle or preview settlement for a contract",
4
4
  usage: [
5
5
  "keiyaku petition [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--renew] [--append-scope PATTERN] [- < petition.md]",
6
6
  "keiyaku @<id> petition [-C|--cwd DIR] [--repo DIR] [--renew] [--append-scope PATTERN] [- < petition.md]",
@@ -8,7 +8,7 @@ export const meta = {
8
8
  ],
9
9
  stdin: { mode: "document", selector: { kind: "positional", index: 0, required: false, rejectBlank: false } },
10
10
  flags: ["cwd", "repo", "contract", "renew", "append-scope", "dry-run", "json"],
11
- purpose: "Seal the current a0 or open explicit arc, queue the contract, and run verdict and claim processing; dry-run previews deterministic gates without mutation.",
11
+ purpose: "Seal the current delivery stage and run settlement checks before claiming the contract; dry-run previews deterministic checks without changing the contract.",
12
12
  input: [
13
13
  "## Oath",
14
14
  "<free first-person attestation>",
@@ -2,23 +2,64 @@ import { resolveContractAddress, resolveExistingContractAddress } from "../../..
2
2
  import { abortRenewKeiyaku, continueRenewKeiyaku, renewKeiyaku } from "../../../../core/renew.js";
3
3
  import { buildRenewAbortResponse, buildRenewResponse } from "../../../render/arc.js";
4
4
  import { renderLifecycleResult } from "../../../render/lifecycle.js";
5
+ import { buildAuditConstructionFailure } from "../../../render/audit.js";
6
+ import { isCompleteLifecycleOutcome } from "../../../../core/outcome-base.js";
7
+ import { writeCliOutput } from "../../../output-stream-error-policy.js";
8
+ import { assertAuditPresentationOptions, runAuditCommand } from "../audit/handler.js";
9
+ import { FlowError } from "../../../../flow-error.js";
5
10
  import { effectiveDirectory, repositoryDirectory } from "../../shared.js";
6
11
  export const handler = async (_stdin, flags, signal) => {
12
+ if (flags.renewAbort && flags.renewAudit) {
13
+ throw new FlowError("INVALID_USAGE", "renew --audit cannot be used with --abort");
14
+ }
15
+ if (flags.auditSkipDiffBody && !flags.renewAudit) {
16
+ throw new FlowError("INVALID_USAGE", "renew --skip-diff-body requires --audit");
17
+ }
18
+ if (flags.renewAudit) {
19
+ assertAuditPresentationOptions({
20
+ diffBudgetBytes: flags.auditDiffBudgetBytes,
21
+ skipDiffBody: flags.auditSkipDiffBody,
22
+ json: flags.json,
23
+ });
24
+ }
7
25
  const cwd = await repositoryDirectory(flags, "renew");
8
26
  const resolveAddress = flags.renewContinue || flags.renewAbort
9
27
  ? resolveContractAddress
10
28
  : resolveExistingContractAddress;
11
29
  const address = await resolveAddress(cwd, flags.contractId, flags.contractAddressSource, effectiveDirectory(flags));
12
30
  if (flags.renewContinue) {
13
- return renderLifecycleResult(continueRenewKeiyaku({ cwd, address, appendScope: flags.appendScope, signal }), buildRenewResponse, { cwd, address });
31
+ const result = await continueRenewKeiyaku({ cwd, address, appendScope: flags.appendScope, signal });
32
+ if (!flags.renewAudit || !isCompleteLifecycleOutcome(result)) {
33
+ return renderLifecycleResult(Promise.resolve(result), buildRenewResponse, { cwd, address });
34
+ }
35
+ return renderRenewThenAudit({ cwd, address, result, flags, signal });
14
36
  }
15
37
  if (flags.renewAbort) {
16
38
  return renderLifecycleResult(abortRenewKeiyaku({ cwd, address, signal }), buildRenewAbortResponse, { cwd, address });
17
39
  }
18
- return renderLifecycleResult(renewKeiyaku({
40
+ const result = await renewKeiyaku({
19
41
  cwd,
20
42
  address,
21
43
  appendScope: flags.appendScope,
22
44
  signal,
23
- }), buildRenewResponse, { cwd, address });
45
+ });
46
+ if (!flags.renewAudit || !isCompleteLifecycleOutcome(result)) {
47
+ return renderLifecycleResult(Promise.resolve(result), buildRenewResponse, { cwd, address });
48
+ }
49
+ return renderRenewThenAudit({ cwd, address, result, flags, signal });
24
50
  };
51
+ async function renderRenewThenAudit({ cwd, address, result, flags, signal, }) {
52
+ await writeCliOutput(process.stdout, `${buildRenewResponse(result).text}\n\n`);
53
+ try {
54
+ return await runAuditCommand({
55
+ cwd,
56
+ address,
57
+ diffBudgetBytes: flags.auditDiffBudgetBytes,
58
+ skipDiffBody: flags.auditSkipDiffBody,
59
+ signal,
60
+ });
61
+ }
62
+ catch (error) {
63
+ return buildAuditConstructionFailure(error, false);
64
+ }
65
+ }
@@ -2,17 +2,18 @@ export const meta = {
2
2
  command: "renew",
3
3
  summary: "Rewrite delivery onto the current base",
4
4
  usage: [
5
- "keiyaku renew [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--append-scope PATTERN]",
6
- "keiyaku @<id> renew --continue [--append-scope PATTERN]",
5
+ "keiyaku renew [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--append-scope PATTERN] [--audit [--skip-diff-body]]",
6
+ "keiyaku @<id> renew --continue [--append-scope PATTERN] [--audit [--skip-diff-body]]",
7
7
  "keiyaku @<id> renew --abort",
8
8
  ],
9
9
  stdin: { mode: "argument" },
10
- flags: ["cwd", "repo", "contract", "append-scope", "continue", "abort"],
11
- purpose: "Capture receipts, rewrite delivery onto the default branch, then seal the current a0 or open explicit arc and record the renewal.",
10
+ flags: ["cwd", "repo", "contract", "append-scope", "continue", "abort", "audit", "skip-diff-body"],
11
+ purpose: "Refresh committed contract changes onto the current target, then seal the refreshed delivery stage and record the renewal.",
12
12
  notes: [
13
13
  "After an explicit arc closes, refuses loose commits until another arc is open.",
14
14
  "Refuses while an Akuma is in flight.",
15
15
  "Conflicts create derived scratch without changing the ledger, delivery branch, or worktree; resolve that scratch with --continue or discard it with --abort.",
16
+ "--audit runs the ordinary read-only audit only after renew completes or reports already fresh; --skip-diff-body is available only with --audit.",
16
17
  ],
17
18
  completionRank: 9,
18
19
  };
@@ -1,12 +1,13 @@
1
1
  import { meta as bindMeta } from "./contract/bind/meta.js";
2
2
  import { meta as arcMeta } from "./contract/arc/meta.js";
3
3
  import { meta as callMeta } from "./projection/call/meta.js";
4
- import { meta as reviveMeta } from "./projection/revive/meta.js";
4
+ import { meta as forkMeta } from "./projection/fork/meta.js";
5
5
  import { meta as waitMeta } from "./projection/wait/meta.js";
6
6
  import { meta as tellMeta } from "./projection/tell/meta.js";
7
7
  import { meta as killMeta } from "./projection/kill/meta.js";
8
8
  import { meta as logMeta } from "./contract/log/meta.js";
9
9
  import { meta as akumaMeta } from "./akuma/akuma/meta.js";
10
+ import { meta as akumaListMeta } from "./akuma/list/meta-list.js";
10
11
  import { meta as akumaLsMeta } from "./akuma/list/meta-ls.js";
11
12
  import { meta as akumaShowMeta } from "./akuma/show/meta.js";
12
13
  import { meta as skillsMeta } from "./skills/skills/meta.js";
@@ -16,12 +17,14 @@ import { meta as auditMeta } from "./contract/audit/meta.js";
16
17
  import { meta as renewMeta } from "./contract/renew/meta.js";
17
18
  import { meta as petitionMeta } from "./contract/petition/meta.js";
18
19
  import { meta as forfeitMeta } from "./contract/forfeit/meta.js";
20
+ import { meta as verificationMeta } from "./verification/meta.js";
19
21
  import { meta as guideMeta } from "./system/guide/meta.js";
20
22
  import { meta as completionMeta } from "./system/completion/meta.js";
21
23
  import { meta as statusMeta } from "./projection/status/meta.js";
22
24
  import { meta as historyMeta } from "./projection/history/meta.js";
23
25
  import { meta as taskMeta } from "./task/task/meta.js";
24
26
  import { meta as taskAddMeta } from "./task/add/meta.js";
27
+ import { meta as taskComposeMeta } from "./task/compose/meta.js";
25
28
  import { meta as taskShowMeta } from "./task/show/meta.js";
26
29
  import { meta as taskLsMeta } from "./task/ls/meta.js";
27
30
  import { meta as taskLogMeta } from "./task/log/meta.js";
@@ -30,24 +33,25 @@ import { meta as taskStopMeta } from "./task/stop/meta.js";
30
33
  import { meta as taskHoldMeta } from "./task/hold/meta.js";
31
34
  import { meta as taskResumeMeta } from "./task/resume/meta.js";
32
35
  import { meta as taskDoneMeta } from "./task/done/meta.js";
36
+ import { meta as taskNoteMeta } from "./task/note/meta.js";
33
37
  import { meta as taskDropMeta } from "./task/drop/meta.js";
34
38
  import { meta as taskUpdateMeta } from "./task/update/meta.js";
35
39
  import { meta as taskDoctorMeta } from "./task/doctor/meta.js";
36
40
  import { meta as dumpEnvMeta } from "./system/dump-env/meta.js";
37
41
  export const COMMAND_METADATA_ORDER = [
38
- "bind", "arc", "call", "revive", "wait", "tell", "kill", "log",
39
- "akuma", "akuma ls", "akuma show", "skills", "skills install", "amend", "audit",
40
- "renew", "petition", "forfeit", "guide", "completion", "status", "history", "task",
41
- "task add", "task show", "task ls", "task log", "task start", "task stop", "task hold", "task resume", "task done",
42
+ "bind", "arc", "call", "fork", "wait", "tell", "kill", "log",
43
+ "akuma", "akuma list", "akuma ls", "akuma show", "skills", "skills install", "amend", "audit",
44
+ "renew", "petition", "forfeit", "verification", "guide", "completion", "status", "history", "task",
45
+ "task add", "task compose", "task show", "task ls", "task log", "task start", "task stop", "task hold", "task resume", "task done", "task note",
42
46
  "task drop", "task update", "task doctor", "dump-env",
43
47
  ];
44
48
  const COMMAND_METADATA = [
45
- bindMeta, arcMeta, callMeta, reviveMeta, waitMeta, tellMeta, killMeta, logMeta,
46
- akumaMeta, akumaLsMeta, akumaShowMeta, skillsMeta, skillsInstallMeta, amendMeta, auditMeta,
47
- renewMeta, petitionMeta, forfeitMeta, guideMeta, completionMeta, statusMeta, historyMeta,
48
- taskMeta, taskAddMeta, taskShowMeta, taskLsMeta, taskLogMeta, taskStartMeta, taskStopMeta,
49
+ bindMeta, arcMeta, callMeta, forkMeta, waitMeta, tellMeta, killMeta, logMeta,
50
+ akumaMeta, akumaListMeta, akumaLsMeta, akumaShowMeta, skillsMeta, skillsInstallMeta, amendMeta, auditMeta,
51
+ renewMeta, petitionMeta, forfeitMeta, verificationMeta, guideMeta, completionMeta, statusMeta, historyMeta,
52
+ taskMeta, taskAddMeta, taskComposeMeta, taskShowMeta, taskLsMeta, taskLogMeta, taskStartMeta, taskStopMeta,
49
53
  taskHoldMeta, taskResumeMeta,
50
- taskDoneMeta, taskDropMeta, taskUpdateMeta, taskDoctorMeta, dumpEnvMeta,
54
+ taskDoneMeta, taskNoteMeta, taskDropMeta, taskUpdateMeta, taskDoctorMeta, dumpEnvMeta,
51
55
  ];
52
56
  export const CLI_COMMAND_METADATA = Object.fromEntries(COMMAND_METADATA.map((meta) => [meta.command, meta]));
53
57
  export function getCommandMetadata(command) {
@@ -10,7 +10,7 @@ export const handler = async (stdin, flags, signal) => {
10
10
  // Bounded outer join: same durable launch/adoption as detach, without core's unbounded join.
11
11
  ...(flags.timeoutMs !== undefined ? { detach: true } : {}),
12
12
  signal,
13
- ...(!flags.detach
13
+ ...(!flags.json && !flags.detach
14
14
  ? {
15
15
  onLaunch: ({ address, projection, akumaName }) => {
16
16
  process.stdout.write(`${renderAdoptedLaunchReceipt(address, projection.id, projection.alias, projection.previousAliasTarget, akumaName)}\n`);
@@ -6,7 +6,7 @@ export const meta = {
6
6
  mode: "argument",
7
7
  selector: { kind: "positional", index: 0, required: true, rejectBlank: true },
8
8
  },
9
- flags: ["cwd", "repo", "contract", "akuma", "model", "effort", "incognito", "bare", "detach", "alias", "wait"],
9
+ flags: ["cwd", "repo", "contract", "akuma", "model", "effort", "incognito", "bare", "detach", "alias", "wait", "json"],
10
10
  purpose: "Run a scoped helper task.",
11
11
  completionRank: 2,
12
12
  };
@@ -1,5 +1,5 @@
1
1
  import { meta as callMeta } from "./call/meta.js";
2
- import { meta as reviveMeta } from "./revive/meta.js";
2
+ import { meta as forkMeta } from "./fork/meta.js";
3
3
  import { meta as waitMeta } from "./wait/meta.js";
4
4
  import { meta as tellMeta } from "./tell/meta.js";
5
5
  import { meta as killMeta } from "./kill/meta.js";
@@ -7,7 +7,7 @@ import { meta as statusMeta } from "./status/meta.js";
7
7
  import { meta as historyMeta } from "./history/meta.js";
8
8
  export const projectionCatalog = [
9
9
  { meta: callMeta, load: () => import("./call/handler.js") },
10
- { meta: reviveMeta, load: () => import("./revive/handler.js") },
10
+ { meta: forkMeta, load: () => import("./fork/handler.js") },
11
11
  { meta: waitMeta, load: () => import("./wait/handler.js") },
12
12
  { meta: tellMeta, load: () => import("./tell/handler.js") },
13
13
  { meta: killMeta, load: () => import("./kill/handler.js") },
@@ -3,13 +3,14 @@ import { FlowError } from "../../../../flow-error.js";
3
3
  import { buildArtifactResolutionAttempt, } from "../../../../core/addressing.js";
4
4
  import { runCallAndPersist } from "../../../../core/call-persist.js";
5
5
  import { locateResponseArtifact, reconcileResponseArtifactCatalog, } from "../../../../core/transcripts.js";
6
+ import { resolveProjectionHistoryAddress } from "../../../../core/projection/index.js";
6
7
  import { observeGitRepository } from "../../../../git/branches.js";
7
8
  import { stableRepoRoot } from "../../../../core/worktree-path.js";
8
9
  import { buildCallResponse } from "../../../render/call.js";
9
- import { buildCallInput, effectiveDirectory, projectDirectory, revivePrompt } from "../../shared.js";
10
+ import { buildCallInput, effectiveDirectory, forkPrompt, projectDirectory } from "../../shared.js";
10
11
  export const handler = async (stdin, flags, signal, positional) => {
11
12
  const cwd = effectiveDirectory(flags);
12
- const artifactCwd = await projectDirectory(flags, "revive");
13
+ const artifactCwd = await projectDirectory(flags, "fork");
13
14
  const artifactId = positional[0];
14
15
  const repository = await observeGitRepository(artifactCwd);
15
16
  if (repository.capability === "unknown")
@@ -20,7 +21,7 @@ export const handler = async (stdin, flags, signal, positional) => {
20
21
  await reconcileResponseArtifactCatalog(responseStoreCwd);
21
22
  }
22
23
  catch {
23
- // The catalog is disposable and cannot make an otherwise valid revive fail.
24
+ // The catalog is disposable and cannot make an otherwise valid fork fail.
24
25
  }
25
26
  const artifact = await locateResponseArtifact({
26
27
  cwd: responseStoreCwd,
@@ -34,6 +35,7 @@ export const handler = async (stdin, flags, signal, positional) => {
34
35
  inference: ["response artifact identity lookup"],
35
36
  }),
36
37
  });
38
+ const sourceProjectionId = await resolveProjectionHistoryAddress(responseStoreCwd, artifactId);
37
39
  let executionCwd;
38
40
  let repo;
39
41
  if (artifact.provenance.authority.kind === "repository") {
@@ -48,9 +50,12 @@ export const handler = async (stdin, flags, signal, positional) => {
48
50
  repo = undefined;
49
51
  }
50
52
  const outcome = await runCallAndPersist({
51
- ...buildCallInput(revivePrompt(stdin), { ...flags, cwd: executionCwd, repo }, "revive"),
53
+ ...buildCallInput(forkPrompt(stdin), { ...flags, cwd: executionCwd, repo }, "revive"),
52
54
  reviveArtifact: artifact,
53
55
  signal,
54
56
  });
55
- return buildCallResponse(outcome.result, { responsePath: outcome.responsePath, artifactId: outcome.artifactId, addressPlacement: "footer" });
57
+ return buildCallResponse({
58
+ ...outcome.result,
59
+ ...(sourceProjectionId ? { sourceProjectionId } : {}),
60
+ }, { responsePath: outcome.responsePath, artifactId: outcome.artifactId, addressPlacement: "footer" });
56
61
  };
@@ -0,0 +1,12 @@
1
+ export const meta = {
2
+ command: "fork",
3
+ summary: "Start an Akuma helper session from a response artifact",
4
+ usage: ["keiyaku fork ARTIFACT [BODY|-]"],
5
+ stdin: {
6
+ mode: "argument",
7
+ selector: { kind: "positional", index: 1, required: false, rejectBlank: true },
8
+ },
9
+ flags: ["cwd", "repo", "model", "effort", "json"],
10
+ purpose: "Start a new projection from a persisted helper session.",
11
+ completionRank: 4,
12
+ };