@astrosheep/keiyaku 2.9.3 → 2.9.5

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 (282) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/agents/call-terms.js +14 -94
  3. package/build/agents/harness/activity-values.js +16 -0
  4. package/build/agents/harness/event-persistence.js +218 -0
  5. package/build/agents/harness/execution-handle.js +26 -222
  6. package/build/agents/harness/index.js +3 -1
  7. package/build/agents/harness/outcome.js +68 -5
  8. package/build/agents/harness/projection.js +179 -124
  9. package/build/agents/harness/provider-adapter.js +58 -0
  10. package/build/agents/harness/router.js +11 -187
  11. package/build/agents/harness/runtime.js +17 -4
  12. package/build/agents/harness/session.js +15 -0
  13. package/build/agents/launch-snapshot/model.js +15 -236
  14. package/build/agents/launch-snapshot/parse-helpers.js +114 -0
  15. package/build/agents/launch-snapshot/resolve.js +17 -43
  16. package/build/agents/opencode-sdk.js +45 -12
  17. package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
  18. package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
  19. package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
  20. package/build/agents/providers/codex-app-server/adapter.js +82 -53
  21. package/build/agents/providers/codex-app-server/events.js +90 -11
  22. package/build/agents/providers/codex-app-server/identity.js +1 -0
  23. package/build/agents/providers/codex-app-server/policy.js +29 -0
  24. package/build/agents/providers/codex-app-server/registration.js +248 -0
  25. package/build/agents/providers/codex-app-server/session-schema.js +6 -0
  26. package/build/agents/providers/codex-app-server/session.js +23 -17
  27. package/build/agents/providers/codex-app-server/terms.js +1 -0
  28. package/build/agents/providers/opencode-sdk/adapter.js +94 -50
  29. package/build/agents/providers/opencode-sdk/events.js +8 -4
  30. package/build/agents/providers/opencode-sdk/registration.js +135 -0
  31. package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
  32. package/build/agents/providers/opencode-sdk/session.js +21 -14
  33. package/build/agents/providers/opencode-sdk/terms.js +1 -0
  34. package/build/agents/providers/pi/adapter.js +36 -30
  35. package/build/agents/providers/pi/events.js +4 -3
  36. package/build/agents/providers/pi/registration.js +145 -0
  37. package/build/agents/providers/pi/session-schema.js +6 -0
  38. package/build/agents/providers/pi/terms.js +1 -0
  39. package/build/agents/providers/registration.js +7 -0
  40. package/build/agents/providers/registry.js +76 -0
  41. package/build/agents/selector.js +2 -29
  42. package/build/agents/types.js +10 -0
  43. package/build/artifact-directories.js +22 -0
  44. package/build/cli/commands/akuma/akuma/handler.js +1 -1
  45. package/build/cli/commands/akuma/akuma/meta.js +1 -1
  46. package/build/cli/commands/akuma/list/meta-ls.js +1 -1
  47. package/build/cli/commands/akuma/view/handler.js +5 -4
  48. package/build/cli/commands/akuma/view/meta.js +1 -1
  49. package/build/cli/commands/akuma.js +6 -0
  50. package/build/cli/commands/contract/amend/handler.js +8 -2
  51. package/build/cli/commands/contract/amend/meta.js +4 -4
  52. package/build/cli/commands/contract/arc/handler.js +8 -2
  53. package/build/cli/commands/contract/arc/meta.js +4 -4
  54. package/build/cli/commands/contract/audit/handler.js +16 -0
  55. package/build/cli/commands/contract/audit/meta.js +16 -0
  56. package/build/cli/commands/contract/bind/handler.js +4 -3
  57. package/build/cli/commands/contract/bind/meta.js +44 -8
  58. package/build/cli/commands/contract/catalog.js +2 -0
  59. package/build/cli/commands/contract/forfeit/handler.js +4 -4
  60. package/build/cli/commands/contract/forfeit/meta.js +1 -1
  61. package/build/cli/commands/contract/log/handler.js +3 -3
  62. package/build/cli/commands/contract/log/meta.js +1 -1
  63. package/build/cli/commands/contract/petition/handler.js +5 -8
  64. package/build/cli/commands/contract/petition/meta.js +6 -6
  65. package/build/cli/commands/contract/renew/handler.js +20 -6
  66. package/build/cli/commands/contract/renew/meta.js +6 -5
  67. package/build/cli/commands/metadata.js +59 -0
  68. package/build/cli/commands/projection/call/handler.js +6 -5
  69. package/build/cli/commands/projection/call/meta.js +4 -1
  70. package/build/cli/commands/projection/kill/handler.js +16 -32
  71. package/build/cli/commands/projection/kill/meta.js +1 -1
  72. package/build/cli/commands/projection/revive/meta.js +4 -1
  73. package/build/cli/commands/projection/shared.js +28 -0
  74. package/build/cli/commands/projection/status/handler.js +1 -1
  75. package/build/cli/commands/projection/status/meta.js +1 -1
  76. package/build/cli/commands/projection/tell/handler.js +14 -30
  77. package/build/cli/commands/projection/tell/meta.js +4 -1
  78. package/build/cli/commands/projection/wait/handler.js +45 -22
  79. package/build/cli/commands/projection/wait/meta.js +8 -3
  80. package/build/cli/commands/registry.js +2 -54
  81. package/build/cli/commands/shared.js +10 -7
  82. package/build/cli/commands/skills/install/handler.js +2 -5
  83. package/build/cli/commands/skills/install/meta.js +1 -1
  84. package/build/cli/commands/skills/skills/handler.js +1 -1
  85. package/build/cli/commands/skills/skills/meta.js +1 -1
  86. package/build/cli/commands/system/completion/meta.js +1 -1
  87. package/build/cli/commands/system/dump-env/meta.js +1 -1
  88. package/build/cli/commands/system/guide/meta.js +1 -1
  89. package/build/cli/commands/task/add/handler.js +7 -15
  90. package/build/cli/commands/task/add/meta.js +4 -1
  91. package/build/cli/commands/task/catalog.js +2 -2
  92. package/build/cli/commands/task/doctor/meta.js +1 -1
  93. package/build/cli/commands/task/done/handler.js +4 -8
  94. package/build/cli/commands/task/done/meta.js +1 -1
  95. package/build/cli/commands/task/drop/handler.js +3 -6
  96. package/build/cli/commands/task/drop/meta.js +1 -1
  97. package/build/cli/commands/task/ls/handler.js +12 -8
  98. package/build/cli/commands/task/ls/meta.js +3 -3
  99. package/build/cli/commands/task/shared.js +14 -4
  100. package/build/cli/commands/task/{view → show}/handler.js +7 -8
  101. package/build/cli/commands/task/show/meta.js +8 -0
  102. package/build/cli/commands/task/start/handler.js +3 -6
  103. package/build/cli/commands/task/start/meta.js +1 -1
  104. package/build/cli/commands/task/stop/handler.js +4 -8
  105. package/build/cli/commands/task/stop/meta.js +1 -1
  106. package/build/cli/commands/task/task/handler.js +1 -1
  107. package/build/cli/commands/task/task/meta.js +1 -1
  108. package/build/cli/commands/task/update/handler.js +6 -11
  109. package/build/cli/commands/task/update/meta.js +4 -1
  110. package/build/cli/completion.js +1 -1
  111. package/build/cli/flags.js +37 -6
  112. package/build/cli/help.js +7 -14
  113. package/build/cli/index.js +112 -154
  114. package/build/cli/missing-subcommand.js +7 -0
  115. package/build/cli/output-stream-error-policy.js +19 -5
  116. package/build/cli/parse-flags.js +33 -7
  117. package/build/cli/parse-metadata.js +3 -9
  118. package/build/cli/parse-selectors.js +2 -1
  119. package/build/cli/parse.js +35 -5
  120. package/build/cli/projection-address.js +12 -12
  121. package/build/cli/render/address.js +41 -37
  122. package/build/cli/render/arc.js +24 -12
  123. package/build/cli/render/audit.js +121 -0
  124. package/build/cli/render/call.js +11 -5
  125. package/build/cli/render/errors.js +36 -1
  126. package/build/cli/render/format.js +4 -0
  127. package/build/cli/render/kanshi.js +6 -12
  128. package/build/cli/render/kill.js +9 -0
  129. package/build/cli/render/misc.js +58 -13
  130. package/build/cli/render/petition.js +20 -15
  131. package/build/cli/render/projection-activity.js +15 -6
  132. package/build/cli/render/shared.js +60 -21
  133. package/build/cli/render/skills.js +10 -0
  134. package/build/cli/render/status.js +56 -23
  135. package/build/cli/render/success-response.js +78 -0
  136. package/build/cli/render/task.js +66 -57
  137. package/build/cli/render/tell.js +5 -0
  138. package/build/cli/render/terminal-failure.js +63 -0
  139. package/build/cli/render/types.js +1 -0
  140. package/build/cli/render/wait.js +68 -38
  141. package/build/cli/types.js +1 -1
  142. package/build/config/akuma-loader.js +0 -5
  143. package/build/config/env-keys.js +3 -1
  144. package/build/config/env.js +3 -0
  145. package/build/config/provider-policy-ownership.js +3 -32
  146. package/build/config/settings/disease.js +8 -1
  147. package/build/config/settings/loader.js +11 -3
  148. package/build/config/settings/provider-instance-fields.js +51 -0
  149. package/build/config/settings/schema.js +6 -176
  150. package/build/core/addressing.js +66 -16
  151. package/build/core/amend.js +61 -18
  152. package/build/core/arc.js +33 -73
  153. package/build/core/audit.js +650 -0
  154. package/build/core/bind.js +82 -35
  155. package/build/core/call/call.js +15 -9
  156. package/build/core/call/context.js +6 -51
  157. package/build/core/call/execution.js +22 -22
  158. package/build/core/call/prompt.js +14 -1
  159. package/build/core/command-markdown.js +45 -0
  160. package/build/core/context.js +13 -7
  161. package/build/core/contract-view.js +22 -6
  162. package/build/core/draft.js +139 -19
  163. package/build/core/entry.js +3 -4
  164. package/build/core/forfeit.js +5 -2
  165. package/build/core/hints.js +1 -75
  166. package/build/core/identifier-slug.js +66 -0
  167. package/build/core/ids.js +25 -11
  168. package/build/core/ledger.js +20 -68
  169. package/build/core/markdown/lex.js +2 -1
  170. package/build/core/markdown/parser.js +0 -68
  171. package/build/core/markdown/render.js +68 -0
  172. package/build/core/markdown/sections.js +2 -1
  173. package/build/core/outcome-base.js +4 -0
  174. package/build/core/projection/generation/database.js +41 -52
  175. package/build/core/projection/generation/model.js +63 -2
  176. package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
  177. package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
  178. package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
  179. package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
  180. package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
  181. package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
  182. package/build/core/projection/generation/store.js +3 -3
  183. package/build/core/projection/generation/transitions.js +19 -3
  184. package/build/core/projection/index.js +27 -0
  185. package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
  186. package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
  187. package/build/core/projection/projection-coordinate.js +61 -0
  188. package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
  189. package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
  190. package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
  191. package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
  192. package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
  193. package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
  194. package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
  195. package/build/core/projection/projection-terminal-failure.js +106 -0
  196. package/build/core/projection/projection-wait.js +275 -0
  197. package/build/core/projection/projection-wake.js +227 -0
  198. package/build/core/provider-loader-ports.js +4 -0
  199. package/build/core/ref-log.js +65 -40
  200. package/build/core/registry.js +63 -10
  201. package/build/core/renew-session.js +128 -0
  202. package/build/core/renew.js +448 -102
  203. package/build/core/scope.js +272 -68
  204. package/build/core/seal.js +165 -40
  205. package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
  206. package/build/core/{claim.js → settlement/claim.js} +32 -8
  207. package/build/core/settlement/index.js +19 -0
  208. package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
  209. package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
  210. package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
  211. package/build/core/settlement/petition-io.js +1 -0
  212. package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
  213. package/build/core/{petition.js → settlement/petition.js} +21 -12
  214. package/build/core/settlement/queue-read-model.js +143 -0
  215. package/build/core/settlement/queue-seat-allocation.js +156 -0
  216. package/build/core/settlement/queue.js +6 -0
  217. package/build/core/settlement/settlement.js +288 -0
  218. package/build/core/{verdict.js → settlement/verdict.js} +9 -37
  219. package/build/core/settlement/verification.js +59 -0
  220. package/build/core/status/board.js +62 -41
  221. package/build/core/status/ledger-batch.js +158 -0
  222. package/build/core/status/reconciliation.js +10 -4
  223. package/build/core/stored-agent-event.js +6 -2
  224. package/build/core/task/board.js +41 -4
  225. package/build/core/task/commands.js +45 -28
  226. package/build/core/task/document.js +5 -0
  227. package/build/core/task/index.js +12 -0
  228. package/build/core/task/model.js +8 -1
  229. package/build/core/task/query.js +172 -0
  230. package/build/core/task/settlement-git.js +265 -74
  231. package/build/core/task/settlement-policy.js +67 -29
  232. package/build/core/task/source-board.js +1 -0
  233. package/build/core/task/task-contract.js +444 -0
  234. package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
  235. package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
  236. package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
  237. package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
  238. package/build/core/task/task-repository.js +1 -0
  239. package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
  240. package/build/core/task/task-store.js +1 -0
  241. package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
  242. package/build/core/task/task.js +7 -0
  243. package/build/core/task/tree.js +37 -0
  244. package/build/core/task/validation.js +5 -2
  245. package/build/core/transcripts.js +15 -3
  246. package/build/core/worktree-path.js +43 -28
  247. package/build/flow-error.js +83 -39
  248. package/build/fs/path-coordinate.js +16 -0
  249. package/build/generated/version.js +3 -2
  250. package/build/git/branches.js +2 -1
  251. package/build/git/core.js +106 -2
  252. package/build/git/diff/parsers.js +23 -13
  253. package/build/git/diff/structured.js +127 -0
  254. package/build/git/path-coordinate.js +17 -0
  255. package/build/git/refs.js +57 -0
  256. package/build/git/streaming-batch.js +301 -0
  257. package/build/git/worktree.js +65 -0
  258. package/build/index.js +9 -9
  259. package/build/keiyaku.js +2 -36
  260. package/build/telemetry/logger.js +4 -2
  261. package/package.json +4 -10
  262. package/skills/keiyaku/SKILL.md +5 -4
  263. package/skills/keiyaku-akuma/SKILL.md +25 -11
  264. package/skills/keiyaku-task/SKILL.md +17 -8
  265. package/skills/keiyaku-workflow/SKILL.md +58 -9
  266. package/build/agents/providers/codex-sdk.js +0 -329
  267. package/build/cli/commands/task/view/meta.js +0 -8
  268. package/build/core/command-io.js +0 -174
  269. package/build/core/path-coordinate.js +0 -27
  270. package/build/core/petition-claim.js +0 -117
  271. package/build/core/petition-run.js +0 -83
  272. package/build/core/projection-coordinate.js +0 -63
  273. package/build/core/projection-wait.js +0 -165
  274. package/build/core/projection-wake.js +0 -136
  275. package/build/core/queue.js +0 -343
  276. package/build/core/task-contract.js +0 -237
  277. package/build/core/task.js +0 -4
  278. /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
  279. /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
  280. /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
  281. /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
  282. /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
@@ -1,19 +1,19 @@
1
- import * as fs from "node:fs/promises";
2
- import * as path from "node:path";
3
- import { FlowError } from "../flow-error.js";
4
- import { createGit, errorContainsAnyPattern, MISSING_HEAD_PATTERNS, wrapGitError } from "../git/core.js";
5
- import { KEIYAKU_FILE } from "../keiyaku.js";
6
- import { activeLedgerRef, appendWithRetry, readLedger } from "./ledger.js";
7
- import { readProjectionStatusBoard } from "./projection-status.js";
8
- import { renderContractView } from "./contract-view.js";
9
- import { captureSeal, findOpenArc, getMaxArc, receiptsAfterFence, sealCurrentArc } from "./seal.js";
1
+ import { asMessage, FlowError } from "../flow-error.js";
2
+ import { createGit, errorContainsAnyPattern, MISSING_HEAD_PATTERNS, parseRevListOutput, runGitProcess, wrapGitError } from "../git/core.js";
3
+ import { readLedger } from "./ledger.js";
4
+ import { hasStrandableProjectionGeneration } from "./projection/index.js";
5
+ import { refreshContractView } from "./contract-view.js";
6
+ import { appendRenewSettlement, appendScopeTerms, captureRenewSeal, captureSeal, findOpenArc, getFence, getMaxArc, receiptsAfterFence } from "./seal.js";
10
7
  import { deriveContractState, isTerminalState } from "./status/lifecycle.js";
11
8
  import { commissionTarget, latestBase } from "./status/drift.js";
12
- import { findContractWorktreePath } from "./worktree-path.js";
9
+ import { findContractWorktreePath, findRegisteredContractWorktreePath, stableRepoRoot } from "./worktree-path.js";
13
10
  import { getCurrentBranch, requireGitRepository } from "../git/branches.js";
11
+ import { assertCleanTrackedWorkingTree, getUnmergedPaths, hasActiveRebase } from "../git/worktree.js";
12
+ import { createRecoveryRef, deleteRecoveryRef } from "../git/refs.js";
14
13
  import { resolveContractAddress, withResolvedAddress } from "./addressing.js";
15
14
  import { ACTOR_IDENTITY } from "../keiyaku.js";
16
15
  import { persistResponseHistory } from "./transcripts.js";
16
+ import { convergeRenewRecoverySession, assertNoRenewRecoverySession, removeRenewRecoverySession, writeRenewRecoverySession, } from "./renew-session.js";
17
17
  function assertOperable(contractId, entries) {
18
18
  const state = deriveContractState(entries);
19
19
  if (state.state === "corrupt") {
@@ -43,15 +43,14 @@ async function resolveCommitOrNull(cwd, rev) {
43
43
  throw wrapGitError(`rev-parse ${rev}`, error, cwd);
44
44
  }
45
45
  }
46
- async function renderUpdatedContract(ledgerCwd, renderCwd, contractId) {
47
- const ledger = await readLedger(ledgerCwd, contractId);
48
- if (!ledger) {
49
- throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger disappeared before render`);
50
- }
51
- await fs.writeFile(path.join(renderCwd, KEIYAKU_FILE), renderContractView({ id: contractId, entries: ledger.entries }), "utf8");
46
+ const RENEW_RECOVERY_REF_PREFIX = "refs/keiyaku/recovery/renew";
47
+ function renewRecoveryRef(contractId, oldHead) {
48
+ return `${RENEW_RECOVERY_REF_PREFIX}/${contractId}/${oldHead}`;
52
49
  }
53
- async function rewriteBranch(cwd, newBase, oldBase, branch) {
50
+ export async function rewriteRenewBranch(input) {
51
+ const { cwd, contractId, oldHead, recoveryRef, newBase, oldBase, branch, preserveConflict } = input;
54
52
  const git = createGit(cwd);
53
+ const originalBranch = branch ? await getCurrentBranch(cwd) : undefined;
55
54
  const args = branch
56
55
  ? ["rebase", "--onto", newBase, oldBase, branch]
57
56
  : ["rebase", "--onto", newBase, oldBase];
@@ -59,31 +58,151 @@ async function rewriteBranch(cwd, newBase, oldBase, branch) {
59
58
  await git.raw(args);
60
59
  }
61
60
  catch (error) {
61
+ const isConflict = errorContainsAnyPattern(error, ["CONFLICT", "could not apply", "Resolve all conflicts manually"]);
62
+ let conflictPaths = [];
63
+ let conflictPathDiagnostic;
64
+ if (isConflict) {
65
+ try {
66
+ conflictPaths = await getUnmergedPaths(cwd);
67
+ }
68
+ catch (captureError) {
69
+ conflictPathDiagnostic = asMessage(captureError);
70
+ }
71
+ }
72
+ if (isConflict && preserveConflict) {
73
+ throw new FlowError("RENEW_SESSION_OPEN", `renew recovery session is open for ${contractId}`, {
74
+ cause: error,
75
+ facts: { kind: "renew_session", commission: contractId, nextAction: "resolve-conflicts" },
76
+ });
77
+ }
62
78
  try {
63
79
  await git.raw(["rebase", "--abort"]);
64
80
  }
65
- catch {
66
- // Preserve the rewrite failure after best-effort restoration.
81
+ catch (abortError) {
82
+ throw wrapGitError("rebase --abort", abortError, cwd);
67
83
  }
68
- if (errorContainsAnyPattern(error, ["CONFLICT", "could not apply", "Resolve all conflicts manually"])) {
69
- throw new FlowError("CLOSE_MERGE_CONFLICT", "renew conflict; working tree restored", { cause: error });
84
+ if (originalBranch && originalBranch !== branch) {
85
+ try {
86
+ await git.raw(["switch", originalBranch]);
87
+ }
88
+ catch (switchError) {
89
+ throw wrapGitError(`switch ${originalBranch}`, switchError, cwd);
90
+ }
91
+ }
92
+ if (isConflict) {
93
+ const restoredHead = await resolveCommit(cwd, `keiyaku/${contractId}`);
94
+ if (restoredHead !== oldHead) {
95
+ throw new FlowError("INTERNAL_STATE", `renew abort did not restore keiyaku/${contractId}: expected ${oldHead}, found ${restoredHead}`);
96
+ }
97
+ await assertCleanTrackedWorkingTree(cwd);
98
+ throw new FlowError("CLOSE_MERGE_CONFLICT", "renew conflict", {
99
+ cause: error,
100
+ facts: {
101
+ kind: "renew_conflict",
102
+ contractId,
103
+ oldHead,
104
+ recoveryRef,
105
+ conflictPaths,
106
+ conflictPathCapture: conflictPathDiagnostic
107
+ ? { status: "failed", diagnostic: conflictPathDiagnostic }
108
+ : { status: "captured" },
109
+ workspaceRestored: true,
110
+ ledgerWrites: false,
111
+ },
112
+ });
70
113
  }
71
114
  throw wrapGitError(`renew ${branch ?? "current branch"}`, error, cwd);
72
115
  }
73
116
  }
74
- function assertNoInFlightProjection(cwd, contractId, nowMs) {
75
- const board = readProjectionStatusBoard(cwd, nowMs);
76
- const unsafe = new Set(["out", "minting", "startup-timeout", "unknown"]);
77
- if (!board?.rows.some((row) => unsafe.has(row.state)))
117
+ async function assertNoInFlightProjection(repositoryRoot, contractId, deliveryWorktree, nowMs) {
118
+ if (!await hasStrandableProjectionGeneration({
119
+ cwd: repositoryRoot,
120
+ commissionId: contractId,
121
+ deliveryWorktree,
122
+ nowMs,
123
+ }))
78
124
  return;
79
- throw new FlowError("INTERNAL_STATE", `akuma still out on ${contractId}'s worktree; rewriting under it would strand its work`, { hints: ["keiyaku status — watch for the akuma to land, then renew"] });
125
+ throw new FlowError("INTERNAL_STATE", `akuma still out on ${contractId}'s worktree; rewriting under it would strand its work`, { facts: { kind: "projection_in_flight", contractId } });
80
126
  }
81
127
  function looseCommitError(contractId, receipts) {
82
- return new FlowError("NO_OPEN_ARC", `${receipts.length} commits after fence have no arc to receipt them`, {
83
- hints: [`keiyaku @${contractId} arc — opens a new arc to receipt them, then renew`],
128
+ return new FlowError("NO_OPEN_ARC", `${receipts.length} commits after fence have no arc to receipt them`, { facts: { kind: "loose_commits", contractId, nextVerb: "renew" } });
129
+ }
130
+ async function mergeBase(cwd, left, right) {
131
+ const git = createGit(cwd);
132
+ try {
133
+ return (await git.raw(["merge-base", left, right])).trim();
134
+ }
135
+ catch (error) {
136
+ throw wrapGitError(`merge-base ${left} ${right}`, error, cwd);
137
+ }
138
+ }
139
+ async function assertRenewCoordinates(input) {
140
+ const fence = getFence(input.entries);
141
+ let branchBase;
142
+ let fenceBase;
143
+ try {
144
+ [branchBase, fenceBase] = await Promise.all([
145
+ mergeBase(input.cwd, input.oldHead, input.targetHead),
146
+ mergeBase(input.cwd, fence, input.oldHead),
147
+ ]);
148
+ }
149
+ catch (error) {
150
+ throw new FlowError("RENEW_COORDINATE_DRIFT", `renew coordinates for ${input.contractId} are detached from the ledger`, {
151
+ cause: error,
152
+ facts: { kind: "renew_coordinate_drift", commission: input.contractId, oldBase: input.oldBase, oldHead: input.oldHead, fence, targetHead: input.targetHead },
153
+ });
154
+ }
155
+ if (branchBase === input.oldBase && fenceBase === fence)
156
+ return;
157
+ throw new FlowError("RENEW_COORDINATE_DRIFT", `renew coordinates for ${input.contractId} drifted from the ledger before scope audit`, {
158
+ facts: { kind: "renew_coordinate_drift", commission: input.contractId, oldBase: input.oldBase, oldHead: input.oldHead, fence, targetHead: input.targetHead },
84
159
  });
85
160
  }
161
+ async function finishRenew(input) {
162
+ const capture = input.capture === undefined
163
+ ? await captureSeal(input.repositoryRoot, input.entries, input.oldHead)
164
+ : input.capture;
165
+ const settlement = await appendRenewSettlement({
166
+ cwd: input.repositoryRoot,
167
+ contractId: input.contractId,
168
+ expectedLedgerHead: input.ledgerHead,
169
+ capture,
170
+ oldBase: input.oldBase,
171
+ newBase: input.newBase,
172
+ oldHead: input.oldHead,
173
+ newHead: input.newHead,
174
+ actor: input.actor,
175
+ nowMs: input.nowMs,
176
+ });
177
+ await input.afterLedgerCas?.();
178
+ await refreshContractView({
179
+ ledgerCwd: input.repositoryRoot,
180
+ renderCwd: input.rewriteCwd,
181
+ contractId: input.contractId,
182
+ });
183
+ const recoveryCleanup = await deleteRecoveryRef(input.repositoryRoot, input.recoveryRef, input.oldHead);
184
+ await removeRenewRecoverySession(input.repositoryRoot, input.contractId);
185
+ return {
186
+ contractId: input.contractId,
187
+ oldBase: input.oldBase,
188
+ newBase: input.newBase,
189
+ oldHead: input.oldHead,
190
+ newHead: input.newHead,
191
+ ledgerHead: settlement.ledgerHead,
192
+ alreadyFresh: false,
193
+ sealed: settlement.sealed,
194
+ recoveryCleanup,
195
+ };
196
+ }
86
197
  export async function renewContract(input) {
198
+ const repositoryRoot = await stableRepoRoot(input.cwd);
199
+ const worktreePath = await findContractWorktreePath(repositoryRoot, input.contractId);
200
+ const rewriteCwd = worktreePath ?? input.cwd;
201
+ await assertNoRenewRecoverySession(repositoryRoot, input.contractId);
202
+ if (input.resolveConflicts && !worktreePath) {
203
+ throw new FlowError("INTERNAL_STATE", `renew --resolve requires ${input.contractId}'s registered contract worktree`);
204
+ }
205
+ await assertCleanTrackedWorkingTree(rewriteCwd);
87
206
  const ledger = await readLedger(input.cwd, input.contractId);
88
207
  if (!ledger) {
89
208
  throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} not found or not active`);
@@ -102,12 +221,35 @@ export async function renewContract(input) {
102
221
  throw new FlowError("INTERNAL_STATE", "ledger must contain bind entry");
103
222
  const branch = `keiyaku/${input.contractId}`;
104
223
  const oldHead = await resolveCommit(input.cwd, branch);
105
- const capture = await captureSeal(input.cwd, ledger.entries, oldHead, input.waivePaths);
224
+ await assertRenewCoordinates({
225
+ cwd: repositoryRoot,
226
+ contractId: input.contractId,
227
+ oldBase,
228
+ oldHead,
229
+ targetHead,
230
+ entries: ledger.entries,
231
+ });
106
232
  if (getMaxArc(ledger.entries) > 0 && !findOpenArc(ledger.entries)) {
107
233
  const loose = await receiptsAfterFence(input.cwd, ledger.entries, oldHead);
108
234
  if (loose.length > 0)
109
235
  throw looseCommitError(input.contractId, loose);
110
236
  }
237
+ if (oldBase !== targetHead) {
238
+ const deliveryWorktree = worktreePath ?? repositoryRoot;
239
+ await assertNoInFlightProjection(repositoryRoot, input.contractId, deliveryWorktree, input.nowMs);
240
+ }
241
+ await appendScopeTerms({
242
+ cwd: repositoryRoot,
243
+ renderCwd: rewriteCwd,
244
+ contractId: input.contractId,
245
+ patterns: input.appendScope,
246
+ actor: input.actor,
247
+ nowMs: input.nowMs,
248
+ });
249
+ const currentLedger = input.appendScope?.length ? await readLedger(repositoryRoot, input.contractId) : ledger;
250
+ if (!currentLedger)
251
+ throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} disappeared while appending scope`);
252
+ const capture = await captureSeal(input.cwd, currentLedger.entries, oldHead);
111
253
  if (oldBase === targetHead) {
112
254
  return {
113
255
  contractId: input.contractId,
@@ -115,54 +257,227 @@ export async function renewContract(input) {
115
257
  newBase: targetHead,
116
258
  oldHead,
117
259
  newHead: oldHead,
118
- ledgerHead: ledger.head,
260
+ ledgerHead: currentLedger.head,
119
261
  alreadyFresh: true,
120
262
  sealed: null,
263
+ recoveryCleanup: null,
121
264
  };
122
265
  }
123
- const worktreePath = await findContractWorktreePath(input.cwd, input.contractId);
124
- const rewriteCwd = worktreePath ?? input.cwd;
125
- assertNoInFlightProjection(rewriteCwd, input.contractId, input.nowMs);
126
- await rewriteBranch(rewriteCwd, targetHead, oldBase, worktreePath ? undefined : branch);
127
- const newHead = await resolveCommit(input.cwd, branch);
128
- const sealed = await sealCurrentArc({
129
- cwd: input.cwd,
130
- renderCwd: rewriteCwd,
131
- contractId: input.contractId,
132
- sealedBy: "renew",
133
- nowMs: input.nowMs,
134
- capture: capture ? { ...capture, newFence: newHead } : null,
135
- });
136
- const at = new Date(input.nowMs).toISOString();
137
- const result = await appendWithRetry(input.cwd, activeLedgerRef(input.contractId), (_head, entries) => {
138
- assertOperable(input.contractId, entries);
139
- if (latestBase(entries) !== oldBase) {
140
- throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} changed while renewing`);
266
+ const recoveryRef = renewRecoveryRef(input.contractId, oldHead);
267
+ await createRecoveryRef(input.cwd, recoveryRef, oldHead);
268
+ if (input.resolveConflicts) {
269
+ await writeRenewRecoverySession(repositoryRoot, {
270
+ commission: input.contractId,
271
+ oldBase,
272
+ oldHead,
273
+ newBase: targetHead,
274
+ recoveryRef,
275
+ });
276
+ }
277
+ try {
278
+ await rewriteRenewBranch({
279
+ cwd: rewriteCwd,
280
+ contractId: input.contractId,
281
+ oldHead,
282
+ recoveryRef,
283
+ newBase: targetHead,
284
+ oldBase,
285
+ branch: worktreePath ? undefined : branch,
286
+ preserveConflict: input.resolveConflicts,
287
+ });
288
+ }
289
+ catch (error) {
290
+ if (input.resolveConflicts && !(error instanceof FlowError && error.code === "RENEW_SESSION_OPEN")) {
291
+ await removeRenewRecoverySession(repositoryRoot, input.contractId);
141
292
  }
142
- return {
143
- v: 1,
144
- kind: "renew",
145
- contract: input.contractId,
146
- at,
147
- actor: input.actor,
148
- data: { oldBase, newBase: targetHead, oldHead, newHead },
149
- };
150
- });
151
- if (!result.ok) {
152
- throw new FlowError("INTERNAL_STATE", `failed to append renew for ${input.contractId}: ${result.reason}`);
293
+ throw error;
153
294
  }
154
- await renderUpdatedContract(input.cwd, rewriteCwd, input.contractId);
155
- return {
295
+ const newHead = await resolveCommit(input.cwd, branch);
296
+ return await finishRenew({
297
+ repositoryRoot,
298
+ rewriteCwd,
299
+ ledgerHead: currentLedger.head,
300
+ entries: currentLedger.entries,
156
301
  contractId: input.contractId,
157
302
  oldBase,
158
- newBase: targetHead,
159
303
  oldHead,
304
+ newBase: targetHead,
160
305
  newHead,
161
- ledgerHead: result.head,
306
+ recoveryRef,
307
+ actor: input.actor,
308
+ nowMs: input.nowMs,
309
+ capture,
310
+ afterLedgerCas: input.afterLedgerCas,
311
+ });
312
+ }
313
+ async function revListRange(cwd, range) {
314
+ const git = createGit(cwd);
315
+ try {
316
+ return parseRevListOutput(await git.raw(["rev-list", "--reverse", range]));
317
+ }
318
+ catch (error) {
319
+ throw wrapGitError(`rev-list ${range}`, error, cwd);
320
+ }
321
+ }
322
+ async function assertRecoveryFacts(repositoryRoot, contractId, session) {
323
+ if (session.commission !== contractId) {
324
+ throw new FlowError("INTERNAL_STATE", `renew recovery session belongs to ${session.commission}, not ${contractId}`);
325
+ }
326
+ const rewriteCwd = await findRegisteredContractWorktreePath(repositoryRoot, contractId);
327
+ if (!rewriteCwd)
328
+ throw new FlowError("INTERNAL_STATE", `registered contract worktree disappeared for ${contractId}`);
329
+ const ledger = await readLedger(repositoryRoot, contractId);
330
+ if (!ledger)
331
+ throw new FlowError("INTERNAL_STATE", `contract ${contractId} not found or not active`);
332
+ const savedHead = await resolveCommit(repositoryRoot, session.recoveryRef);
333
+ if (savedHead !== session.oldHead || latestBase(ledger.entries) !== session.oldBase) {
334
+ throw new FlowError("RENEW_SESSION_OPEN", `renew recovery session facts no longer match the owned rewrite for ${contractId}`, {
335
+ facts: { kind: "renew_session", commission: contractId, nextAction: "abort" },
336
+ });
337
+ }
338
+ return { ledger, rewriteCwd };
339
+ }
340
+ async function resultFromSpentSession(repositoryRoot, spent) {
341
+ const seal = spent.seal;
342
+ const sealed = seal ? {
343
+ ...seal.data,
344
+ scopeViolationEvidence: [],
345
+ ledgerHead: await resolveCommit(repositoryRoot, `${spent.ledger.head}^`),
346
+ } : null;
347
+ return {
348
+ contractId: spent.session.commission,
349
+ ...spent.renew.data,
350
+ ledgerHead: spent.ledger.head,
162
351
  alreadyFresh: false,
163
352
  sealed,
353
+ recoveryCleanup: spent.recoveryCleanup,
164
354
  };
165
355
  }
356
+ export async function continueRenewContract(input) {
357
+ const repositoryRoot = await stableRepoRoot(input.cwd);
358
+ const sessionState = await convergeRenewRecoverySession(repositoryRoot, input.contractId);
359
+ if (sessionState.state === "spent")
360
+ return await resultFromSpentSession(repositoryRoot, sessionState);
361
+ if (sessionState.state === "none") {
362
+ throw new FlowError("RENEW_SESSION_NOT_FOUND", `no renew recovery session is open for ${input.contractId}`);
363
+ }
364
+ const session = sessionState.session;
365
+ const { ledger, rewriteCwd } = await assertRecoveryFacts(repositoryRoot, input.contractId, session);
366
+ const delivery = await revListRange(repositoryRoot, `${session.oldBase}..${session.oldHead}`);
367
+ if (await hasActiveRebase(rewriteCwd)) {
368
+ const stoppedAt = await resolveCommitOrNull(rewriteCwd, "REBASE_HEAD");
369
+ if (!stoppedAt) {
370
+ throw new FlowError("RENEW_SESSION_OPEN", `owned rebase state has no stopped receipt for ${input.contractId}`, {
371
+ facts: { kind: "renew_session", commission: input.contractId, nextAction: "abort" },
372
+ });
373
+ }
374
+ const stoppedIndex = delivery.indexOf(stoppedAt);
375
+ const rewrittenPrefix = await revListRange(rewriteCwd, `${session.newBase}..HEAD`);
376
+ if (stoppedIndex < 0 || rewrittenPrefix.length !== stoppedIndex) {
377
+ throw new FlowError("RENEW_SESSION_OPEN", `loose commits do not belong to the owned renew rebase for ${input.contractId}`, {
378
+ facts: { kind: "renew_session", commission: input.contractId, nextAction: "continue-or-abort" },
379
+ });
380
+ }
381
+ const continued = await runGitProcess(rewriteCwd, ["rebase", "--continue"], {
382
+ env: { GIT_EDITOR: "true" },
383
+ });
384
+ if (continued.status !== 0) {
385
+ const error = continued.error ?? { message: "git rebase --continue failed", stderr: continued.stderr, stdout: continued.stdout };
386
+ if (errorContainsAnyPattern(error, ["CONFLICT", "could not apply", "Resolve all conflicts manually"])) {
387
+ throw new FlowError("RENEW_SESSION_OPEN", `renew recovery session is open for ${input.contractId}`, {
388
+ cause: error,
389
+ facts: { kind: "renew_session", commission: input.contractId, nextAction: "resolve-conflicts" },
390
+ });
391
+ }
392
+ throw wrapGitError("rebase --continue", error, rewriteCwd);
393
+ }
394
+ }
395
+ const newHead = await resolveCommit(repositoryRoot, `keiyaku/${input.contractId}`);
396
+ const rewritten = await revListRange(repositoryRoot, `${session.newBase}..${newHead}`);
397
+ if (await mergeBase(repositoryRoot, session.newBase, newHead) !== session.newBase || rewritten.length !== delivery.length) {
398
+ throw new FlowError("RENEW_SESSION_OPEN", `rewritten delivery no longer corresponds to the saved renew receipts for ${input.contractId}`, {
399
+ facts: { kind: "renew_session", commission: input.contractId, nextAction: "abort" },
400
+ });
401
+ }
402
+ await appendScopeTerms({
403
+ cwd: repositoryRoot,
404
+ renderCwd: rewriteCwd,
405
+ contractId: input.contractId,
406
+ patterns: input.appendScope,
407
+ actor: input.actor,
408
+ nowMs: input.nowMs,
409
+ });
410
+ const currentLedger = input.appendScope?.length ? await readLedger(repositoryRoot, input.contractId) : ledger;
411
+ if (!currentLedger)
412
+ throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} disappeared while appending scope`);
413
+ const capture = await captureRenewSeal({
414
+ cwd: repositoryRoot,
415
+ entries: currentLedger.entries,
416
+ receiptHead: session.oldHead,
417
+ contentBase: session.newBase,
418
+ contentHead: newHead,
419
+ });
420
+ return await finishRenew({
421
+ repositoryRoot,
422
+ rewriteCwd,
423
+ ledgerHead: currentLedger.head,
424
+ entries: currentLedger.entries,
425
+ contractId: input.contractId,
426
+ oldBase: session.oldBase,
427
+ oldHead: session.oldHead,
428
+ newBase: session.newBase,
429
+ newHead,
430
+ recoveryRef: session.recoveryRef,
431
+ actor: input.actor,
432
+ nowMs: input.nowMs,
433
+ capture,
434
+ afterLedgerCas: input.afterLedgerCas,
435
+ });
436
+ }
437
+ export async function abortRenewContract(input) {
438
+ const repositoryRoot = await stableRepoRoot(input.cwd);
439
+ const sessionState = await convergeRenewRecoverySession(repositoryRoot, input.contractId);
440
+ if (sessionState.state !== "live") {
441
+ throw new FlowError("RENEW_SESSION_NOT_FOUND", `no renew recovery session is open for ${input.contractId}`);
442
+ }
443
+ const session = sessionState.session;
444
+ const { rewriteCwd } = await assertRecoveryFacts(repositoryRoot, input.contractId, session);
445
+ const git = createGit(rewriteCwd);
446
+ if (await hasActiveRebase(rewriteCwd)) {
447
+ try {
448
+ await git.raw(["rebase", "--abort"]);
449
+ }
450
+ catch (error) {
451
+ throw wrapGitError("rebase --abort", error, rewriteCwd);
452
+ }
453
+ }
454
+ let branch;
455
+ try {
456
+ branch = (await git.raw(["symbolic-ref", "--quiet", "--short", "HEAD"])).trim();
457
+ }
458
+ catch {
459
+ branch = undefined;
460
+ }
461
+ const expectedBranch = `keiyaku/${input.contractId}`;
462
+ if (branch !== expectedBranch) {
463
+ try {
464
+ await git.raw(["switch", expectedBranch]);
465
+ }
466
+ catch (error) {
467
+ throw wrapGitError(`switch ${expectedBranch}`, error, rewriteCwd);
468
+ }
469
+ }
470
+ try {
471
+ await git.raw(["reset", "--hard", session.oldHead]);
472
+ }
473
+ catch (error) {
474
+ throw wrapGitError(`reset --hard ${session.recoveryRef}`, error, rewriteCwd);
475
+ }
476
+ await assertCleanTrackedWorkingTree(rewriteCwd);
477
+ await removeRenewRecoverySession(repositoryRoot, input.contractId);
478
+ const recoveryCleanup = await deleteRecoveryRef(repositoryRoot, session.recoveryRef, session.oldHead);
479
+ return { contractId: input.contractId, oldHead: session.oldHead, recoveryCleanup };
480
+ }
166
481
  export async function renewKeiyaku(input) {
167
482
  await requireGitRepository(input.cwd, "renew");
168
483
  const address = input.address ?? await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
@@ -173,48 +488,79 @@ export async function renewKeiyaku(input) {
173
488
  contractId,
174
489
  actor: ACTOR_IDENTITY,
175
490
  nowMs: Date.now(),
176
- waivePaths: input.waivePaths,
491
+ appendScope: input.appendScope,
492
+ resolveConflicts: input.resolveConflicts,
177
493
  });
178
- const currentBranch = await getCurrentBranch(input.cwd);
179
- const baseBranch = address.target.branch.slice("refs/heads/".length);
180
- const diff = renewed.sealed?.incrementalDiff ?? "nothing sealed";
181
- const summary = renewed.alreadyFresh
182
- ? `Contract ${contractId} is already fresh; nothing touched.`
183
- : `Contract ${contractId} renewed onto ${renewed.newBase}.`;
184
- let responsePath;
185
- let artifactId;
186
- try {
187
- const persisted = await persistResponseHistory({
188
- cwd: input.cwd,
189
- tool: "renew",
190
- provenance: { authority: { kind: "repository" }, binding: address.binding, evidenceCwd: input.cwd },
191
- title: contractId,
192
- oldBase: renewed.oldBase,
193
- newBase: renewed.newBase,
194
- oldHead: renewed.oldHead,
195
- newHead: renewed.newHead,
196
- ledgerCommit: renewed.ledgerHead,
197
- summary,
198
- diff,
199
- ...(renewed.sealed ? { sealed: renewed.sealed } : {}),
200
- });
201
- responsePath = persisted.responsePath;
202
- artifactId = persisted.artifactId;
203
- }
204
- catch {
205
- responsePath = undefined;
206
- }
494
+ return await buildRenewOutcome(input.cwd, address, renewed);
495
+ });
496
+ }
497
+ async function buildRenewOutcome(cwd, address, renewed) {
498
+ const contractId = address.binding.commissionId;
499
+ const currentBranch = await getCurrentBranch(cwd);
500
+ const baseBranch = address.target.branch.slice("refs/heads/".length);
501
+ const summary = renewed.alreadyFresh
502
+ ? `Contract ${contractId} is already fresh; nothing touched.`
503
+ : `Contract ${contractId} renewed onto ${renewed.newBase}.`;
504
+ const cleanupWarnings = renewed.recoveryCleanup?.status === "retained"
505
+ ? [`Renew succeeded, but recovery ref ${renewed.recoveryCleanup.ref} was retained: ${renewed.recoveryCleanup.diagnostic}`]
506
+ : [];
507
+ let responsePath;
508
+ let artifactId;
509
+ try {
510
+ const persisted = await persistResponseHistory({
511
+ cwd,
512
+ tool: "renew",
513
+ provenance: { authority: { kind: "repository" }, binding: address.binding, evidenceCwd: cwd },
514
+ title: contractId,
515
+ oldBase: renewed.oldBase,
516
+ newBase: renewed.newBase,
517
+ oldHead: renewed.oldHead,
518
+ newHead: renewed.newHead,
519
+ ledgerCommit: renewed.ledgerHead,
520
+ summary,
521
+ emptyDiffLabel: "nothing sealed",
522
+ ...(renewed.sealed ? { sealed: renewed.sealed } : {}),
523
+ });
524
+ responsePath = persisted.responsePath;
525
+ artifactId = persisted.artifactId;
526
+ }
527
+ catch {
528
+ responsePath = undefined;
529
+ }
530
+ return {
531
+ status: "success",
532
+ ...renewed,
533
+ currentBranch,
534
+ baseBranch,
535
+ // CLI/render synthesizes public face bytes from sealed typed facts.
536
+ diff: "",
537
+ sealed: renewed.sealed ?? undefined,
538
+ summary,
539
+ ...(cleanupWarnings.length > 0 ? { meta: { warnings: cleanupWarnings } } : {}),
540
+ responsePath,
541
+ artifactId,
542
+ address,
543
+ };
544
+ }
545
+ export async function continueRenewKeiyaku(input) {
546
+ await requireGitRepository(input.cwd, "renew --continue");
547
+ return await withResolvedAddress(input.address, async () => buildRenewOutcome(input.cwd, input.address, await continueRenewContract({
548
+ cwd: input.cwd,
549
+ contractId: input.address.binding.commissionId,
550
+ actor: ACTOR_IDENTITY,
551
+ nowMs: Date.now(),
552
+ appendScope: input.appendScope,
553
+ })));
554
+ }
555
+ export async function abortRenewKeiyaku(input) {
556
+ await requireGitRepository(input.cwd, "renew --abort");
557
+ return await withResolvedAddress(input.address, async () => {
558
+ const result = await abortRenewContract({ cwd: input.cwd, contractId: input.address.binding.commissionId });
207
559
  return {
208
560
  status: "success",
209
- ...renewed,
210
- currentBranch,
211
- baseBranch,
212
- diff,
213
- sealed: renewed.sealed ?? undefined,
214
- summary,
215
- responsePath,
216
- artifactId,
217
- address,
561
+ ...result,
562
+ address: input.address,
563
+ summary: `Renew recovery for ${result.contractId} aborted; delivery restored to ${result.oldHead}.`,
218
564
  };
219
565
  });
220
566
  }