@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.
- package/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +14 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +26 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +68 -5
- package/build/agents/harness/projection.js +179 -124
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +82 -53
- package/build/agents/providers/codex-app-server/events.js +90 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/events.js +4 -3
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +10 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +1 -1
- package/build/cli/commands/akuma/list/meta-ls.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma/view/meta.js +1 -1
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/amend/meta.js +4 -4
- package/build/cli/commands/contract/arc/handler.js +8 -2
- package/build/cli/commands/contract/arc/meta.js +4 -4
- package/build/cli/commands/contract/audit/handler.js +16 -0
- package/build/cli/commands/contract/audit/meta.js +16 -0
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +44 -8
- package/build/cli/commands/contract/catalog.js +2 -0
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/forfeit/meta.js +1 -1
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/log/meta.js +1 -1
- package/build/cli/commands/contract/petition/handler.js +5 -8
- package/build/cli/commands/contract/petition/meta.js +6 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +6 -5
- package/build/cli/commands/metadata.js +59 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/call/meta.js +4 -1
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/kill/meta.js +1 -1
- package/build/cli/commands/projection/revive/meta.js +4 -1
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/status/meta.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/tell/meta.js +4 -1
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +8 -3
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/install/meta.js +1 -1
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/skills/skills/meta.js +1 -1
- package/build/cli/commands/system/completion/meta.js +1 -1
- package/build/cli/commands/system/dump-env/meta.js +1 -1
- package/build/cli/commands/system/guide/meta.js +1 -1
- package/build/cli/commands/task/add/handler.js +7 -15
- package/build/cli/commands/task/add/meta.js +4 -1
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/doctor/meta.js +1 -1
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/ls/handler.js +12 -8
- package/build/cli/commands/task/ls/meta.js +3 -3
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/task/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +6 -11
- package/build/cli/commands/task/update/meta.js +4 -1
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +37 -6
- package/build/cli/help.js +7 -14
- package/build/cli/index.js +112 -154
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/output-stream-error-policy.js +19 -5
- package/build/cli/parse-flags.js +33 -7
- package/build/cli/parse-metadata.js +3 -9
- package/build/cli/parse-selectors.js +2 -1
- package/build/cli/parse.js +35 -5
- package/build/cli/projection-address.js +12 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/audit.js +121 -0
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +58 -13
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +15 -6
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +56 -23
- package/build/cli/render/success-response.js +78 -0
- package/build/cli/render/task.js +66 -57
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +63 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +68 -38
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +3 -1
- package/build/config/env.js +3 -0
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +61 -18
- package/build/core/arc.js +33 -73
- package/build/core/audit.js +650 -0
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +22 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +22 -6
- package/build/core/draft.js +139 -19
- package/build/core/entry.js +3 -4
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/lex.js +2 -1
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +41 -52
- package/build/core/projection/generation/model.js +63 -2
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
- package/build/core/projection/generation/store.js +3 -3
- package/build/core/projection/generation/transitions.js +19 -3
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
- package/build/core/projection/projection-terminal-failure.js +106 -0
- package/build/core/projection/projection-wait.js +275 -0
- package/build/core/projection/projection-wake.js +227 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +448 -102
- package/build/core/scope.js +272 -68
- package/build/core/seal.js +165 -40
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
- package/build/core/{petition.js → settlement/petition.js} +21 -12
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +288 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/settlement/verification.js +59 -0
- package/build/core/status/board.js +62 -41
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +6 -2
- package/build/core/task/board.js +41 -4
- package/build/core/task/commands.js +45 -28
- package/build/core/task/document.js +5 -0
- package/build/core/task/index.js +12 -0
- package/build/core/task/model.js +8 -1
- package/build/core/task/query.js +172 -0
- package/build/core/task/settlement-git.js +265 -74
- package/build/core/task/settlement-policy.js +67 -29
- package/build/core/task/source-board.js +1 -0
- package/build/core/task/task-contract.js +444 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +7 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +83 -39
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/diff/parsers.js +23 -13
- package/build/git/diff/structured.js +127 -0
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +9 -9
- package/build/keiyaku.js +2 -36
- package/build/telemetry/logger.js +4 -2
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +5 -4
- package/skills/keiyaku-akuma/SKILL.md +25 -11
- package/skills/keiyaku-task/SKILL.md +17 -8
- package/skills/keiyaku-workflow/SKILL.md +58 -9
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
package/build/core/renew.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
|
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
|
-
|
|
81
|
+
catch (abortError) {
|
|
82
|
+
throw wrapGitError("rebase --abort", abortError, cwd);
|
|
67
83
|
}
|
|
68
|
-
if (
|
|
69
|
-
|
|
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(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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`, {
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
260
|
+
ledgerHead: currentLedger.head,
|
|
119
261
|
alreadyFresh: true,
|
|
120
262
|
sealed: null,
|
|
263
|
+
recoveryCleanup: null,
|
|
121
264
|
};
|
|
122
265
|
}
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
491
|
+
appendScope: input.appendScope,
|
|
492
|
+
resolveConflicts: input.resolveConflicts,
|
|
177
493
|
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
...
|
|
210
|
-
|
|
211
|
-
|
|
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
|
}
|