@astrosheep/keiyaku 4.0.4 → 4.0.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/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +14 -0
- package/build/src/akuma/akuma.d.ts +0 -1
- package/build/src/akuma/akuma.js +1 -6
- package/build/src/akuma/allowed.d.ts +1 -1
- package/build/src/akuma/allowed.js +3 -10
- package/build/src/akuma/body.d.ts +5 -2
- package/build/src/akuma/body.js +29 -23
- package/build/src/akuma/heart/facts.d.ts +35 -9
- package/build/src/akuma/heart/index.d.ts +4 -13
- package/build/src/akuma/heart/index.js +2 -133
- package/build/src/akuma/heart/request-authority.d.ts +12 -0
- package/build/src/akuma/heart/request-authority.js +119 -0
- package/build/src/akuma/heart/request-rows.d.ts +16 -0
- package/build/src/akuma/heart/request-rows.js +88 -0
- package/build/src/akuma/heart/rows.d.ts +1 -28
- package/build/src/akuma/heart/rows.js +0 -137
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +9 -2
- package/build/src/akuma/heart/soul.js +0 -36
- package/build/src/akuma/index.d.ts +1 -1
- package/build/src/akuma/provider-recipe.js +1 -11
- package/build/src/akuma/provider.d.ts +1 -6
- package/build/src/akuma/providers/acp/core.js +6 -2
- package/build/src/akuma/providers/acp/index.js +0 -1
- package/build/src/akuma/providers/claude/index.d.ts +0 -4
- package/build/src/akuma/providers/claude/index.js +7 -3
- package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
- package/build/src/akuma/providers/codex-app-server/index.js +0 -2
- package/build/src/akuma/providers/grok-build/index.js +0 -1
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
- package/build/src/akuma/providers/opencode-sdk/index.js +8 -4
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +1 -1
- package/build/src/akuma/providers/opencode-sdk/session.js +1 -1
- package/build/src/akuma/providers/pi/index.js +11 -4
- package/build/src/akuma/request-serve.d.ts +87 -0
- package/build/src/akuma/request-serve.js +484 -0
- package/build/src/akuma/request-wire.d.ts +124 -0
- package/build/src/akuma/request-wire.js +380 -0
- package/build/src/akuma/requests.d.ts +28 -94
- package/build/src/akuma/requests.js +52 -562
- package/build/src/akuma-body.d.ts +7 -0
- package/build/src/akuma-body.js +54 -1
- package/build/src/body/arc.js +4 -29
- package/build/src/body/decode.js +5 -39
- package/build/src/body/envelope.d.ts +7 -0
- package/build/src/body/envelope.js +37 -0
- package/build/src/cli/accepted.js +17 -9
- package/build/src/cli/commands/akuma.js +2 -2
- package/build/src/cli/commands/contract.d.ts +6 -6
- package/build/src/cli/commands/contract.js +3 -3
- package/build/src/cli/commands/task-invoke.js +98 -9
- package/build/src/cli/coordinates.d.ts +1 -0
- package/build/src/cli/coordinates.js +7 -4
- package/build/src/cli/invoke.js +28 -4
- package/build/src/cli/parse.d.ts +2 -2
- package/build/src/cli/parse.js +21 -8
- package/build/src/cli/render/akuma.js +56 -13
- package/build/src/cli/render/audit.js +2 -6
- package/build/src/cli/render/contract.js +40 -0
- package/build/src/cli/render/receipt.js +28 -1
- package/build/src/cli/render/terminal.d.ts +0 -2
- package/build/src/cli/render/terminal.js +0 -29
- package/build/src/cli/result.d.ts +15 -7
- package/build/src/contract-worktree.d.ts +1 -2
- package/build/src/contract-worktree.js +4 -9
- package/build/src/core/facts/codec.js +9 -0
- package/build/src/core/facts/fold.js +13 -1
- package/build/src/core/facts/types.d.ts +8 -1
- package/build/src/core/subject.js +4 -3
- package/build/src/core/verbs/placement.d.ts +9 -1
- package/build/src/core/verbs/placement.js +24 -6
- package/build/src/core/verbs/reintegrate.d.ts +13 -0
- package/build/src/core/verbs/reintegrate.js +24 -0
- package/build/src/dispatch/index.d.ts +1 -1
- package/build/src/git/admission.d.ts +2 -1
- package/build/src/git/integration.d.ts +5 -2
- package/build/src/git/integration.js +54 -1
- package/build/src/git/observe.d.ts +2 -1
- package/build/src/git/observe.js +6 -5
- package/build/src/git/process.d.ts +26 -0
- package/build/src/git/process.js +94 -0
- package/build/src/git/read-observation.d.ts +2 -1
- package/build/src/git/read-observation.js +3 -2
- package/build/src/git/reconcile.d.ts +2 -1
- package/build/src/git/reconcile.js +9 -6
- package/build/src/git/repository.d.ts +2 -29
- package/build/src/git/repository.js +4 -118
- package/build/src/git/scratch.d.ts +1 -1
- package/build/src/git/scratch.js +1 -1
- package/build/src/git/target-placement.d.ts +1 -1
- package/build/src/git/target-placement.js +9 -7
- package/build/src/git/tender.d.ts +1 -1
- package/build/src/git/tender.js +2 -1
- package/build/src/git/terminal-seal.d.ts +2 -2
- package/build/src/git/terminal-seal.js +3 -6
- package/build/src/git/workspace.d.ts +1 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/index.d.ts +1 -2
- package/build/src/index.js +1 -1
- package/build/src/library/address.js +7 -1
- package/build/src/library/audit.d.ts +2 -1
- package/build/src/library/audit.js +1 -1
- package/build/src/library/bind.d.ts +2 -1
- package/build/src/library/bind.js +1 -1
- package/build/src/library/configuration.d.ts +1 -1
- package/build/src/library/configuration.js +52 -18
- package/build/src/library/contract.d.ts +55 -2
- package/build/src/library/contract.js +162 -23
- package/build/src/library/delivery.d.ts +1 -1
- package/build/src/library/fleet.d.ts +27 -7
- package/build/src/library/fleet.js +79 -39
- package/build/src/library/input.d.ts +0 -1
- package/build/src/library/input.js +0 -5
- package/build/src/library/keiyaku.d.ts +1 -1
- package/build/src/library/mutation.d.ts +2 -1
- package/build/src/library/reconcile.d.ts +2 -1
- package/build/src/library/reconcile.js +3 -1
- package/build/src/library/region.d.ts +1 -1
- package/build/src/library/repo.d.ts +3 -1
- package/build/src/library/repo.js +8 -4
- package/build/src/protocol/abandon.d.ts +9 -0
- package/build/src/protocol/abandon.js +15 -0
- package/build/src/protocol/amend.d.ts +16 -0
- package/build/src/protocol/amend.js +77 -0
- package/build/src/protocol/arc.d.ts +6 -0
- package/build/src/protocol/arc.js +12 -0
- package/build/src/protocol/attempt.d.ts +2 -1
- package/build/src/protocol/audit.d.ts +53 -0
- package/build/src/protocol/audit.js +140 -0
- package/build/src/protocol/bind.d.ts +1 -1
- package/build/src/protocol/completion.d.ts +32 -0
- package/build/src/protocol/completion.js +130 -0
- package/build/src/protocol/deliver.d.ts +37 -0
- package/build/src/protocol/deliver.js +160 -0
- package/build/src/protocol/intent.d.ts +1 -1
- package/build/src/protocol/intent.js +1 -1
- package/build/src/protocol/operations.d.ts +64 -200
- package/build/src/protocol/operations.js +21 -640
- package/build/src/protocol/placement.d.ts +4 -13
- package/build/src/protocol/placement.js +3 -15
- package/build/src/protocol/read/status.d.ts +1 -1
- package/build/src/protocol/read/status.js +3 -1
- package/build/src/protocol/reconcile.d.ts +35 -0
- package/build/src/protocol/reconcile.js +41 -0
- package/build/src/protocol/reintegrate.d.ts +31 -0
- package/build/src/protocol/reintegrate.js +74 -0
- package/build/src/protocol/review.d.ts +33 -0
- package/build/src/protocol/review.js +148 -0
- package/build/src/protocol/run.d.ts +1 -1
- package/build/src/settlement/fence.d.ts +1 -1
- package/build/src/settlement/holder.d.ts +1 -1
- package/build/src/settlement/settle.d.ts +1 -1
- package/build/src/task/board.d.ts +0 -1
- package/build/src/task/board.js +0 -3
- package/build/src/task/compose.d.ts +1 -1
- package/build/src/task/compose.js +11 -4
- package/build/src/task/index.d.ts +1 -1
- package/build/src/task/index.js +2 -127
- package/build/src/task/input.d.ts +18 -0
- package/build/src/task/input.js +189 -0
- package/build/src/task/mutation.d.ts +39 -0
- package/build/src/task/mutation.js +85 -0
- package/build/src/task/operations.d.ts +2 -0
- package/build/src/task/operations.js +35 -11
- package/build/src/task/store.js +0 -2
- package/build/src/verification/execution.d.ts +1 -1
- package/build/src/workspace-place.d.ts +1 -4
- package/build/src/workspace-place.js +0 -15
- package/package.json +3 -3
package/build/src/cli/parse.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isTaskAction, parseTaskCommand, renderTaskUsage, } from "./commands/task.js";
|
|
2
2
|
import { isAkumaAction, parseAkumaCatalogPath, parseAkumaCommand, renderAkumaRootRows, renderAkumaUsage, } from "./commands/akuma.js";
|
|
3
3
|
import { INSTALL_USAGE, parseInstallCommand, renderInstallHelp } from "./commands/install.js";
|
|
4
|
-
import { AMEND_MINIMAL_STDIN_HELP, CONTRACT_COMMAND_SPECS } from "./commands/contract.js";
|
|
4
|
+
import { AMEND_MINIMAL_STDIN_HELP, CONTRACT_COMMAND_SPECS, } from "./commands/contract.js";
|
|
5
5
|
import { CliUsageError, isBlankInput, usageLine, withJsonAutomationHelp } from "./usage.js";
|
|
6
6
|
export { CliUsageError } from "./usage.js";
|
|
7
7
|
const ROOT_USAGE = "usage: keiyaku [-C <path>] [--repo <path>] <command> [<contract>|@<contract>] [--flag ...] [-]";
|
|
@@ -69,9 +69,12 @@ function scanOption(command, argv, state, index) {
|
|
|
69
69
|
return index;
|
|
70
70
|
}
|
|
71
71
|
const value = argv[index + 1];
|
|
72
|
-
if (value === undefined
|
|
72
|
+
if (value === undefined)
|
|
73
73
|
refuse(command, `${token} requires a value`);
|
|
74
|
-
if (
|
|
74
|
+
if (kind !== "raw-value" && (value === "-" || value.startsWith("--"))) {
|
|
75
|
+
refuse(command, `${token} requires a value`);
|
|
76
|
+
}
|
|
77
|
+
if (kind !== "raw-value" && isBlankInput(value))
|
|
75
78
|
refuse(command, `${token} requires a nonblank value`);
|
|
76
79
|
if (kind === "repeat-value") {
|
|
77
80
|
const values = state.flags[name];
|
|
@@ -121,7 +124,7 @@ function parseBind(parts) {
|
|
|
121
124
|
const task = optionalFlag(parts.flags, "task");
|
|
122
125
|
const target = optionalFlag(parts.flags, "target");
|
|
123
126
|
const after = parts.flags.after === undefined ? [] : Array.isArray(parts.flags.after) ? parts.flags.after : [parts.flags.after];
|
|
124
|
-
const gates =
|
|
127
|
+
const gates = parseGateBundleNames(parts, "bind");
|
|
125
128
|
return {
|
|
126
129
|
command: "bind",
|
|
127
130
|
...(task === undefined ? {} : { task }),
|
|
@@ -138,7 +141,7 @@ function parseAmend(parts) {
|
|
|
138
141
|
const after = parts.flags.after === undefined ? [] : Array.isArray(parts.flags.after) ? parts.flags.after : [parts.flags.after];
|
|
139
142
|
if (parts.flags["clear-after"] === true && after.length > 0)
|
|
140
143
|
refuse("amend", "--clear-after and --after are mutually exclusive");
|
|
141
|
-
const gates =
|
|
144
|
+
const gates = parseGateBundleNames(parts, "amend");
|
|
142
145
|
if (!parts.stdin && parts.flags.after === undefined && parts.flags["clear-after"] !== true && gates === undefined) {
|
|
143
146
|
refuse("amend", "amend requires stdin or --after, --clear-after, or --gates");
|
|
144
147
|
}
|
|
@@ -153,6 +156,16 @@ function parseAmend(parts) {
|
|
|
153
156
|
output: parts.output,
|
|
154
157
|
};
|
|
155
158
|
}
|
|
159
|
+
function parseGateBundleNames(parts, command) {
|
|
160
|
+
const value = optionalFlag(parts.flags, "gates");
|
|
161
|
+
if (value === undefined)
|
|
162
|
+
return undefined;
|
|
163
|
+
const names = value.split(",");
|
|
164
|
+
if (names.some((name) => name.length === 0)) {
|
|
165
|
+
refuse(command, "--gates requires nonempty comma-separated names");
|
|
166
|
+
}
|
|
167
|
+
return names;
|
|
168
|
+
}
|
|
156
169
|
function parseDeliver(parts) {
|
|
157
170
|
const contract = parts.positionals[0];
|
|
158
171
|
const message = optionalFlag(parts.flags, "message");
|
|
@@ -240,14 +253,14 @@ function parseRegion(parts) {
|
|
|
240
253
|
}
|
|
241
254
|
function parseLs(parts) {
|
|
242
255
|
const path = parts.positionals[0];
|
|
243
|
-
if (path === "task/")
|
|
256
|
+
if (path === "task" || path === "task/")
|
|
244
257
|
return { command: "ls", query: { kind: "tasks" }, output: parts.output };
|
|
245
|
-
if (path === "kei/")
|
|
258
|
+
if (path === "kei" || path === "kei/")
|
|
246
259
|
return { command: "ls", query: { kind: "contracts" }, output: parts.output };
|
|
247
260
|
try {
|
|
248
261
|
const query = parseAkumaCatalogPath(path);
|
|
249
262
|
if (query === null)
|
|
250
|
-
refuse("ls", "ls requires
|
|
263
|
+
refuse("ls", "ls requires a supported identity directory selector");
|
|
251
264
|
return { command: "ls", query, output: parts.output };
|
|
252
265
|
}
|
|
253
266
|
catch (error) {
|
|
@@ -7,16 +7,27 @@ const VERB_WIDTH = 6;
|
|
|
7
7
|
function identity(id, alias) {
|
|
8
8
|
return `${id}${alias === undefined ? "" : ` (${alias})`}`;
|
|
9
9
|
}
|
|
10
|
-
function
|
|
10
|
+
function associatedContractId(contract) {
|
|
11
|
+
return contract.kind === "associated" ? contract.contractId : undefined;
|
|
12
|
+
}
|
|
13
|
+
function associatedIdentity(id, alias, contract) {
|
|
14
|
+
const contractId = contract === undefined ? undefined : associatedContractId(contract);
|
|
11
15
|
return `${identity(id, alias)}${contractId === undefined ? "" : ` [${contractId}]`}`;
|
|
12
16
|
}
|
|
13
|
-
function snapshotHeading(id, alias,
|
|
17
|
+
function snapshotHeading(id, alias, contract) {
|
|
18
|
+
const contractId = contract === undefined ? undefined : associatedContractId(contract);
|
|
14
19
|
return [
|
|
15
20
|
OPENING_STROKE,
|
|
16
21
|
identity(id, alias),
|
|
17
22
|
...(contractId === undefined ? [] : [`└─ ${contractId}`]),
|
|
18
23
|
];
|
|
19
24
|
}
|
|
25
|
+
function contractFacts(contract) {
|
|
26
|
+
return contract.kind === "failed" ? [`! contract failed ${safeText(contract.diagnostic)}`] : [];
|
|
27
|
+
}
|
|
28
|
+
function unobservedText(id, diagnostic) {
|
|
29
|
+
return `! ${id} unobserved: ${safeText(diagnostic)}`;
|
|
30
|
+
}
|
|
20
31
|
function lifeLabel(life) {
|
|
21
32
|
if (life === "running")
|
|
22
33
|
return "● running";
|
|
@@ -201,11 +212,12 @@ function snapshotText(view, context, options = {}) {
|
|
|
201
212
|
: groupedEntries(snapshot.entries, context);
|
|
202
213
|
const facts = [
|
|
203
214
|
...(view.status.readonly?.enforcement === "none" ? [`! ${safeText(view.status.readonly.diagnostic)}`] : []),
|
|
215
|
+
...contractFacts(view.contract),
|
|
204
216
|
...(options.facts ?? []),
|
|
205
217
|
];
|
|
206
218
|
const footer = options.showLife === false ? [] : [` ${lifeLabel(view.status.life)}`];
|
|
207
219
|
return [
|
|
208
|
-
...snapshotHeading(view.status.id, options.alias, view.
|
|
220
|
+
...snapshotHeading(view.status.id, options.alias, view.contract),
|
|
209
221
|
...facts,
|
|
210
222
|
...activity,
|
|
211
223
|
...footer,
|
|
@@ -213,17 +225,33 @@ function snapshotText(view, context, options = {}) {
|
|
|
213
225
|
...renderTaskContextLines(view.createdTasks, context.columns),
|
|
214
226
|
].join("\n");
|
|
215
227
|
}
|
|
228
|
+
function observationStageText(id, observation, context, options = {}) {
|
|
229
|
+
if (observation.kind === "unobserved")
|
|
230
|
+
return unobservedText(id, observation.diagnostic);
|
|
231
|
+
return snapshotText(observation, context, options);
|
|
232
|
+
}
|
|
233
|
+
function waitText(result, context) {
|
|
234
|
+
const alias = result.alias;
|
|
235
|
+
const blocks = [
|
|
236
|
+
...result.result.observations.map((observation) => snapshotText(observation, context, { ...(alias === undefined ? {} : { alias }) })),
|
|
237
|
+
...result.result.unobserved.map((member) => unobservedText(member.id, member.diagnostic)),
|
|
238
|
+
];
|
|
239
|
+
return blocks.join("\n\n");
|
|
240
|
+
}
|
|
216
241
|
function historyText(command, result, context) {
|
|
217
242
|
if (command.last)
|
|
218
243
|
return result.mode === "last" ? result.answer : "no answer retained";
|
|
219
244
|
if (result.mode !== "page")
|
|
220
245
|
throw new Error("history result lacks page");
|
|
221
|
-
|
|
222
|
-
return [...snapshotHeading(result.akuma, result.alias, contractId), ...groupedRows(result.history.rows, context, true)].join("\n");
|
|
246
|
+
return [...snapshotHeading(result.akuma, result.alias, result.historyResult.contract), ...groupedRows(result.history.rows, context, true)].join("\n");
|
|
223
247
|
}
|
|
224
248
|
function tellText(result, context) {
|
|
225
249
|
const facts = typeof result.result.tell.wake === "string" ? [] : [`! error ${safeText(result.result.tell.wake.diagnostic)}`];
|
|
226
|
-
return
|
|
250
|
+
return observationStageText(result.result.akuma, result.result.observation, context, {
|
|
251
|
+
...(result.alias === undefined ? {} : { alias: result.alias }),
|
|
252
|
+
facts,
|
|
253
|
+
showLife: false,
|
|
254
|
+
});
|
|
227
255
|
}
|
|
228
256
|
function dispatchLines(stage) {
|
|
229
257
|
if (stage.kind === "none" || stage.kind === "dispatched")
|
|
@@ -272,7 +300,9 @@ function callText(result, context) {
|
|
|
272
300
|
facts.push(`alias failed ${result.result.alias.failure.kind} ${safeText(result.result.alias.failure.diagnostic)}`);
|
|
273
301
|
const cwd = executionCwdLine(result.result);
|
|
274
302
|
if (result.result.observation.kind === "detached") {
|
|
275
|
-
const lines = [...snapshotHeading(result.result.akuma, alias, contractId
|
|
303
|
+
const lines = [...snapshotHeading(result.result.akuma, alias, contractId === undefined
|
|
304
|
+
? { kind: "none" }
|
|
305
|
+
: { kind: "associated", contractId }), ...cwd, ...restraint, ...facts];
|
|
276
306
|
if (!callFailed(result.result)) {
|
|
277
307
|
const selector = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : result.result.akuma;
|
|
278
308
|
lines.push(`$ keiyaku -C ${result.world} wait ${selector} --timeout 5m`);
|
|
@@ -280,9 +310,14 @@ function callText(result, context) {
|
|
|
280
310
|
return lines.join("\n");
|
|
281
311
|
}
|
|
282
312
|
if (result.result.observation.kind === "failed") {
|
|
283
|
-
return [...snapshotHeading(result.result.akuma, alias, contractId
|
|
313
|
+
return [...snapshotHeading(result.result.akuma, alias, contractId === undefined
|
|
314
|
+
? { kind: "none" }
|
|
315
|
+
: { kind: "associated", contractId }), ...cwd, ...restraint, ...facts, `! error ${safeText(result.result.observation.failure.diagnostic)}`].join("\n");
|
|
284
316
|
}
|
|
285
|
-
return snapshotText({
|
|
317
|
+
return snapshotText({
|
|
318
|
+
status: result.result.observation.status,
|
|
319
|
+
contract: contractId === undefined ? { kind: "none" } : { kind: "associated", contractId },
|
|
320
|
+
}, context, {
|
|
286
321
|
...(alias === undefined ? {} : { alias }),
|
|
287
322
|
facts: [...cwd, ...facts],
|
|
288
323
|
});
|
|
@@ -299,17 +334,25 @@ export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
|
|
|
299
334
|
case "call": return callText(result, context);
|
|
300
335
|
case "status": return snapshotText(result.status, context, { ...(result.alias === undefined ? {} : { alias: result.alias }) });
|
|
301
336
|
case "wait":
|
|
302
|
-
return result
|
|
303
|
-
case "tell":
|
|
337
|
+
return waitText(result, context);
|
|
338
|
+
case "tell":
|
|
339
|
+
return result.mode === "ordinary"
|
|
340
|
+
? tellText(result, context)
|
|
341
|
+
: observationStageText(result.result.id, result.result.observation, context, {
|
|
342
|
+
...(result.alias === undefined ? {} : { alias: result.alias }),
|
|
343
|
+
showLife: false,
|
|
344
|
+
});
|
|
304
345
|
case "history":
|
|
305
346
|
return historyText(command, result, context);
|
|
306
347
|
case "fork": {
|
|
307
348
|
if (result.receipt.kind !== "forked")
|
|
308
349
|
return result.receipt.kind === "unknown-history" ? `${result.receipt.at} has no matching retained answered turn` : result.receipt.kind === "provider-cannot-fork" ? `${result.receipt.provider} cannot fork` : result.receipt.diagnostic;
|
|
309
350
|
const contractId = result.receipt.dispatch.kind === "dispatched" ? result.receipt.dispatch.dispatch.contractId : undefined;
|
|
310
|
-
return associatedIdentity(result.receipt.child, undefined, contractId
|
|
351
|
+
return associatedIdentity(result.receipt.child, undefined, contractId === undefined
|
|
352
|
+
? { kind: "none" }
|
|
353
|
+
: { kind: "associated", contractId });
|
|
311
354
|
}
|
|
312
|
-
case "kill": return result.result.results.map((member) =>
|
|
355
|
+
case "kill": return result.result.results.map((member) => observationStageText(member.id, member.observation, context, { facts: [`kill ${member.evidence}`], ...(result.alias === undefined ? {} : { alias: result.alias }) })).join("\n\n");
|
|
313
356
|
}
|
|
314
357
|
}
|
|
315
358
|
function callExitCode(result) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cleanupLines, leakLines, receiptPayload, receiptRow, stopLines, titleLines, } from "./receipt.js";
|
|
2
2
|
import { renderRefusalFacts } from "./refusal.js";
|
|
3
|
-
import { gitShortStat,
|
|
3
|
+
import { gitShortStat, renderOpaqueBlock, } from "./terminal.js";
|
|
4
4
|
const CHILD = " ";
|
|
5
5
|
function workspaceEvidence(workspace, columns) {
|
|
6
6
|
return renderOpaqueBlock(`workspace ${workspace.kind} ${workspace.path}`, CHILD, columns);
|
|
@@ -46,11 +46,7 @@ function verificationLines(verification, columns, addressed) {
|
|
|
46
46
|
{ text: `${verification.passed} of ${verification.total}` },
|
|
47
47
|
], columns);
|
|
48
48
|
if (verification.summary !== undefined) {
|
|
49
|
-
lines
|
|
50
|
-
first: `${CHILD}summary `,
|
|
51
|
-
continuation: CHILD,
|
|
52
|
-
columns,
|
|
53
|
-
}));
|
|
49
|
+
receiptPayload(lines, "summary", verification.summary);
|
|
54
50
|
}
|
|
55
51
|
return lines;
|
|
56
52
|
}
|
|
@@ -201,10 +201,37 @@ function renderAcceptedAmend(result, columns) {
|
|
|
201
201
|
lines.push(...acceptedDeviations(result, columns), ...recordBlock(result, columns));
|
|
202
202
|
return lines.join("\n");
|
|
203
203
|
}
|
|
204
|
+
function reintegrationLines(result, complete, columns) {
|
|
205
|
+
const reintegrated = result.facts.filter((fact) => fact.kind === "reintegrated");
|
|
206
|
+
if (reintegrated.length === 0)
|
|
207
|
+
return [];
|
|
208
|
+
const lines = [];
|
|
209
|
+
for (const fact of reintegrated) {
|
|
210
|
+
receiptRow(lines, " ", "re-integrated", [
|
|
211
|
+
{ text: fact.data.predecessor, opaque: true },
|
|
212
|
+
{ text: "->" },
|
|
213
|
+
{ text: fact.data.snapshot, opaque: true },
|
|
214
|
+
], columns);
|
|
215
|
+
}
|
|
216
|
+
if (result.verificationVerdict !== undefined) {
|
|
217
|
+
receiptRow(lines, " ", "verification re-run", [
|
|
218
|
+
{ text: "·" },
|
|
219
|
+
{ text: result.verificationVerdict },
|
|
220
|
+
], columns);
|
|
221
|
+
}
|
|
222
|
+
if (complete) {
|
|
223
|
+
receiptRow(lines, " ", "target", [
|
|
224
|
+
{ text: "->" },
|
|
225
|
+
{ text: reintegrated.at(-1).data.snapshot, opaque: true },
|
|
226
|
+
], columns);
|
|
227
|
+
}
|
|
228
|
+
return lines;
|
|
229
|
+
}
|
|
204
230
|
function renderAcceptedDeliver(result, columns) {
|
|
205
231
|
const complete = result.facts.some((fact) => fact.kind === "claimed");
|
|
206
232
|
const title = complete ? "delivered" : "deliver — not complete";
|
|
207
233
|
const lines = titleLines("✓", title, result.contract, columns);
|
|
234
|
+
lines.push(...reintegrationLines(result, complete, columns));
|
|
208
235
|
if (!complete)
|
|
209
236
|
receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
|
|
210
237
|
if (result.verification !== undefined) {
|
|
@@ -229,12 +256,20 @@ function renderAcceptedDeliver(result, columns) {
|
|
|
229
256
|
function renderAcceptedReview(result, columns) {
|
|
230
257
|
const complete = result.facts.some((fact) => fact.kind === "claimed");
|
|
231
258
|
const lines = titleLines("✓", `review ${result.verdict}`, result.contract, columns);
|
|
259
|
+
lines.push(...reintegrationLines(result, complete, columns));
|
|
232
260
|
receiptRow(lines, complete ? "✓" : "!", "contract", [
|
|
233
261
|
{ text: complete ? "complete" : "not complete" },
|
|
234
262
|
], columns);
|
|
235
263
|
if (result.placement !== undefined) {
|
|
236
264
|
lines.push(...stopLines("completion", result.placement, columns, result.contract));
|
|
237
265
|
}
|
|
266
|
+
if (result.verification !== undefined) {
|
|
267
|
+
lines.push(...stopLines("verification", result.verification, columns, result.contract));
|
|
268
|
+
}
|
|
269
|
+
if (result.cleanup !== undefined)
|
|
270
|
+
pushBlock(lines, cleanupLines(result.cleanup, columns));
|
|
271
|
+
if (result.leak !== undefined)
|
|
272
|
+
pushBlock(lines, leakLines(result.leak, columns));
|
|
238
273
|
lines.push(...acceptedDeviations(result, columns), ...recordBlock(result, columns));
|
|
239
274
|
return lines.join("\n");
|
|
240
275
|
}
|
|
@@ -338,6 +373,11 @@ function journalBody(fact) {
|
|
|
338
373
|
` require-branches-to-be-up-to-date ${String(policy.requireBranchesToBeUpToDate)}`,
|
|
339
374
|
];
|
|
340
375
|
}
|
|
376
|
+
case "reintegrated":
|
|
377
|
+
return [
|
|
378
|
+
` predecessor ${fact.data.predecessor}`,
|
|
379
|
+
` snapshot ${fact.data.snapshot}`,
|
|
380
|
+
];
|
|
341
381
|
case "attestation": {
|
|
342
382
|
const lines = [
|
|
343
383
|
` gate ${fact.data.gate}`,
|
|
@@ -59,6 +59,32 @@ export function reuseLines(reuse, columns) {
|
|
|
59
59
|
return [];
|
|
60
60
|
return renderOpaqueBlock(`reuse verification ${reuse.entry} ${reuse.verdict}`, " ", columns);
|
|
61
61
|
}
|
|
62
|
+
function prerequisiteRows(stop, columns) {
|
|
63
|
+
if (!("refusal" in stop) || stop.refusal?.kind !== "prerequisites-unsatisfied")
|
|
64
|
+
return [];
|
|
65
|
+
const lines = [];
|
|
66
|
+
for (const prerequisite of stop.refusal.unmet) {
|
|
67
|
+
receiptRow(lines, " ", "prerequisite", [
|
|
68
|
+
{ text: prerequisite.contractId, opaque: true },
|
|
69
|
+
{ text: "·" },
|
|
70
|
+
{ text: prerequisite.state },
|
|
71
|
+
], columns);
|
|
72
|
+
}
|
|
73
|
+
return lines;
|
|
74
|
+
}
|
|
75
|
+
function targetMovedDetail(stop) {
|
|
76
|
+
if ("integratedAt" in stop) {
|
|
77
|
+
return [
|
|
78
|
+
{ text: stop.target, opaque: true },
|
|
79
|
+
{ text: `${stop.integratedAt} -> ${stop.observed}`, opaque: true },
|
|
80
|
+
{ text: `attempts=${stop.attempts}` },
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
return [
|
|
84
|
+
{ text: stop.target, opaque: true },
|
|
85
|
+
{ text: `${stop.expected} -> ${stop.observed}`, opaque: true },
|
|
86
|
+
];
|
|
87
|
+
}
|
|
62
88
|
export function stopLines(label, stop, columns, addressed) {
|
|
63
89
|
const detail = [];
|
|
64
90
|
if ("refusal" in stop && stop.refusal !== undefined) {
|
|
@@ -76,12 +102,13 @@ export function stopLines(label, stop, columns, addressed) {
|
|
|
76
102
|
detail.push({ text: `command=${stop.command}` }, { text: hookFailureSummary(stop.detail), opaque: true });
|
|
77
103
|
}
|
|
78
104
|
else if (stop.failure === "target-moved") {
|
|
79
|
-
detail.push(
|
|
105
|
+
detail.push(...targetMovedDetail(stop));
|
|
80
106
|
}
|
|
81
107
|
}
|
|
82
108
|
const lines = [];
|
|
83
109
|
const state = label === "verification" ? "failed" : "blocked";
|
|
84
110
|
receiptRow(lines, "!", label, [{ text: state }, { text: "·" }, ...detail], columns);
|
|
111
|
+
lines.push(...prerequisiteRows(stop, columns));
|
|
85
112
|
if ("failure" in stop && stop.failure === "environment-failure" && "command" in stop) {
|
|
86
113
|
appendHookPayload(lines, stop.detail);
|
|
87
114
|
}
|
|
@@ -23,8 +23,6 @@ export declare function renderBoundedTextBlock(value: string, input: Readonly<{
|
|
|
23
23
|
truncated?: boolean;
|
|
24
24
|
}>): readonly string[];
|
|
25
25
|
export declare function safeText(value: string): string;
|
|
26
|
-
export declare function renderFacts(primary: string, facts: readonly string[], columns: number): readonly string[];
|
|
27
26
|
export declare function renderTextBlock(value: string, indent: string, columns: number): readonly string[];
|
|
28
27
|
export declare function renderOpaqueBlock(value: string, indent: string, columns: number): readonly string[];
|
|
29
|
-
export declare function renderVoiceRuler(left: string, right: string, columns: number): string;
|
|
30
28
|
export declare function tone(value: string, kind: "dim" | "alert", color: boolean): string;
|
|
@@ -110,28 +110,6 @@ export function renderBoundedTextBlock(value, input) {
|
|
|
110
110
|
export function safeText(value) {
|
|
111
111
|
return value.replaceAll(/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/gu, (character) => /\s/u.test(character) ? " " : "�");
|
|
112
112
|
}
|
|
113
|
-
export function renderFacts(primary, facts, columns) {
|
|
114
|
-
const head = safeText(primary);
|
|
115
|
-
const clean = facts.map(safeText);
|
|
116
|
-
if (clean.length === 0)
|
|
117
|
-
return [head];
|
|
118
|
-
const inline = `${head} ${clean.join(" · ")}`;
|
|
119
|
-
if (displayColumns(inline) <= columns)
|
|
120
|
-
return [inline];
|
|
121
|
-
const lines = [head];
|
|
122
|
-
let current = " ";
|
|
123
|
-
for (const fact of clean) {
|
|
124
|
-
const candidate = current === " " ? `${current}${fact}` : `${current} · ${fact}`;
|
|
125
|
-
if (current !== " " && displayColumns(candidate) > columns) {
|
|
126
|
-
lines.push(current);
|
|
127
|
-
current = ` ${fact}`;
|
|
128
|
-
}
|
|
129
|
-
else
|
|
130
|
-
current = candidate;
|
|
131
|
-
}
|
|
132
|
-
lines.push(current);
|
|
133
|
-
return lines;
|
|
134
|
-
}
|
|
135
113
|
export function renderTextBlock(value, indent, columns) {
|
|
136
114
|
const words = safeText(value).trim().split(/\s+/u).filter((word) => word.length > 0);
|
|
137
115
|
if (words.length === 0)
|
|
@@ -183,13 +161,6 @@ export function renderOpaqueBlock(value, indent, columns) {
|
|
|
183
161
|
}
|
|
184
162
|
return lines;
|
|
185
163
|
}
|
|
186
|
-
export function renderVoiceRuler(left, right, columns) {
|
|
187
|
-
const width = Math.max(20, Math.min(80, columns));
|
|
188
|
-
const occupied = displayColumns(left) + displayColumns(right) + 2;
|
|
189
|
-
if (occupied >= width)
|
|
190
|
-
return `${left}\n${"─".repeat(Math.max(1, width - displayColumns(right) - 1))} ${right}`;
|
|
191
|
-
return `${left} ${"─".repeat(width - occupied)} ${right}`;
|
|
192
|
-
}
|
|
193
164
|
export function tone(value, kind, color) {
|
|
194
165
|
if (!color)
|
|
195
166
|
return value;
|
|
@@ -11,11 +11,19 @@ export type BindDraftReceipt = Readonly<{
|
|
|
11
11
|
warning: string;
|
|
12
12
|
}>;
|
|
13
13
|
export type Effect = ReconcileReport["effects"][number];
|
|
14
|
-
|
|
14
|
+
type AcceptedFactEnvelope = Readonly<{
|
|
15
15
|
contract: ContractId;
|
|
16
16
|
entry: string;
|
|
17
|
-
kind: Fact["kind"];
|
|
18
17
|
}>;
|
|
18
|
+
export type AcceptedFact = (AcceptedFactEnvelope & Readonly<{
|
|
19
|
+
kind: Exclude<Fact["kind"], "reintegrated">;
|
|
20
|
+
data?: never;
|
|
21
|
+
}>) | (AcceptedFactEnvelope & Readonly<{
|
|
22
|
+
kind: "reintegrated";
|
|
23
|
+
data: Extract<Fact, {
|
|
24
|
+
kind: "reintegrated";
|
|
25
|
+
}>["data"];
|
|
26
|
+
}>);
|
|
19
27
|
export type Lag = ReconcileReport["lag"][number];
|
|
20
28
|
type MutationEnvelope = Pick<MutationResult<unknown>, "head" | "effects" | "settlement">;
|
|
21
29
|
export type AcceptedEnvelope = Readonly<{
|
|
@@ -80,18 +88,18 @@ export type AcceptedDeliverResult = AcceptedEnvelope & Readonly<{
|
|
|
80
88
|
export type AcceptedReviewResult = AcceptedEnvelope & Readonly<{
|
|
81
89
|
verb: "review";
|
|
82
90
|
verdict: "satisfied" | "unsatisfied";
|
|
91
|
+
verificationVerdict?: "satisfied" | "unsatisfied";
|
|
92
|
+
verification?: VerificationStop;
|
|
93
|
+
verificationReuse?: VerificationReuse;
|
|
83
94
|
placement?: PlacementStop;
|
|
84
95
|
workspace?: Review["workspace"];
|
|
96
|
+
cleanup?: MutationResult<unknown>["cleanup"];
|
|
97
|
+
leak?: MutationResult<unknown>["leak"];
|
|
85
98
|
target?: never;
|
|
86
|
-
verification?: never;
|
|
87
|
-
verificationReuse?: never;
|
|
88
|
-
cleanup?: never;
|
|
89
|
-
leak?: never;
|
|
90
99
|
overlaps?: never;
|
|
91
100
|
overlapFailure?: never;
|
|
92
101
|
report?: never;
|
|
93
102
|
diff?: never;
|
|
94
|
-
verificationVerdict?: never;
|
|
95
103
|
chapter?: never;
|
|
96
104
|
note?: never;
|
|
97
105
|
}>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DerivedFileAction } from "./coordination/durable-file.js";
|
|
2
2
|
import { type ContractId, type ContractState } from "./core/facts/types.js";
|
|
3
|
-
import { type GitRepository } from "./git/
|
|
3
|
+
import { type GitRepository } from "./git/process.js";
|
|
4
4
|
import { type PlaceRegister } from "./workspace-place.js";
|
|
5
5
|
export declare function renderContractGuidance(state: ContractState): string;
|
|
6
6
|
export type ContractFileEffect = Readonly<{
|
|
@@ -40,5 +40,4 @@ export type ContractReservation = Readonly<{
|
|
|
40
40
|
export declare function reserveContractWorktree(repository: GitRepository, contract: ContractId): Promise<ContractReservation>;
|
|
41
41
|
export declare function withContractWorktreeAppointment<T>(repository: GitRepository, action: () => T | Promise<T>): Promise<T>;
|
|
42
42
|
export declare function releaseContractWorktree(repository: GitRepository, contract: ContractId): Promise<void>;
|
|
43
|
-
export declare function removeContractWorktreeAppointment(repository: GitRepository, contract: ContractId): Promise<void>;
|
|
44
43
|
export declare function projectContractWorktree(repository: GitRepository, state: ContractState | null, register?: PlaceRegister): Promise<ContractWorktreeResult>;
|
|
@@ -3,9 +3,10 @@ import { join } from "node:path";
|
|
|
3
3
|
import { acquireSqliteTransactionLock } from "./coordination/sqlite-transaction-lock.js";
|
|
4
4
|
import { createFileDurablyExclusive, repairDerivedFile, } from "./coordination/durable-file.js";
|
|
5
5
|
import { contractId } from "./core/facts/types.js";
|
|
6
|
-
import {
|
|
6
|
+
import { worktreeGitDirectory, worktreeRoot, } from "./git/repository.js";
|
|
7
|
+
import { GitPlumbingError, runGit } from "./git/process.js";
|
|
7
8
|
import { worktreePath } from "./git/workspace.js";
|
|
8
|
-
import { appointmentFor, placeRegisterPath,
|
|
9
|
+
import { appointmentFor, placeRegisterPath, } from "./workspace-place.js";
|
|
9
10
|
const IGNORE_BYTES = ".gitignore\nKEIYAKU.md\n";
|
|
10
11
|
const APPOINTMENT_DESCRIPTION = "This is a read-only projection. Do not edit manually.";
|
|
11
12
|
function appointmentBytes(contract) {
|
|
@@ -132,12 +133,6 @@ export async function releaseContractWorktree(repository, contract) {
|
|
|
132
133
|
}
|
|
133
134
|
catch { /* reservation cleanup is best effort */ }
|
|
134
135
|
}
|
|
135
|
-
export async function removeContractWorktreeAppointment(repository, contract) {
|
|
136
|
-
const appointment = await readContractAppointment(repository);
|
|
137
|
-
if (appointment.kind !== "appointed" || appointment.contract !== contract)
|
|
138
|
-
return;
|
|
139
|
-
await unlink(appointment.path);
|
|
140
|
-
}
|
|
141
136
|
async function repair(repository, worktree, relativePath, bytes) {
|
|
142
137
|
const path = join(worktree, relativePath);
|
|
143
138
|
if (await isTracked(repository, relativePath))
|
|
@@ -238,7 +233,7 @@ export async function projectContractWorktree(repository, state, register) {
|
|
|
238
233
|
if (state.coordinates.workspace === "here") {
|
|
239
234
|
return await here(repository, state, renderContractGuidance(state));
|
|
240
235
|
}
|
|
241
|
-
const appointed =
|
|
236
|
+
const appointed = register === undefined ? undefined : appointmentFor(register, state.id);
|
|
242
237
|
if (appointed === undefined) {
|
|
243
238
|
return {
|
|
244
239
|
effects: [],
|
|
@@ -6,6 +6,7 @@ const VERSION_BY_KIND = {
|
|
|
6
6
|
amend: 1,
|
|
7
7
|
bound: 1,
|
|
8
8
|
deliver: 1,
|
|
9
|
+
reintegrated: 1,
|
|
9
10
|
attestation: 1,
|
|
10
11
|
claimed: 1,
|
|
11
12
|
arc: 1,
|
|
@@ -182,6 +183,14 @@ function validateData(kind, value) {
|
|
|
182
183
|
},
|
|
183
184
|
};
|
|
184
185
|
}
|
|
186
|
+
case "reintegrated": {
|
|
187
|
+
const object = requireRecord(value, path);
|
|
188
|
+
requireKeys(object, ["predecessor", "snapshot"], path);
|
|
189
|
+
return {
|
|
190
|
+
predecessor: brandedValue(object.predecessor, `${path}.predecessor`, snapshotId),
|
|
191
|
+
snapshot: brandedValue(object.snapshot, `${path}.snapshot`, snapshotId),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
185
194
|
case "attestation":
|
|
186
195
|
return validateAttestation(value, path);
|
|
187
196
|
case "claimed": {
|
|
@@ -24,6 +24,7 @@ function stateFromBind(id, head, bind, attestations) {
|
|
|
24
24
|
terms: cloneTerms(bind.data.terms),
|
|
25
25
|
bound: null,
|
|
26
26
|
delivery: null,
|
|
27
|
+
currentIntegration: null,
|
|
27
28
|
attestations,
|
|
28
29
|
terminal: null,
|
|
29
30
|
};
|
|
@@ -55,7 +56,18 @@ function foldEntry(state, entry, attestations) {
|
|
|
55
56
|
case "deliver":
|
|
56
57
|
if (state.bound === null)
|
|
57
58
|
foldError("deliver requires bound");
|
|
58
|
-
return { ...state, delivery: entry };
|
|
59
|
+
return { ...state, delivery: entry, currentIntegration: { ...entry.data.integration } };
|
|
60
|
+
case "reintegrated":
|
|
61
|
+
if (state.delivery === null)
|
|
62
|
+
foldError("reintegrated requires a deliver");
|
|
63
|
+
return {
|
|
64
|
+
...state,
|
|
65
|
+
currentIntegration: {
|
|
66
|
+
predecessor: entry.data.predecessor,
|
|
67
|
+
snapshot: entry.data.snapshot,
|
|
68
|
+
changeId: state.delivery.data.integration.changeId,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
59
71
|
case "attestation":
|
|
60
72
|
attestations.push(entry);
|
|
61
73
|
return { ...state, attestations };
|
|
@@ -85,6 +85,11 @@ export type DeliverData = Readonly<{
|
|
|
85
85
|
requireBranchesToBeUpToDate: boolean;
|
|
86
86
|
}>;
|
|
87
87
|
}>;
|
|
88
|
+
export type CurrentIntegration = DeliverData["integration"];
|
|
89
|
+
export type ReintegratedData = Readonly<{
|
|
90
|
+
predecessor: SnapshotId;
|
|
91
|
+
snapshot: SnapshotId;
|
|
92
|
+
}>;
|
|
88
93
|
export type AttestationData = Readonly<{
|
|
89
94
|
gate: Gate;
|
|
90
95
|
subject: DependencyKeySet;
|
|
@@ -116,11 +121,12 @@ export type BindEntry = JournalEnvelope<"bind", BindData>;
|
|
|
116
121
|
type AmendEntry = JournalEnvelope<"amend", AmendData>;
|
|
117
122
|
type BoundEntry = JournalEnvelope<"bound", BoundData>;
|
|
118
123
|
type DeliverEntry = JournalEnvelope<"deliver", DeliverData>;
|
|
124
|
+
export type ReintegratedEntry = JournalEnvelope<"reintegrated", ReintegratedData>;
|
|
119
125
|
export type AttestationEntry = JournalEnvelope<"attestation", AttestationData>;
|
|
120
126
|
type ClaimedEntry = JournalEnvelope<"claimed", ClaimedData>;
|
|
121
127
|
export type ArcEntry = JournalEnvelope<"arc", ArcData>;
|
|
122
128
|
type AbandonedEntry = JournalEnvelope<"abandoned", AbandonedData>;
|
|
123
|
-
export type JournalEntry = BindEntry | AmendEntry | BoundEntry | DeliverEntry | AttestationEntry | ClaimedEntry | ArcEntry | AbandonedEntry;
|
|
129
|
+
export type JournalEntry = BindEntry | AmendEntry | BoundEntry | DeliverEntry | ReintegratedEntry | AttestationEntry | ClaimedEntry | ArcEntry | AbandonedEntry;
|
|
124
130
|
export type FactKind = JournalEntry["kind"];
|
|
125
131
|
type ContractTerminal = ClaimedEntry | AbandonedEntry;
|
|
126
132
|
export type ContractState = Readonly<{
|
|
@@ -130,6 +136,7 @@ export type ContractState = Readonly<{
|
|
|
130
136
|
terms: ContractTerms;
|
|
131
137
|
bound: BoundEntry | null;
|
|
132
138
|
delivery: DeliverEntry | null;
|
|
139
|
+
currentIntegration: CurrentIntegration | null;
|
|
133
140
|
attestations: readonly AttestationEntry[];
|
|
134
141
|
currentArc?: ArcEntry;
|
|
135
142
|
terminal: ContractTerminal | null;
|
|
@@ -65,12 +65,13 @@ export function parseDependencyKeySet(value) {
|
|
|
65
65
|
return decodeDependencyKeySet(value).canonical;
|
|
66
66
|
}
|
|
67
67
|
function currentKeys(state) {
|
|
68
|
+
const integration = state.currentIntegration ?? state.delivery?.data.integration;
|
|
68
69
|
return new Set([
|
|
69
70
|
encodeKey({ kind: "document", value: state.terms.document.key }),
|
|
70
71
|
...state.terms.segments.map((value) => encodeKey({ kind: "segment", value })),
|
|
71
|
-
...(
|
|
72
|
-
encodeKey({ kind: "snapshot", value:
|
|
73
|
-
encodeKey({ kind: "change", value:
|
|
72
|
+
...(integration === undefined ? [] : [
|
|
73
|
+
encodeKey({ kind: "snapshot", value: integration.snapshot }),
|
|
74
|
+
encodeKey({ kind: "change", value: integration.changeId }),
|
|
74
75
|
]),
|
|
75
76
|
]);
|
|
76
77
|
}
|
|
@@ -5,9 +5,17 @@ type PlacementInput = Readonly<{
|
|
|
5
5
|
actor?: ActorId;
|
|
6
6
|
at: string;
|
|
7
7
|
}>;
|
|
8
|
+
export type UnmetPrerequisite = Readonly<{
|
|
9
|
+
contractId: ContractId;
|
|
10
|
+
state: "missing" | "active" | "abandoned";
|
|
11
|
+
}>;
|
|
8
12
|
export type PlacementRefusal = Readonly<{
|
|
9
|
-
kind: "contract-missing" | "delivery-missing" | "terminal" | "
|
|
13
|
+
kind: "contract-missing" | "delivery-missing" | "terminal" | "gates-unsatisfied";
|
|
14
|
+
contractId: ContractId;
|
|
15
|
+
}> | Readonly<{
|
|
16
|
+
kind: "prerequisites-unsatisfied";
|
|
10
17
|
contractId: ContractId;
|
|
18
|
+
unmet: readonly UnmetPrerequisite[];
|
|
11
19
|
}>;
|
|
12
20
|
export declare function decidePlacement({ input, attempt, observation }: DecideInput<PlacementInput>): OfferDecision<PlacementRefusal>;
|
|
13
21
|
export {};
|