@astrosheep/keiyaku 2.9.8 → 2.9.10
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/README.md +50 -182
- package/build/.tsbuildinfo +1 -1
- package/build/agents/harness/control-types.js +18 -1
- package/build/agents/harness/index.js +2 -0
- package/build/agents/harness/outcome-error.js +81 -0
- package/build/agents/harness/projection.js +10 -7
- package/build/agents/harness/router.js +5 -1
- package/build/agents/providers/claude-agent-sdk/adapter.js +18 -4
- package/build/agents/providers/claude-agent-sdk/registration.js +11 -1
- package/build/agents/providers/claude-agent-sdk/session.js +19 -5
- package/build/agents/providers/codex-app-server/adapter.js +11 -6
- package/build/agents/providers/codex-app-server/events.js +67 -6
- package/build/agents/providers/codex-app-server/registration.js +11 -1
- package/build/agents/providers/opencode-sdk/adapter.js +8 -1
- package/build/agents/providers/opencode-sdk/events.js +24 -2
- package/build/agents/providers/opencode-sdk/registration.js +11 -1
- package/build/agents/providers/pi/checkpoint.js +9 -1
- package/build/agents/providers/pi/events.js +2 -0
- package/build/agents/providers/pi/registration.js +14 -1
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +3 -3
- package/build/cli/commands/akuma/catalog.js +2 -2
- package/build/cli/commands/akuma/{view → show}/handler.js +5 -5
- package/build/cli/commands/akuma/{view → show}/meta.js +3 -3
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +5 -4
- package/build/cli/commands/contract/arc/handler.js +5 -4
- package/build/cli/commands/contract/audit/handler.js +2 -2
- package/build/cli/commands/contract/bind/handler.js +12 -3
- package/build/cli/commands/contract/bind/meta.js +45 -15
- package/build/cli/commands/contract/forfeit/handler.js +9 -5
- package/build/cli/commands/contract/log/handler.js +2 -2
- package/build/cli/commands/contract/petition/handler.js +34 -7
- package/build/cli/commands/contract/renew/handler.js +7 -7
- package/build/cli/commands/contract/renew/meta.js +3 -3
- package/build/cli/commands/metadata.js +10 -6
- package/build/cli/commands/projection/call/meta.js +1 -1
- package/build/cli/commands/projection/catalog.js +2 -0
- package/build/cli/commands/projection/history/handler.js +21 -0
- package/build/cli/commands/projection/history/meta.js +9 -0
- package/build/cli/commands/projection/shared.js +3 -4
- package/build/cli/commands/projection/status/handler.js +3 -3
- package/build/cli/commands/projection/wait/handler.js +20 -11
- package/build/cli/commands/task/add/handler.js +14 -5
- package/build/cli/commands/task/add/meta.js +2 -2
- package/build/cli/commands/task/catalog.js +4 -0
- package/build/cli/commands/task/done/handler.js +1 -4
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/hold/handler.js +3 -0
- package/build/cli/commands/task/hold/meta.js +8 -0
- package/build/cli/commands/task/log/handler.js +1 -1
- package/build/cli/commands/task/log/meta.js +2 -2
- package/build/cli/commands/task/resume/handler.js +3 -0
- package/build/cli/commands/task/resume/meta.js +8 -0
- package/build/cli/commands/task/shared.js +39 -14
- package/build/cli/commands/task/show/handler.js +1 -1
- package/build/cli/commands/task/show/meta.js +1 -1
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +1 -4
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +11 -3
- package/build/cli/commands/task/update/meta.js +3 -3
- package/build/cli/completion.js +3 -2
- package/build/cli/flags.js +51 -14
- package/build/cli/help.js +4 -1
- package/build/cli/index.js +40 -25
- package/build/cli/parse-flags.js +40 -7
- package/build/cli/parse-metadata.js +5 -2
- package/build/cli/parse-selectors.js +2 -3
- package/build/cli/parse.js +40 -6
- package/build/cli/projection-address.js +12 -10
- package/build/cli/render/amendment-warning.js +8 -0
- package/build/cli/render/arc.js +6 -2
- package/build/cli/render/audit.js +400 -81
- package/build/cli/render/kanshi.js +242 -79
- package/build/cli/render/lifecycle.js +56 -0
- package/build/cli/render/misc.js +24 -28
- package/build/cli/render/petition.js +5 -0
- package/build/cli/render/projection-activity.js +65 -29
- package/build/cli/render/projection-history.js +64 -0
- package/build/cli/render/shared.js +23 -9
- package/build/cli/render/status.js +13 -35
- package/build/cli/render/task.js +51 -26
- package/build/cli/render/terminal-failure.js +3 -1
- package/build/cli/render/wait.js +45 -69
- package/build/cli/subagent-guard.js +1 -1
- package/build/cli/types.js +1 -1
- package/build/config/env-keys.js +3 -1
- package/build/config/env.js +24 -1
- package/build/config/settings/schema.js +3 -1
- package/build/core/address-carrier.js +89 -0
- package/build/core/addressing.js +255 -196
- package/build/core/amend.js +115 -38
- package/build/core/amendment-criteria.js +17 -0
- package/build/core/amendment-warning.js +10 -0
- package/build/core/arc.js +184 -83
- package/build/core/audit/candidate.js +110 -9
- package/build/core/audit/coordinates.js +120 -65
- package/build/core/audit/evidence.js +19 -23
- package/build/core/audit/facade.js +34 -11
- package/build/core/audit/report.js +5 -5
- package/build/core/bind-reconciliation.js +390 -0
- package/build/core/bind-workspace.js +12 -20
- package/build/core/bind.js +242 -273
- package/build/core/call/call.js +1 -0
- package/build/core/call/context.js +46 -71
- package/build/core/call/prompt.js +6 -3
- package/build/core/context.js +49 -35
- package/build/core/contract-carrier-runtime.js +408 -0
- package/build/core/contract-carrier.js +270 -0
- package/build/core/contract-view.js +33 -27
- package/build/core/contract.js +5 -1
- package/build/core/derived-replay.js +207 -0
- package/build/core/draft.js +125 -57
- package/build/core/forfeit.js +113 -56
- package/build/core/identifier-slug.js +63 -13
- package/build/core/ids.js +4 -4
- package/build/core/lifecycle-history.js +35 -0
- package/build/core/lifecycle-recovery.js +117 -0
- package/build/core/lifecycle-runner.js +377 -0
- package/build/core/log.js +37 -11
- package/build/core/outcome-base.js +181 -0
- package/build/core/process-group.js +139 -0
- package/build/core/projection/generation/database.js +82 -7
- package/build/core/projection/generation/model.js +9 -36
- package/build/core/projection/generation/projection-generation-continuation.js +10 -22
- package/build/core/projection/generation/projection-generation-execution.js +13 -6
- package/build/core/projection/index.js +5 -4
- package/build/core/projection/projection-activity.js +29 -8
- package/build/core/projection/projection-alias.js +23 -10
- package/build/core/projection/projection-core.js +21 -7
- package/build/core/projection/projection-execution-observer.js +91 -39
- package/build/core/projection/projection-history.js +474 -0
- package/build/core/projection/projection-runner-lock.js +12 -0
- package/build/core/projection/projection-status-observation.js +365 -0
- package/build/core/projection/projection-status.js +35 -337
- package/build/core/projection/projection-terminal-failure.js +13 -8
- package/build/core/projection/projection-wait.js +7 -2
- package/build/core/projection/tell/launch-store.js +244 -0
- package/build/core/projection/tell/model.js +3 -3
- package/build/core/projection/tell/store.js +70 -118
- package/build/core/registry.js +22 -87
- package/build/core/renew-build.js +424 -0
- package/build/core/renew-plan.js +239 -0
- package/build/core/renew-rewrite.js +77 -0
- package/build/core/renew.js +295 -520
- package/build/core/repository-ledger/accepted-fold-read.js +19 -0
- package/build/core/repository-ledger/accepted-tail.js +116 -0
- package/build/core/repository-ledger/admission.js +38 -0
- package/build/core/repository-ledger/authoritative-transaction.js +1 -0
- package/build/core/repository-ledger/claim-evidence.js +147 -0
- package/build/core/repository-ledger/codec.js +297 -0
- package/build/core/repository-ledger/current-state-store.js +853 -0
- package/build/core/repository-ledger/fold-repository.js +375 -0
- package/build/core/repository-ledger/fold.js +248 -0
- package/build/core/repository-ledger/git-object-store.js +243 -0
- package/build/core/repository-ledger/history-read.js +15 -0
- package/build/core/repository-ledger/incremental-read.js +153 -0
- package/build/core/repository-ledger/index.js +15 -0
- package/build/core/repository-ledger/inventory-plan.js +75 -0
- package/build/core/repository-ledger/inventory.js +310 -0
- package/build/core/repository-ledger/publication-admission.js +125 -0
- package/build/core/repository-ledger/publication.js +353 -0
- package/build/core/repository-ledger/read-model.js +469 -0
- package/build/core/repository-ledger/transaction-membership.js +78 -0
- package/build/core/repository-ledger/traversal.js +404 -0
- package/build/core/repository-ledger/write-transaction.js +339 -0
- package/build/core/seal.js +168 -161
- package/build/core/settlement/claim-delivery.js +42 -215
- package/build/core/settlement/claim.js +235 -153
- package/build/core/settlement/index.js +4 -4
- package/build/core/settlement/petition-claim-gates.js +52 -33
- package/build/core/settlement/petition-forfeit.js +12 -5
- package/build/core/settlement/petition-head-guard.js +8 -5
- package/build/core/settlement/petition-preview.js +68 -56
- package/build/core/settlement/petition-window.js +50 -0
- package/build/core/settlement/petition.js +252 -131
- package/build/core/settlement/queue-read-model.js +72 -95
- package/build/core/settlement/queue-seat-allocation.js +35 -126
- package/build/core/settlement/queue.js +1 -1
- package/build/core/settlement/settlement.js +172 -80
- package/build/core/settlement/verdict.js +112 -66
- package/build/core/settlement/verification-coordination.js +305 -0
- package/build/core/settlement/verification-supervisor.js +275 -0
- package/build/core/settlement/verification.js +398 -31
- package/build/core/status/board.js +125 -127
- package/build/core/status/lifecycle.js +7 -80
- package/build/core/structured-query.js +23 -0
- package/build/core/target-ref.js +1 -1
- package/build/core/task/board.js +59 -24
- package/build/core/task/commands.js +181 -33
- package/build/core/task/coordinate.js +56 -0
- package/build/core/task/document.js +25 -9
- package/build/core/task/index.js +7 -4
- package/build/core/task/query.js +17 -27
- package/build/core/task/settlement-git.js +164 -179
- package/build/core/task/settlement-policy.js +15 -11
- package/build/core/task/source-board.js +31 -13
- package/build/core/task/task-bind-preparation.js +193 -0
- package/build/core/task/task-contract.js +102 -193
- package/build/core/task/task-file-transaction.js +171 -0
- package/build/core/task/task-git-runtime.js +76 -14
- package/build/core/task/task-git-store.js +68 -169
- package/build/core/task/task-store-repository.js +13 -6
- package/build/core/task/task-worktree.js +6 -33
- package/build/core/task/task.js +1 -1
- package/build/core/task/tree.js +3 -3
- package/build/core/task/validation.js +4 -3
- package/build/core/transcripts.js +93 -1
- package/build/core/worktree-bootstrap.js +44 -36
- package/build/core/worktree-path.js +210 -77
- package/build/flow-error.js +7 -7
- package/build/generated/version.js +2 -2
- package/build/git/core.js +76 -13
- package/build/git/refs.js +168 -46
- package/build/git/streaming-batch.js +73 -13
- package/package.json +1 -1
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +3 -3
- package/skills/keiyaku-task/SKILL.md +4 -2
- package/skills/keiyaku-workflow/SKILL.md +88 -203
- package/build/core/entry.js +0 -305
- package/build/core/ledger-batch.js +0 -194
- package/build/core/ledger.js +0 -84
- package/build/core/projection/leash.js +0 -87
- package/build/core/ref-log.js +0 -119
- package/build/core/renew-session.js +0 -128
- package/build/core/status/ledger-batch.js +0 -1
- package/build/core/status/reconciliation.js +0 -137
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { FlowError } from "../../flow-error.js";
|
|
2
2
|
import { readCurrentContractContext } from "../context.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { deriveContractState } from "../status/lifecycle.js";
|
|
3
|
+
import { convergeContractCarrier, withContractCarrierSession } from "../contract-carrier.js";
|
|
4
|
+
import { createGit } from "../../git/core.js";
|
|
6
5
|
import { getCurrentBranch, requireGitRepository } from "../../git/branches.js";
|
|
6
|
+
import { getLatestCommitHash } from "../../git/staging.js";
|
|
7
7
|
import { readContractLog } from "../log.js";
|
|
8
|
-
import { listRefLogCommits } from "../ref-log.js";
|
|
9
|
-
import { effectiveScope } from "../seal.js";
|
|
10
8
|
import { scopePathEvidence } from "../scope.js";
|
|
11
9
|
import { nextReviewResponseNumber } from "../transcripts.js";
|
|
10
|
+
import { stableRepoRoot } from "../worktree-path.js";
|
|
11
|
+
import { isCompleteLifecycleOutcome } from "../outcome-base.js";
|
|
12
12
|
import { claimContract } from "./claim.js";
|
|
13
|
+
import { assertClaimQueueHead, deriveQueueReadModel } from "./queue.js";
|
|
14
|
+
import { classifyCurrentPetitionWindow } from "./petition-window.js";
|
|
13
15
|
import { buildClaimGatePipeline, } from "./petition-claim-gates.js";
|
|
14
|
-
import {
|
|
16
|
+
import { composeVerificationPlan, contractVerificationDeclarations, resolveVerificationPolicy } from "./verification.js";
|
|
15
17
|
import { forfeitKeiyaku } from "./petition-forfeit.js";
|
|
16
18
|
import { assertHeadUnchanged } from "./petition-head-guard.js";
|
|
17
19
|
import { petitionContract } from "./petition.js";
|
|
@@ -19,10 +21,13 @@ import { verdictContract } from "./verdict.js";
|
|
|
19
21
|
const VERDICT_DENIED_CODE = "VERDICT_DENIED";
|
|
20
22
|
async function resolveClaimGateConfig(cwd) {
|
|
21
23
|
const merged = {
|
|
22
|
-
|
|
24
|
+
repositoryGates: [],
|
|
25
|
+
verificationTimeoutMs: 300_000,
|
|
23
26
|
};
|
|
24
27
|
try {
|
|
25
|
-
|
|
28
|
+
const policy = await resolveVerificationPolicy(cwd);
|
|
29
|
+
merged.repositoryGates = policy.commands;
|
|
30
|
+
merged.verificationTimeoutMs = policy.timeoutMs;
|
|
26
31
|
return merged;
|
|
27
32
|
}
|
|
28
33
|
catch (error) {
|
|
@@ -35,21 +40,34 @@ async function resolveClaimGateConfig(cwd) {
|
|
|
35
40
|
throw error;
|
|
36
41
|
}
|
|
37
42
|
}
|
|
38
|
-
async function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (!ledger) {
|
|
43
|
-
throw new FlowError("INTERNAL_STATE", `contract ${requestedContractId} not found or not active`);
|
|
43
|
+
async function pinnedCloseCandidate(cwd, contractId, signal) {
|
|
44
|
+
return withContractCarrierSession({ cwd, contractId, mode: "observe-only", signal }, async (session) => {
|
|
45
|
+
if (session.target.status !== "available" || !session.pins.delivery.head) {
|
|
46
|
+
throw new FlowError("INTERNAL_STATE", session.target.status === "available" ? `contract ${contractId} delivery ref does not resolve` : session.target.reason);
|
|
44
47
|
}
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
const git = createGit(session.target.root);
|
|
49
|
+
const [head, tree] = await Promise.all([
|
|
50
|
+
git.raw(["rev-parse", "--verify", "HEAD^{commit}"]),
|
|
51
|
+
git.raw(["rev-parse", "--verify", "HEAD^{tree}"]),
|
|
52
|
+
]);
|
|
53
|
+
if (head.trim() !== session.pins.delivery.head) {
|
|
54
|
+
throw new FlowError("INTERNAL_STATE", `contract ${contractId} delivery head changed while petition was being prepared`);
|
|
48
55
|
}
|
|
56
|
+
return { deliveryCwd: session.target.root, candidate: { head: head.trim(), tree: tree.trim() }, contractVerification: contractVerificationDeclarations(session.lifecycle) };
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async function loadCloseContext(cwd, requestedContractId, signal) {
|
|
60
|
+
await requireGitRepository(cwd, "petition");
|
|
61
|
+
if (requestedContractId) {
|
|
62
|
+
const lifecycle = (await convergeContractCarrier({ cwd, contractId: requestedContractId, signal, mode: "observe-only" })).lifecycle;
|
|
63
|
+
const pinned = await pinnedCloseCandidate(cwd, requestedContractId, signal);
|
|
49
64
|
return {
|
|
50
65
|
cwd,
|
|
66
|
+
deliveryCwd: pinned.deliveryCwd,
|
|
67
|
+
verificationCandidate: pinned.candidate,
|
|
68
|
+
contractVerification: pinned.contractVerification,
|
|
51
69
|
keiyakuBranch: `keiyaku/${requestedContractId}`,
|
|
52
|
-
baseBranch: target.
|
|
70
|
+
baseBranch: lifecycle.pins.target.ref.slice("refs/heads/".length),
|
|
53
71
|
contractId: requestedContractId,
|
|
54
72
|
};
|
|
55
73
|
}
|
|
@@ -64,8 +82,12 @@ async function loadCloseContext(cwd, requestedContractId) {
|
|
|
64
82
|
throw new FlowError("NOT_ACTIVE_KEIYAKU_BRANCH", "Current workspace is not addressing an active Keiyaku contract.");
|
|
65
83
|
}
|
|
66
84
|
const keiyakuBranch = await getCurrentBranch(cwd);
|
|
85
|
+
const pinned = await pinnedCloseCandidate(cwd, contractContext.contractId, signal);
|
|
67
86
|
return {
|
|
68
87
|
cwd,
|
|
88
|
+
deliveryCwd: pinned.deliveryCwd,
|
|
89
|
+
verificationCandidate: pinned.candidate,
|
|
90
|
+
contractVerification: pinned.contractVerification,
|
|
69
91
|
keiyakuBranch,
|
|
70
92
|
baseBranch: contractContext.baseBranch,
|
|
71
93
|
contractId: contractContext.contractId,
|
|
@@ -84,30 +106,47 @@ async function throwClaimGateFailure(failure, _input, context, _dependencies) {
|
|
|
84
106
|
});
|
|
85
107
|
}
|
|
86
108
|
async function runClaimGatePipelineOrThrow(input, context, dependencies) {
|
|
87
|
-
const
|
|
109
|
+
const deliveryCwd = context.deliveryCwd ?? context.cwd;
|
|
110
|
+
const verificationCandidate = context.verificationCandidate ?? {
|
|
111
|
+
head: await getLatestCommitHash(deliveryCwd),
|
|
112
|
+
tree: (await createGit(deliveryCwd).raw(["rev-parse", "--verify", "HEAD^{tree}"])).trim(),
|
|
113
|
+
};
|
|
114
|
+
const gateConfig = await dependencies.resolveClaimGateConfig(context.cwd);
|
|
115
|
+
const repositoryGates = gateConfig.repositoryGates ?? gateConfig.verificationCommands ?? [];
|
|
116
|
+
const verificationPlan = composeVerificationPlan({ contract: context.contractVerification ?? [], repositoryGates, timeoutMs: gateConfig.verificationTimeoutMs });
|
|
117
|
+
const coordinationRoot = await stableRepoRoot(context.cwd);
|
|
88
118
|
let review;
|
|
89
119
|
let reviewHeadBeforeWrite;
|
|
90
120
|
let reviewerActor;
|
|
121
|
+
let reviewPersistence;
|
|
122
|
+
let verification;
|
|
91
123
|
for (const gate of buildClaimGatePipeline()) {
|
|
92
124
|
const result = await gate.evaluate({
|
|
93
|
-
cwd:
|
|
125
|
+
cwd: deliveryCwd,
|
|
126
|
+
coordinationRoot,
|
|
94
127
|
contractId: context.contractId,
|
|
95
128
|
input,
|
|
96
|
-
|
|
129
|
+
verificationPlan,
|
|
130
|
+
verificationCandidate,
|
|
97
131
|
baseBranch: dependencies.baseBranch,
|
|
98
132
|
reviewNumber: dependencies.reviewNumber,
|
|
99
133
|
});
|
|
134
|
+
if (!result.pass) {
|
|
135
|
+
await throwClaimGateFailure(result, input, context, dependencies);
|
|
136
|
+
}
|
|
100
137
|
if (result.review) {
|
|
101
138
|
review = result.review;
|
|
102
139
|
reviewHeadBeforeWrite = result.reviewHeadBeforeWrite;
|
|
103
140
|
}
|
|
104
141
|
if (result.reviewerActor)
|
|
105
142
|
reviewerActor = result.reviewerActor;
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
143
|
+
if (result.reviewPersistence)
|
|
144
|
+
reviewPersistence = result.reviewPersistence;
|
|
145
|
+
if ("verification" in result && result.verification)
|
|
146
|
+
verification = result.verification;
|
|
109
147
|
}
|
|
110
|
-
|
|
148
|
+
await assertHeadUnchanged(deliveryCwd, verificationCandidate.head, "claim verification");
|
|
149
|
+
return { review, reviewHeadBeforeWrite, reviewerActor, reviewPersistence, verification };
|
|
111
150
|
}
|
|
112
151
|
function maxArc(entries) {
|
|
113
152
|
return entries.filter((entry) => entry.kind === "arc").length;
|
|
@@ -117,75 +156,108 @@ function cleanupWarnings(cleanup) {
|
|
|
117
156
|
...(cleanup.worktreeRemoveFailure
|
|
118
157
|
? [`Could not remove contract worktree ${cleanup.worktreeRemoveFailure.path}: ${cleanup.worktreeRemoveFailure.reason}`]
|
|
119
158
|
: []),
|
|
120
|
-
...(cleanup.
|
|
121
|
-
? [`
|
|
159
|
+
...(cleanup.deliveryRef.status === "mismatch"
|
|
160
|
+
? [`Delivery ref ${cleanup.deliveryRef.mismatch.ref} remains present at ${cleanup.deliveryRef.mismatch.observed.head}; terminal replay preserved it as a projected-surface mismatch.`]
|
|
122
161
|
: []),
|
|
123
162
|
];
|
|
124
163
|
}
|
|
125
|
-
function findClaimEntry(entries) {
|
|
126
|
-
return entries.find((entry) => entry.kind === "claim");
|
|
127
|
-
}
|
|
128
|
-
/** Verdict for the open petition window (after last petition, before claim). */
|
|
129
|
-
function latestCurrentPetitionVerdict(entries) {
|
|
130
|
-
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
131
|
-
const entry = entries[index];
|
|
132
|
-
if (entry.kind === "verdict")
|
|
133
|
-
return entry;
|
|
134
|
-
if (entry.kind === "petition")
|
|
135
|
-
return undefined;
|
|
136
|
-
}
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
164
|
/**
|
|
140
165
|
* Crash-recovery head: petition → approved verdict → no claim.
|
|
141
166
|
* Orchestrator resumes claim delivery only; no gates, petition, or re-judgment.
|
|
142
167
|
*/
|
|
143
|
-
function isApprovedVerdictAwaitingClaim(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (findClaimEntry(entries))
|
|
148
|
-
return false;
|
|
149
|
-
return latestCurrentPetitionVerdict(entries)?.data.result === "approved";
|
|
168
|
+
function isApprovedVerdictAwaitingClaim(lifecycle) {
|
|
169
|
+
return lifecycle.phase === "approved"
|
|
170
|
+
&& lifecycle.petition.state === "approved"
|
|
171
|
+
&& lifecycle.petition.intent === "claim";
|
|
150
172
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
/** Resume the first missing stage of an existing petition settlement. */
|
|
174
|
+
export async function reconcilePetitionRetry(input) {
|
|
175
|
+
const observed = await withContractCarrierSession({ ...input, mode: "observe-only" }, async (session) => ({
|
|
176
|
+
window: classifyCurrentPetitionWindow(session.lifecycle, session.pins),
|
|
177
|
+
queue: deriveQueueReadModel(session.repository),
|
|
178
|
+
}));
|
|
179
|
+
if (observed.window.status === "none")
|
|
180
|
+
return { status: "not-needed" };
|
|
181
|
+
if (observed.window.status === "approved-awaiting-claim") {
|
|
182
|
+
return { status: "approved-awaiting-claim" };
|
|
183
|
+
}
|
|
184
|
+
if (observed.window.status === "invalid") {
|
|
185
|
+
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} petition recovery is invalid: ${observed.window.reason}`);
|
|
186
|
+
}
|
|
187
|
+
assertClaimQueueHead(observed.queue, input.contractId);
|
|
188
|
+
if (observed.window.coordinates === "fresh") {
|
|
189
|
+
return {
|
|
190
|
+
status: "verdict",
|
|
191
|
+
result: "approved",
|
|
192
|
+
reason: "resume",
|
|
193
|
+
verdict: await verdictContract({
|
|
194
|
+
cwd: input.cwd,
|
|
195
|
+
contractId: input.contractId,
|
|
196
|
+
actor: "keiyaku",
|
|
197
|
+
nowMs: Date.now(),
|
|
198
|
+
result: "approved",
|
|
199
|
+
summary: "Recovered passed petition at its pinned candidate.",
|
|
200
|
+
signal: input.signal,
|
|
201
|
+
}),
|
|
202
|
+
};
|
|
158
203
|
}
|
|
204
|
+
const reason = observed.window.coordinates;
|
|
205
|
+
return {
|
|
206
|
+
status: "verdict",
|
|
207
|
+
result: "rejected",
|
|
208
|
+
reason,
|
|
209
|
+
verdict: await verdictContract({
|
|
210
|
+
cwd: input.cwd,
|
|
211
|
+
contractId: input.contractId,
|
|
212
|
+
actor: "keiyaku",
|
|
213
|
+
nowMs: Date.now(),
|
|
214
|
+
result: "rejected",
|
|
215
|
+
summary: reason === "target-drift"
|
|
216
|
+
? "Petition target advanced before verdict."
|
|
217
|
+
: "Petition delivery changed before verdict.",
|
|
218
|
+
signal: input.signal,
|
|
219
|
+
}),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
export async function recoverCurrentPetitionSeal(cwd, lifecycle) {
|
|
223
|
+
if (lifecycle.petition.state !== "approved" || lifecycle.petition.intent !== "claim")
|
|
224
|
+
return undefined;
|
|
225
|
+
const petitionObjectId = lifecycle.petition.objectId;
|
|
226
|
+
const petitionIndex = lifecycle.history.findIndex(({ objectId }) => objectId === petitionObjectId);
|
|
159
227
|
if (petitionIndex <= 0)
|
|
160
228
|
return undefined;
|
|
161
|
-
const seal =
|
|
162
|
-
if (seal.kind !== "seal" || seal.data.sealedBy !== "petition")
|
|
229
|
+
const seal = lifecycle.history[petitionIndex - 1];
|
|
230
|
+
if (seal?.entry.kind !== "seal" || seal.entry.data.sealedBy !== "petition")
|
|
163
231
|
return undefined;
|
|
164
|
-
const
|
|
165
|
-
const ledgerHead = commits[petitionIndex - 1];
|
|
166
|
-
if (!ledgerHead || commits.length !== ledger.entries.length) {
|
|
167
|
-
throw new FlowError("INTERNAL_STATE", `contract ${ledger.contractId} ledger entries do not align with ref-log commits during petition recovery`);
|
|
168
|
-
}
|
|
169
|
-
const scopeViolationEvidence = await scopePathEvidence(cwd, effectiveScope(ledger.entries), seal.data.scopeAudit.violations);
|
|
232
|
+
const scopeViolationEvidence = await scopePathEvidence(cwd, lifecycle.effectiveScope, seal.entry.data.scopeAudit.violations);
|
|
170
233
|
return {
|
|
171
|
-
...seal.data,
|
|
234
|
+
...seal.entry.data,
|
|
235
|
+
receipts: [...seal.entry.data.receipts],
|
|
236
|
+
diffstat: { ...seal.entry.data.diffstat },
|
|
237
|
+
scopeAudit: { violations: [...seal.entry.data.scopeAudit.violations] },
|
|
172
238
|
scopeViolationEvidence,
|
|
173
|
-
ledgerHead,
|
|
239
|
+
ledgerHead: seal.objectId,
|
|
174
240
|
};
|
|
175
241
|
}
|
|
176
242
|
async function finishApprovedClaim(context, options) {
|
|
177
243
|
const { cwd, baseBranch, contractId } = context;
|
|
178
244
|
// Capture arc facts before claim cleanup may remove the delivery worktree cwd.
|
|
179
|
-
const log = await readContractLog({ cwd, contractId });
|
|
245
|
+
const log = await readContractLog({ cwd, contractId, signal: options.signal });
|
|
180
246
|
const claimed = await claimContract({
|
|
181
247
|
cwd,
|
|
182
248
|
contractId,
|
|
183
249
|
actor: "keiyaku",
|
|
184
250
|
nowMs: options.nowMs,
|
|
251
|
+
signal: options.signal,
|
|
185
252
|
});
|
|
186
|
-
|
|
253
|
+
if (!isCompleteLifecycleOutcome(claimed))
|
|
254
|
+
return claimed;
|
|
255
|
+
if (!claimed.cleanup)
|
|
256
|
+
throw new FlowError("INTERNAL_STATE", "complete claim has no terminal cleanup facts");
|
|
257
|
+
const cleanup = claimed.cleanup;
|
|
187
258
|
const warnings = [...(claimed.warnings ?? []), ...cleanupWarnings(cleanup)];
|
|
188
259
|
return {
|
|
260
|
+
...claimed,
|
|
189
261
|
status: "success",
|
|
190
262
|
result: "merged",
|
|
191
263
|
arc: maxArc(log.entries),
|
|
@@ -193,12 +265,12 @@ async function finishApprovedClaim(context, options) {
|
|
|
193
265
|
baseBranch,
|
|
194
266
|
commit: claimed.mergeCommit,
|
|
195
267
|
mergedInto: baseBranch,
|
|
196
|
-
...(cleanup.deletedBranch ? { deletedBranch: cleanup.deletedBranch } : {}),
|
|
197
268
|
cleanup,
|
|
198
269
|
diff: `Merged contract ${contractId} with merge-tree/commit-tree CAS.`,
|
|
199
270
|
// Prior public outcome carried sealed facts when petition sealed an open arc.
|
|
200
271
|
...(options.sealed ? { sealed: options.sealed } : {}),
|
|
201
272
|
...(warnings.length > 0 ? { meta: { warnings } } : {}),
|
|
273
|
+
carrier: claimed.carrier,
|
|
202
274
|
};
|
|
203
275
|
}
|
|
204
276
|
/**
|
|
@@ -213,29 +285,35 @@ async function finishApprovedClaim(context, options) {
|
|
|
213
285
|
*/
|
|
214
286
|
export async function claimKeiyaku(input, context, dependencies) {
|
|
215
287
|
const { cwd, baseBranch, contractId } = context;
|
|
288
|
+
const retry = await reconcilePetitionRetry({
|
|
289
|
+
cwd,
|
|
290
|
+
contractId,
|
|
291
|
+
signal: input.signal,
|
|
292
|
+
});
|
|
293
|
+
if (retry.status === "verdict" && !isCompleteLifecycleOutcome(retry.verdict)) {
|
|
294
|
+
return retry.verdict;
|
|
295
|
+
}
|
|
216
296
|
// Crash recovery: petition → approved verdict → no claim.
|
|
217
297
|
// Resume claim delivery only; do not re-gate, re-petition, or re-judge.
|
|
218
|
-
const existing = await
|
|
219
|
-
if (
|
|
220
|
-
const sealed = await recoverCurrentPetitionSeal(cwd, existing);
|
|
298
|
+
const existing = await convergeContractCarrier({ cwd, contractId, signal: input.signal, mode: "observe-only" });
|
|
299
|
+
if (isApprovedVerdictAwaitingClaim(existing.lifecycle)) {
|
|
300
|
+
const sealed = await recoverCurrentPetitionSeal(cwd, existing.lifecycle);
|
|
221
301
|
return finishApprovedClaim(context, {
|
|
222
302
|
nowMs: Date.now(),
|
|
303
|
+
signal: input.signal,
|
|
223
304
|
...(sealed ? { sealed } : {}),
|
|
224
305
|
});
|
|
225
306
|
}
|
|
226
307
|
const claimResult = "dangerouslyBypassGates" in input && input.dangerouslyBypassGates
|
|
227
|
-
? { review: undefined, reviewHeadBeforeWrite: undefined, bypassedByArchitect: true }
|
|
308
|
+
? { review: undefined, reviewHeadBeforeWrite: undefined, reviewPersistence: undefined, bypassedByArchitect: true }
|
|
228
309
|
: {
|
|
229
|
-
...(await runClaimGatePipelineOrThrow(input,
|
|
310
|
+
...(await runClaimGatePipelineOrThrow(input, context, {
|
|
230
311
|
...dependencies,
|
|
231
312
|
baseBranch,
|
|
232
313
|
reviewNumber: await nextReviewResponseNumber(cwd),
|
|
233
314
|
})),
|
|
234
315
|
bypassedByArchitect: false,
|
|
235
316
|
};
|
|
236
|
-
if (claimResult.review && claimResult.reviewHeadBeforeWrite) {
|
|
237
|
-
await assertHeadUnchanged(cwd, claimResult.reviewHeadBeforeWrite, "claim review");
|
|
238
|
-
}
|
|
239
317
|
const oath = String(input.oath ?? "").trim();
|
|
240
318
|
if (!oath) {
|
|
241
319
|
throw new FlowError("OATH_MISSING", "Oath missing.");
|
|
@@ -249,7 +327,14 @@ export async function claimKeiyaku(input, context, dependencies) {
|
|
|
249
327
|
intent: "claim",
|
|
250
328
|
oath,
|
|
251
329
|
appendScope: input.appendScope,
|
|
330
|
+
reviewPersistence: claimResult.reviewPersistence,
|
|
331
|
+
signal: input.signal,
|
|
252
332
|
});
|
|
333
|
+
if (!isCompleteLifecycleOutcome(petition))
|
|
334
|
+
return petition;
|
|
335
|
+
const review = claimResult.review
|
|
336
|
+
? { ...claimResult.review, ...(petition.reviewHistoryPath ? { historyPath: petition.reviewHistoryPath } : {}) }
|
|
337
|
+
: undefined;
|
|
253
338
|
// 2. Pure verdict: judgment facts only; no claim execution.
|
|
254
339
|
// Capture one clock for verdict + claim so ledger timestamps match the prior
|
|
255
340
|
// verdict→claim atomic pair (verdict previously forwarded its own nowMs).
|
|
@@ -260,24 +345,31 @@ export async function claimKeiyaku(input, context, dependencies) {
|
|
|
260
345
|
actor: claimResult.reviewerActor ?? "keiyaku",
|
|
261
346
|
nowMs: judgmentNowMs,
|
|
262
347
|
result: "approved",
|
|
263
|
-
summary:
|
|
348
|
+
summary: review?.findings?.trim() || "礼成",
|
|
349
|
+
signal: input.signal,
|
|
264
350
|
});
|
|
351
|
+
if (!isCompleteLifecycleOutcome(verdict))
|
|
352
|
+
return verdict;
|
|
265
353
|
// 3. Execution: approved → claim delivery (same sequential append window as before).
|
|
266
354
|
// Rejected verdict publication is verdictContract itself (state returns active).
|
|
267
355
|
if (verdict.result !== "approved") {
|
|
268
356
|
throw new FlowError("INTERNAL_STATE", `settlement expected approved verdict for ${contractId}, got ${verdict.result}`);
|
|
269
357
|
}
|
|
270
|
-
|
|
358
|
+
const completed = await finishApprovedClaim(context, {
|
|
271
359
|
nowMs: judgmentNowMs,
|
|
360
|
+
signal: input.signal,
|
|
272
361
|
...(petition.sealed ? { sealed: petition.sealed } : {}),
|
|
273
362
|
});
|
|
363
|
+
if (!claimResult.verification || !isCompleteLifecycleOutcome(completed))
|
|
364
|
+
return completed;
|
|
365
|
+
return { ...completed, verification: claimResult.verification };
|
|
274
366
|
}
|
|
275
367
|
/** Public settlement entrypoint for CLI petition (claim or forfeit). */
|
|
276
368
|
export async function petitionKeiyaku(input) {
|
|
277
|
-
const context = await loadCloseContext(input.cwd, input.contractId);
|
|
369
|
+
const context = await loadCloseContext(input.cwd, input.contractId, input.signal);
|
|
278
370
|
const { intent } = input;
|
|
279
371
|
if (intent === "FORFEIT") {
|
|
280
|
-
return forfeitKeiyaku(context);
|
|
372
|
+
return forfeitKeiyaku(context, input.signal);
|
|
281
373
|
}
|
|
282
374
|
if (intent === "CLAIM") {
|
|
283
375
|
return claimKeiyaku(input, context, {
|
|
@@ -1,80 +1,126 @@
|
|
|
1
1
|
import { FlowError } from "../../flow-error.js";
|
|
2
|
-
import {
|
|
3
|
-
import { assertClaimQueueHead
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (entry.kind === "verdict")
|
|
9
|
-
return entry;
|
|
10
|
-
if (entry.kind === "petition")
|
|
11
|
-
return undefined;
|
|
12
|
-
}
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
|
-
function assertPetitioned(contractId, entries) {
|
|
16
|
-
const state = deriveContractState(entries);
|
|
2
|
+
import { runLifecycle } from "../lifecycle-runner.js";
|
|
3
|
+
import { assertClaimQueueHead } from "./queue.js";
|
|
4
|
+
import { deriveQueueReadModel } from "./queue-read-model.js";
|
|
5
|
+
import { currentLifecycleState } from "../repository-ledger/read-model.js";
|
|
6
|
+
function assertFoldedPetitioned(contractId, model) {
|
|
7
|
+
const state = currentLifecycleState(model);
|
|
17
8
|
if (state.state !== "petitioned") {
|
|
18
9
|
throw new FlowError("INTERNAL_STATE", `contract ${contractId} cannot verdict from state ${state.state}`);
|
|
19
10
|
}
|
|
20
11
|
}
|
|
12
|
+
function assertApprovedWindow(contractId, model, pins) {
|
|
13
|
+
if (model.petition.state !== "awaiting-verdict") {
|
|
14
|
+
throw new FlowError("VERDICT_DENIED", `contract ${contractId} cannot approve petition without an awaiting-verdict fold`);
|
|
15
|
+
}
|
|
16
|
+
if (!pins.target.head || !pins.delivery.head) {
|
|
17
|
+
throw new FlowError("VERDICT_DENIED", `contract ${contractId} cannot approve petition because current coordinates do not resolve`);
|
|
18
|
+
}
|
|
19
|
+
if (model.pins.base !== pins.target.head) {
|
|
20
|
+
throw new FlowError("VERDICT_DENIED", `contract ${contractId} cannot approve petition from target-drift`);
|
|
21
|
+
}
|
|
22
|
+
if (model.pins.delivery !== pins.delivery.head) {
|
|
23
|
+
throw new FlowError("VERDICT_DENIED", `contract ${contractId} cannot approve petition from delivery-drift`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
21
26
|
/**
|
|
22
27
|
* Append a verdict entry and return typed judgment facts.
|
|
23
28
|
* Does not claim, clean up, or otherwise execute delivery.
|
|
24
29
|
*/
|
|
25
30
|
export async function verdictContract(input) {
|
|
26
31
|
const at = new Date(input.nowMs).toISOString();
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
const ref = activeLedgerRef(input.contractId);
|
|
39
|
-
const appendResult = await appendWithRetry(input.cwd, ref, async (_head, entries) => {
|
|
40
|
-
const existingVerdict = latestVerdict(entries);
|
|
41
|
-
if (existingVerdict)
|
|
42
|
-
return null;
|
|
43
|
-
assertPetitioned(input.contractId, entries);
|
|
44
|
-
if (input.result === "approved") {
|
|
45
|
-
const model = await readQueueReadModel(input.cwd);
|
|
46
|
-
assertClaimQueueHead(model, input.contractId);
|
|
47
|
-
}
|
|
48
|
-
const entry = {
|
|
49
|
-
v: 1,
|
|
50
|
-
kind: "verdict",
|
|
51
|
-
contract: input.contractId,
|
|
52
|
-
at,
|
|
53
|
-
actor: input.actor,
|
|
54
|
-
data: {
|
|
55
|
-
result: input.result,
|
|
56
|
-
summary: input.summary,
|
|
32
|
+
const execution = await runLifecycle({
|
|
33
|
+
cwd: input.cwd,
|
|
34
|
+
contractId: input.contractId,
|
|
35
|
+
mutation: {
|
|
36
|
+
verb: "verdict",
|
|
37
|
+
matchesAccepted: (transaction) => {
|
|
38
|
+
const accepted = transaction.entries.at(-1);
|
|
39
|
+
return accepted?.kind === "verdict"
|
|
40
|
+
&& accepted.data.result === input.result
|
|
41
|
+
&& accepted.data.summary === input.summary;
|
|
57
42
|
},
|
|
58
|
-
}
|
|
59
|
-
|
|
43
|
+
},
|
|
44
|
+
signal: input.signal,
|
|
45
|
+
admit: async (session, replay) => {
|
|
46
|
+
const transaction = replay.state === "verb-committed" ? replay.transaction : undefined;
|
|
47
|
+
const accepted = transaction?.entries.at(-1);
|
|
48
|
+
if (accepted && accepted.kind !== "verdict") {
|
|
49
|
+
throw new FlowError("INTERNAL_STATE", `accepted transaction ${transaction.transactionObjectId} is not a verdict`);
|
|
50
|
+
}
|
|
51
|
+
if (!accepted)
|
|
52
|
+
assertFoldedPetitioned(input.contractId, session.lifecycle);
|
|
53
|
+
const queue = input.result === "approved" && !accepted ? deriveQueueReadModel(session.repository) : null;
|
|
54
|
+
if (queue) {
|
|
55
|
+
assertClaimQueueHead(queue, input.contractId);
|
|
56
|
+
assertApprovedWindow(input.contractId, session.lifecycle, session.pins);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
existing: accepted?.kind === "verdict"
|
|
60
|
+
? { transactionObjectId: transaction.transactionObjectId, result: accepted.data.result, summary: accepted.data.summary }
|
|
61
|
+
: undefined,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
prepare: () => ({ entry: {
|
|
65
|
+
v: 1,
|
|
66
|
+
kind: "verdict",
|
|
67
|
+
contract: input.contractId,
|
|
68
|
+
at,
|
|
69
|
+
actor: input.actor,
|
|
70
|
+
data: {
|
|
71
|
+
result: input.result,
|
|
72
|
+
summary: input.summary,
|
|
73
|
+
},
|
|
74
|
+
} }),
|
|
75
|
+
revalidate: async ({ session, admission }) => {
|
|
76
|
+
if (admission.business.existing) {
|
|
77
|
+
return session.repository.topology.nodes.some((node) => node.objectId === admission.business.existing.transactionObjectId)
|
|
78
|
+
? undefined
|
|
79
|
+
: { code: "VERDICT_CHANGED", message: "current petition verdict changed during preparation" };
|
|
80
|
+
}
|
|
81
|
+
assertFoldedPetitioned(input.contractId, session.lifecycle);
|
|
82
|
+
if (input.result === "approved") {
|
|
83
|
+
const queue = deriveQueueReadModel(session.repository);
|
|
84
|
+
try {
|
|
85
|
+
assertClaimQueueHead(queue, input.contractId);
|
|
86
|
+
assertApprovedWindow(input.contractId, session.lifecycle, session.pins);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
return {
|
|
90
|
+
code: "VERDICT_COORDINATES_CHANGED",
|
|
91
|
+
message: error instanceof Error ? error.message : String(error),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
},
|
|
97
|
+
effect: async ({ context, admission, prepared }) => {
|
|
98
|
+
if (admission.business.existing) {
|
|
99
|
+
return {
|
|
100
|
+
kind: "committed",
|
|
101
|
+
commit: await context.replayCommitted({ transactionObjectId: admission.business.existing.transactionObjectId }),
|
|
102
|
+
entryKind: "verdict",
|
|
103
|
+
value: { result: admission.business.existing.result, summary: admission.business.existing.summary },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const committed = await context.publishAuthoritative({ verb: "verdict", admittedLedgerHead: admission.ledgerHead, acceptedLifecycleTail: context.session.lifecycle.history.at(-1).objectId, entries: [prepared.entry] });
|
|
107
|
+
if (committed.status === "indeterminate") {
|
|
108
|
+
return { kind: "precommit-effects-only", authoritativeHead: committed.currentHead ?? admission.ledgerHead };
|
|
109
|
+
}
|
|
110
|
+
if (committed.status !== "committed") {
|
|
111
|
+
return { kind: "refused-before-effects", authoritativeHead: committed.currentHead ?? context.session.lifecycle.observedLedgerHead, refusal: { code: "LEDGER_CAS_CONFLICT", message: `contract ${input.contractId} changed during verdict` } };
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
kind: "committed",
|
|
115
|
+
commit: committed,
|
|
116
|
+
entryKind: "verdict",
|
|
117
|
+
value: { result: input.result, summary: input.summary },
|
|
118
|
+
};
|
|
119
|
+
},
|
|
60
120
|
});
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} disappeared before verdict settlement`);
|
|
67
|
-
}
|
|
68
|
-
const verdict = latestVerdict(settled.entries);
|
|
69
|
-
if (!verdict) {
|
|
70
|
-
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} missing verdict after settlement write`);
|
|
71
|
-
}
|
|
72
|
-
if (verdict.data.result !== input.result) {
|
|
73
|
-
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} already has ${verdict.data.result} verdict`);
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
contractId: input.contractId,
|
|
77
|
-
result: verdict.data.result,
|
|
78
|
-
summary: verdict.data.summary,
|
|
79
|
-
};
|
|
121
|
+
if (execution.kind === "noncommitted")
|
|
122
|
+
return execution.outcome;
|
|
123
|
+
if (execution.kind === "contained")
|
|
124
|
+
return { ...execution.outcome, contractId: input.contractId };
|
|
125
|
+
return { ...execution.outcome, contractId: input.contractId, ...execution.payload, carrier: execution.carrier };
|
|
80
126
|
}
|