@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
package/build/cli/flags.js
CHANGED
|
@@ -83,22 +83,37 @@ export const FLAG_SPECS = {
|
|
|
83
83
|
place: {
|
|
84
84
|
kind: "value",
|
|
85
85
|
placeholder: "NAME",
|
|
86
|
-
description: "
|
|
86
|
+
description: "Legacy bind title spelling; bind rejects it with --title migration guidance.",
|
|
87
87
|
},
|
|
88
88
|
objective: {
|
|
89
89
|
kind: "value",
|
|
90
90
|
placeholder: "TEXT",
|
|
91
91
|
description: "Set the objective for flag-generated bind Markdown.",
|
|
92
92
|
},
|
|
93
|
+
context: {
|
|
94
|
+
kind: "value",
|
|
95
|
+
placeholder: "TEXT",
|
|
96
|
+
description: "Set established facts and constraints for flag-generated bind Markdown.",
|
|
97
|
+
},
|
|
98
|
+
design: {
|
|
99
|
+
kind: "value",
|
|
100
|
+
placeholder: "TEXT",
|
|
101
|
+
description: "Set the settled design for flag-generated bind Markdown.",
|
|
102
|
+
},
|
|
93
103
|
scope: {
|
|
94
104
|
kind: "value",
|
|
95
105
|
placeholder: "GLOB",
|
|
96
106
|
description: "Set the single scope pattern for flag-generated bind Markdown.",
|
|
97
107
|
},
|
|
98
|
-
|
|
108
|
+
criteria: {
|
|
99
109
|
kind: "value",
|
|
100
|
-
placeholder: "
|
|
101
|
-
description: "Set the single acceptance
|
|
110
|
+
placeholder: "CRITERION",
|
|
111
|
+
description: "Set the single declarative acceptance criterion for flag-generated bind Markdown.",
|
|
112
|
+
},
|
|
113
|
+
verification: {
|
|
114
|
+
kind: "value",
|
|
115
|
+
placeholder: "DECLARATION",
|
|
116
|
+
description: "Set the single executable verification declaration for flag-generated bind Markdown.",
|
|
102
117
|
},
|
|
103
118
|
task: {
|
|
104
119
|
kind: "value",
|
|
@@ -132,17 +147,13 @@ export const FLAG_SPECS = {
|
|
|
132
147
|
kind: "boolean",
|
|
133
148
|
description: "Renew onto the current target before petitioning.",
|
|
134
149
|
},
|
|
135
|
-
resolve: {
|
|
136
|
-
kind: "boolean",
|
|
137
|
-
description: "Open a durable Keiyaku-owned renew recovery session when the rewrite conflicts.",
|
|
138
|
-
},
|
|
139
150
|
continue: {
|
|
140
151
|
kind: "boolean",
|
|
141
|
-
description: "Continue the
|
|
152
|
+
description: "Continue from the derived renew conflict scratch.",
|
|
142
153
|
},
|
|
143
154
|
abort: {
|
|
144
155
|
kind: "boolean",
|
|
145
|
-
description: "
|
|
156
|
+
description: "Delete the derived renew conflict scratch without moving authoritative refs.",
|
|
146
157
|
},
|
|
147
158
|
shell: {
|
|
148
159
|
kind: "value",
|
|
@@ -174,7 +185,7 @@ export const FLAG_SPECS = {
|
|
|
174
185
|
},
|
|
175
186
|
json: {
|
|
176
187
|
kind: "boolean",
|
|
177
|
-
description: "Render
|
|
188
|
+
description: "Render structured data as JSON.",
|
|
178
189
|
},
|
|
179
190
|
"diff-budget": {
|
|
180
191
|
kind: "value",
|
|
@@ -188,12 +199,12 @@ export const FLAG_SPECS = {
|
|
|
188
199
|
filter: {
|
|
189
200
|
kind: "value",
|
|
190
201
|
placeholder: TASK_FILTER_GRAMMAR,
|
|
191
|
-
description: "Filter structured
|
|
202
|
+
description: "Filter structured facts. Repeat --filter for AND; comma values or | terms are OR.",
|
|
192
203
|
},
|
|
193
204
|
sort: {
|
|
194
205
|
kind: "value",
|
|
195
206
|
placeholder: "KEY[,KEY...]",
|
|
196
|
-
description: "Sort
|
|
207
|
+
description: "Sort the selected structured collection.",
|
|
197
208
|
},
|
|
198
209
|
pri: {
|
|
199
210
|
kind: "value",
|
|
@@ -224,16 +235,41 @@ export const FLAG_SPECS = {
|
|
|
224
235
|
placeholder: "ID",
|
|
225
236
|
description: "Add a discovery-lineage task. May be repeated.",
|
|
226
237
|
},
|
|
238
|
+
supersedes: {
|
|
239
|
+
kind: "value",
|
|
240
|
+
placeholder: "ID",
|
|
241
|
+
description: "Record that this task supersedes another task. May be repeated.",
|
|
242
|
+
},
|
|
243
|
+
"drop-supersedes": {
|
|
244
|
+
kind: "value",
|
|
245
|
+
placeholder: "ID",
|
|
246
|
+
description: "Remove a supersedes relation. May be repeated.",
|
|
247
|
+
},
|
|
248
|
+
"relates-to": {
|
|
249
|
+
kind: "value",
|
|
250
|
+
placeholder: "ID",
|
|
251
|
+
description: "Record related work. May be repeated.",
|
|
252
|
+
},
|
|
253
|
+
"drop-relates-to": {
|
|
254
|
+
kind: "value",
|
|
255
|
+
placeholder: "ID",
|
|
256
|
+
description: "Remove a related-work relation. May be repeated.",
|
|
257
|
+
},
|
|
227
258
|
title: {
|
|
228
259
|
kind: "value",
|
|
229
260
|
placeholder: "TEXT",
|
|
230
|
-
description: "
|
|
261
|
+
description: "Set the bind document title or replace the task title.",
|
|
231
262
|
},
|
|
232
263
|
body: {
|
|
233
264
|
kind: "value",
|
|
234
265
|
placeholder: "TEXT|-",
|
|
235
266
|
description: "Replace the task body; literal - reads stdin.",
|
|
236
267
|
},
|
|
268
|
+
append: {
|
|
269
|
+
kind: "value",
|
|
270
|
+
placeholder: "TEXT|-",
|
|
271
|
+
description: "Append a Markdown paragraph to the task body; literal - reads stdin.",
|
|
272
|
+
},
|
|
237
273
|
};
|
|
238
274
|
export const CONTROL_FLAGS = new Set(Object.keys(FLAG_SPECS));
|
|
239
275
|
export const VALUE_FLAGS = new Set(Object.entries(FLAG_SPECS)
|
|
@@ -244,5 +280,6 @@ export const BOOLEAN_FLAGS = new Set(Object.entries(FLAG_SPECS)
|
|
|
244
280
|
.map(([name]) => name));
|
|
245
281
|
export const SHORT_FLAG_ALIASES = {
|
|
246
282
|
C: "cwd",
|
|
283
|
+
d: "detach",
|
|
247
284
|
f: "force",
|
|
248
285
|
};
|
package/build/cli/help.js
CHANGED
|
@@ -13,6 +13,9 @@ function flagUsage(name, specs) {
|
|
|
13
13
|
if (name === "cwd") {
|
|
14
14
|
return `-C, --cwd ${spec?.placeholder ?? "DIR"}`;
|
|
15
15
|
}
|
|
16
|
+
if (name === "detach") {
|
|
17
|
+
return "-d, --detach";
|
|
18
|
+
}
|
|
16
19
|
return spec?.kind === "value" ? `--${name} ${spec.placeholder ?? "VALUE"}` : `--${name}`;
|
|
17
20
|
}
|
|
18
21
|
export { CLI_COMMAND_METADATA };
|
|
@@ -69,7 +72,7 @@ export function renderCliHelp(version) {
|
|
|
69
72
|
"Configuration:",
|
|
70
73
|
" Akuma profiles <KEIYAKU_HOME>/akuma/*.md or .keiyaku/akuma/*.md",
|
|
71
74
|
" Settings <KEIYAKU_HOME>/settings.json or .keiyaku/settings.json",
|
|
72
|
-
" Inspect keiyaku akuma ls | keiyaku akuma
|
|
75
|
+
" Inspect keiyaku akuma ls | keiyaku akuma show NAME",
|
|
73
76
|
" Environment keiyaku dump-env",
|
|
74
77
|
" Full format README Configuration",
|
|
75
78
|
].join("\n");
|
package/build/cli/index.js
CHANGED
|
@@ -23,42 +23,54 @@ function commandSavesFailedStdin(command) {
|
|
|
23
23
|
return (commandRequiresStdin(command) || commandAcceptsOptionalStdin(command)) && command !== "call";
|
|
24
24
|
}
|
|
25
25
|
function hasBindDomainFlags(flags) {
|
|
26
|
-
return (flags.
|
|
26
|
+
return (flags.bindTitle !== undefined
|
|
27
|
+
|| flags.bindContext !== undefined
|
|
27
28
|
|| flags.bindObjective !== undefined
|
|
29
|
+
|| flags.bindDesign !== undefined
|
|
28
30
|
|| flags.bindScope !== undefined
|
|
29
|
-
|| flags.
|
|
31
|
+
|| flags.bindCriteria !== undefined
|
|
32
|
+
|| flags.bindVerification !== undefined);
|
|
30
33
|
}
|
|
31
|
-
function prepareBindInput(stdin, flags) {
|
|
34
|
+
function prepareBindInput(stdin, flags, selectsStdin) {
|
|
35
|
+
if (flags.contractId !== undefined)
|
|
36
|
+
return "";
|
|
32
37
|
const nonblankStdin = stdin.trim().length > 0;
|
|
33
38
|
const domainFlags = hasBindDomainFlags(flags);
|
|
34
39
|
if (flags.dryRun && flags.draftOnly) {
|
|
35
40
|
throw new FlowError("EMPTY_PARAM", "--dry-run cannot be combined with --draft-only");
|
|
36
41
|
}
|
|
37
|
-
if (
|
|
38
|
-
throw new FlowError("EMPTY_PARAM", "bind accepts either stdin Markdown or
|
|
42
|
+
if (selectsStdin && domainFlags) {
|
|
43
|
+
throw new FlowError("EMPTY_PARAM", "bind accepts either stdin Markdown or domain flags, not both");
|
|
39
44
|
}
|
|
40
45
|
if (domainFlags) {
|
|
41
46
|
const missing = [];
|
|
42
|
-
if (flags.
|
|
43
|
-
missing.push("--
|
|
47
|
+
if (flags.bindTitle === undefined)
|
|
48
|
+
missing.push("--title");
|
|
49
|
+
if (flags.bindContext === undefined)
|
|
50
|
+
missing.push("--context");
|
|
44
51
|
if (flags.bindObjective === undefined)
|
|
45
52
|
missing.push("--objective");
|
|
53
|
+
if (flags.bindDesign === undefined)
|
|
54
|
+
missing.push("--design");
|
|
46
55
|
if (flags.bindScope === undefined)
|
|
47
56
|
missing.push("--scope");
|
|
48
|
-
if (flags.
|
|
49
|
-
missing.push("--
|
|
50
|
-
if (missing.length > 0) {
|
|
51
|
-
throw new FlowError("EMPTY_PARAM", `bind flag mode requires --
|
|
57
|
+
if (flags.bindCriteria === undefined)
|
|
58
|
+
missing.push("--criteria");
|
|
59
|
+
if (missing.length > 0 && (flags.bindTaskIds?.length ?? 0) === 0) {
|
|
60
|
+
throw new FlowError("EMPTY_PARAM", `bind flag mode requires --title, --context, --objective, --design, --scope, and --criteria; missing ${missing.join(", ")}`);
|
|
52
61
|
}
|
|
53
62
|
return compileBindDraftFlags({
|
|
54
|
-
|
|
63
|
+
title: flags.bindTitle,
|
|
64
|
+
context: flags.bindContext,
|
|
55
65
|
objective: flags.bindObjective,
|
|
66
|
+
design: flags.bindDesign,
|
|
56
67
|
scope: flags.bindScope,
|
|
57
|
-
|
|
68
|
+
criteria: flags.bindCriteria,
|
|
69
|
+
verification: flags.bindVerification,
|
|
58
70
|
});
|
|
59
71
|
}
|
|
60
72
|
if (!nonblankStdin) {
|
|
61
|
-
// --task may supply
|
|
73
|
+
// --task may supply title/objective defaults; core merges and reports missing sections.
|
|
62
74
|
if (flags.bindTaskIds !== undefined && flags.bindTaskIds.length > 0) {
|
|
63
75
|
return "";
|
|
64
76
|
}
|
|
@@ -76,6 +88,7 @@ async function readStdin() {
|
|
|
76
88
|
function makeAbortSignal() {
|
|
77
89
|
const controller = new AbortController();
|
|
78
90
|
process.once("SIGINT", () => controller.abort());
|
|
91
|
+
process.once("SIGTERM", () => controller.abort());
|
|
79
92
|
return controller.signal;
|
|
80
93
|
}
|
|
81
94
|
function responseText(response) {
|
|
@@ -93,8 +106,8 @@ async function saveFailedStdin(input) {
|
|
|
93
106
|
/**
|
|
94
107
|
* Rebuild bind flags for a failed-stdin retry in deterministic shell-safe order.
|
|
95
108
|
* Order follows bind usage/parse authority: cwd, repo, after, exclusive,
|
|
96
|
-
* draft-only, task. Domain-flag bind does not save stdin, so
|
|
97
|
-
* scope/
|
|
109
|
+
* draft-only, task. Domain-flag bind does not save stdin, so title/objective/
|
|
110
|
+
* scope/criteria are not reconstructed. --dry-run never reaches this path.
|
|
98
111
|
*/
|
|
99
112
|
function bindRetryFlagTokens(flags) {
|
|
100
113
|
const tokens = [];
|
|
@@ -190,13 +203,13 @@ function selectedArgument(parsed) {
|
|
|
190
203
|
return undefined;
|
|
191
204
|
return { token, replace: () => parsed.flags };
|
|
192
205
|
}
|
|
193
|
-
const flagName = stdin.selector.name;
|
|
194
|
-
const token = parsed.flags[flagName];
|
|
206
|
+
const flagName = stdin.selector.names.find((name) => parsed.flags[name] !== undefined);
|
|
207
|
+
const token = flagName === undefined ? undefined : parsed.flags[flagName];
|
|
195
208
|
if (token === undefined && !stdin.selector.required)
|
|
196
209
|
return undefined;
|
|
197
210
|
return {
|
|
198
211
|
token,
|
|
199
|
-
replace: (value) => ({ ...parsed.flags, [flagName]: value }),
|
|
212
|
+
replace: (value) => flagName === undefined ? parsed.flags : ({ ...parsed.flags, [flagName]: value }),
|
|
200
213
|
};
|
|
201
214
|
}
|
|
202
215
|
async function resolveCliInput(parsed) {
|
|
@@ -221,7 +234,7 @@ async function resolveCliInput(parsed) {
|
|
|
221
234
|
: `${parsed.command} body cannot be empty`;
|
|
222
235
|
throw new FlowError("EMPTY_PARAM", message);
|
|
223
236
|
}
|
|
224
|
-
return { stdin: input, flags: selected?.replace(input) ?? parsed.flags };
|
|
237
|
+
return { stdin: input, flags: selected?.replace(input) ?? parsed.flags, selectsStdin };
|
|
225
238
|
}
|
|
226
239
|
function usageExample(command) {
|
|
227
240
|
const meta = getCommandMetadata(command);
|
|
@@ -242,9 +255,11 @@ export async function runCliCommand(tokens) {
|
|
|
242
255
|
}
|
|
243
256
|
const cwd = parsed.flags.cwd ?? process.cwd();
|
|
244
257
|
let stdin;
|
|
258
|
+
let selectsStdin = false;
|
|
245
259
|
try {
|
|
246
260
|
const resolved = await resolveCliInput(parsed);
|
|
247
261
|
stdin = resolved.stdin;
|
|
262
|
+
selectsStdin = resolved.selectsStdin;
|
|
248
263
|
parsed = { ...parsed, flags: resolved.flags };
|
|
249
264
|
}
|
|
250
265
|
catch (error) {
|
|
@@ -255,7 +270,7 @@ export async function runCliCommand(tokens) {
|
|
|
255
270
|
// repository admission as bind but does not persist an artifact on failure.
|
|
256
271
|
if (parsed.command === "bind") {
|
|
257
272
|
try {
|
|
258
|
-
stdin = prepareBindInput(stdin, parsed.flags);
|
|
273
|
+
stdin = prepareBindInput(stdin, parsed.flags, selectsStdin);
|
|
259
274
|
}
|
|
260
275
|
catch (error) {
|
|
261
276
|
await printFailure(error, cwd);
|
|
@@ -267,7 +282,7 @@ export async function runCliCommand(tokens) {
|
|
|
267
282
|
response = await runResponse(parsed.command, parsed.flags, stdin, parsed.positional);
|
|
268
283
|
}
|
|
269
284
|
catch (error) {
|
|
270
|
-
if (commandRequiresStdin(parsed.command) || (parsed.command === "bind" && !parsed.flags.dryRun)) {
|
|
285
|
+
if (commandRequiresStdin(parsed.command) || (parsed.command === "bind" && !parsed.flags.dryRun && parsed.flags.contractId === undefined)) {
|
|
271
286
|
return await handleFailureAfterStdin({
|
|
272
287
|
error,
|
|
273
288
|
cwd,
|
|
@@ -282,12 +297,12 @@ export async function runCliCommand(tokens) {
|
|
|
282
297
|
return 2;
|
|
283
298
|
return failureExitCode(error);
|
|
284
299
|
}
|
|
285
|
-
const success = !response.payload || !("error" in response.payload);
|
|
300
|
+
const success = !response.isDomainFailure && (!response.payload || !("error" in response.payload));
|
|
286
301
|
if (success) {
|
|
287
302
|
await writeSuccessResponse(parsed.command, parsed.flags, response);
|
|
288
303
|
return response.exitCode ?? 0;
|
|
289
304
|
}
|
|
290
|
-
if (commandRequiresStdin(parsed.command) || (parsed.command === "bind" && !parsed.flags.dryRun)) {
|
|
305
|
+
if (commandRequiresStdin(parsed.command) || (parsed.command === "bind" && !parsed.flags.dryRun && parsed.flags.contractId === undefined)) {
|
|
291
306
|
return await handleFailureAfterStdin({
|
|
292
307
|
response,
|
|
293
308
|
cwd,
|
|
@@ -298,7 +313,7 @@ export async function runCliCommand(tokens) {
|
|
|
298
313
|
});
|
|
299
314
|
}
|
|
300
315
|
await writeCliOutput(process.stderr, `${responseText(response)}\n`);
|
|
301
|
-
return 1;
|
|
316
|
+
return response.exitCode ?? 1;
|
|
302
317
|
}
|
|
303
318
|
export function renderCliCommandHelp(command) {
|
|
304
319
|
const meta = getCommandMetadata(command);
|
package/build/cli/parse-flags.js
CHANGED
|
@@ -75,17 +75,35 @@ export function assignFlag(flags, name, value) {
|
|
|
75
75
|
}
|
|
76
76
|
flags.bindObjective = String(value);
|
|
77
77
|
return;
|
|
78
|
+
case "context":
|
|
79
|
+
if (flags.bindContext !== undefined) {
|
|
80
|
+
throw new FlowError("EMPTY_PARAM", "option --context may only be specified once");
|
|
81
|
+
}
|
|
82
|
+
flags.bindContext = String(value);
|
|
83
|
+
return;
|
|
84
|
+
case "design":
|
|
85
|
+
if (flags.bindDesign !== undefined) {
|
|
86
|
+
throw new FlowError("EMPTY_PARAM", "option --design may only be specified once");
|
|
87
|
+
}
|
|
88
|
+
flags.bindDesign = String(value);
|
|
89
|
+
return;
|
|
78
90
|
case "scope":
|
|
79
91
|
if (flags.bindScope !== undefined) {
|
|
80
92
|
throw new FlowError("EMPTY_PARAM", "option --scope may only be specified once");
|
|
81
93
|
}
|
|
82
94
|
flags.bindScope = String(value);
|
|
83
95
|
return;
|
|
84
|
-
case "
|
|
85
|
-
if (flags.
|
|
86
|
-
throw new FlowError("EMPTY_PARAM", "option --
|
|
96
|
+
case "criteria":
|
|
97
|
+
if (flags.bindCriteria !== undefined) {
|
|
98
|
+
throw new FlowError("EMPTY_PARAM", "option --criteria may only be specified once");
|
|
87
99
|
}
|
|
88
|
-
flags.
|
|
100
|
+
flags.bindCriteria = String(value);
|
|
101
|
+
return;
|
|
102
|
+
case "verification":
|
|
103
|
+
if (flags.bindVerification !== undefined) {
|
|
104
|
+
throw new FlowError("EMPTY_PARAM", "option --verification may only be specified once");
|
|
105
|
+
}
|
|
106
|
+
flags.bindVerification = String(value);
|
|
89
107
|
return;
|
|
90
108
|
case "task":
|
|
91
109
|
flags.bindTaskIds = [...(flags.bindTaskIds ?? []), String(value)];
|
|
@@ -108,9 +126,6 @@ export function assignFlag(flags, name, value) {
|
|
|
108
126
|
case "renew":
|
|
109
127
|
flags.renewBeforePetition = Boolean(value);
|
|
110
128
|
return;
|
|
111
|
-
case "resolve":
|
|
112
|
-
flags.renewResolve = Boolean(value);
|
|
113
|
-
return;
|
|
114
129
|
case "continue":
|
|
115
130
|
flags.renewContinue = Boolean(value);
|
|
116
131
|
return;
|
|
@@ -184,6 +199,18 @@ export function assignFlag(flags, name, value) {
|
|
|
184
199
|
case "from":
|
|
185
200
|
flags.taskFrom = [...(flags.taskFrom ?? []), String(value)];
|
|
186
201
|
return;
|
|
202
|
+
case "supersedes":
|
|
203
|
+
flags.taskSupersedes = [...(flags.taskSupersedes ?? []), String(value)];
|
|
204
|
+
return;
|
|
205
|
+
case "drop-supersedes":
|
|
206
|
+
flags.taskDropSupersedes = [...(flags.taskDropSupersedes ?? []), String(value)];
|
|
207
|
+
return;
|
|
208
|
+
case "relates-to":
|
|
209
|
+
flags.taskRelatesTo = [...(flags.taskRelatesTo ?? []), String(value)];
|
|
210
|
+
return;
|
|
211
|
+
case "drop-relates-to":
|
|
212
|
+
flags.taskDropRelatesTo = [...(flags.taskDropRelatesTo ?? []), String(value)];
|
|
213
|
+
return;
|
|
187
214
|
case "parent":
|
|
188
215
|
if (flags.taskParent !== undefined) {
|
|
189
216
|
throw new FlowError("EMPTY_PARAM", "option --parent may only be specified once");
|
|
@@ -205,6 +232,12 @@ export function assignFlag(flags, name, value) {
|
|
|
205
232
|
}
|
|
206
233
|
flags.taskBody = String(value);
|
|
207
234
|
return;
|
|
235
|
+
case "append":
|
|
236
|
+
if (flags.taskAppend !== undefined) {
|
|
237
|
+
throw new FlowError("EMPTY_PARAM", "option --append may only be specified once");
|
|
238
|
+
}
|
|
239
|
+
flags.taskAppend = String(value);
|
|
240
|
+
return;
|
|
208
241
|
default:
|
|
209
242
|
throw new FlowError("EMPTY_PARAM", `unknown option: --${name}`);
|
|
210
243
|
}
|
|
@@ -56,7 +56,7 @@ export function parseWaitTimeout(value) {
|
|
|
56
56
|
return timeoutMs;
|
|
57
57
|
}
|
|
58
58
|
export function commandPositionalRange(command) {
|
|
59
|
-
if (command === "akuma
|
|
59
|
+
if (command === "akuma show") {
|
|
60
60
|
return { min: 1, max: 1, label: "<name>" };
|
|
61
61
|
}
|
|
62
62
|
if (command === "log") {
|
|
@@ -80,10 +80,13 @@ export function commandPositionalRange(command) {
|
|
|
80
80
|
if (command === "status") {
|
|
81
81
|
return { min: 0, max: 1, label: "[projection-id]" };
|
|
82
82
|
}
|
|
83
|
+
if (command === "history") {
|
|
84
|
+
return { min: 0, max: 1, label: "[projection|alias|rsp]" };
|
|
85
|
+
}
|
|
83
86
|
if (command === "task add") {
|
|
84
87
|
return { min: 1, max: 1, label: "<BODY|->" };
|
|
85
88
|
}
|
|
86
|
-
if (command === "task show" || command === "task log" || command === "task start" || command === "task drop") {
|
|
89
|
+
if (command === "task show" || command === "task log" || command === "task start" || command === "task hold" || command === "task resume" || command === "task drop") {
|
|
87
90
|
return { min: 1, max: 1, label: "<ID>" };
|
|
88
91
|
}
|
|
89
92
|
if (command === "task update") {
|
|
@@ -2,6 +2,7 @@ import { FlowError } from "../flow-error.js";
|
|
|
2
2
|
import { assignFlag } from "./parse-flags.js";
|
|
3
3
|
import { normalizeContractAddress } from "./parse-metadata.js";
|
|
4
4
|
const COMMISSION_SELECTOR_COMMANDS = new Set([
|
|
5
|
+
"bind",
|
|
5
6
|
"arc",
|
|
6
7
|
"amend",
|
|
7
8
|
"call",
|
|
@@ -45,9 +46,7 @@ export function assertCommissionSelectorAllowed(command, flags) {
|
|
|
45
46
|
if (flags.contractId === undefined || COMMISSION_SELECTOR_COMMANDS.has(command)) {
|
|
46
47
|
return;
|
|
47
48
|
}
|
|
48
|
-
throw new FlowError("EMPTY_PARAM",
|
|
49
|
-
? `bind creates a commission and does not accept @${flags.contractId}; use -C/--cwd to select the repository`
|
|
50
|
-
: `contract address @${flags.contractId} is not valid for ${command}`);
|
|
49
|
+
throw new FlowError("EMPTY_PARAM", `contract address @${flags.contractId} is not valid for ${command}`);
|
|
51
50
|
}
|
|
52
51
|
export function assertProjectionSelectorPresent(command, flags, atTokens, contractFlagRaws, restLength, payloadLength) {
|
|
53
52
|
if ((command !== "wait" && command !== "tell") || flags.contractId === undefined) {
|
package/build/cli/parse.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FlowError } from "../flow-error.js";
|
|
2
2
|
import { agentNameSchema } from "../config/settings/schema.js";
|
|
3
3
|
import { isResponseArtifactId } from "../core/response-artifact-id.js";
|
|
4
|
+
import { isCommissionId } from "../core/ids.js";
|
|
4
5
|
import { HELP_FLAGS } from "./flags.js";
|
|
5
6
|
import { getCommandMetadata } from "./commands/metadata.js";
|
|
6
7
|
import { assertAllowedFlag, assignFlag, BOOLEAN_FLAGS, CONTROL_FLAGS, parseFlagName, readValueFlag, SHORT_FLAG_ALIASES, VALUE_FLAGS, } from "./parse-flags.js";
|
|
@@ -102,7 +103,7 @@ export function parseCliArgs(tokens) {
|
|
|
102
103
|
};
|
|
103
104
|
}
|
|
104
105
|
if (command === "akuma") {
|
|
105
|
-
throw new FlowError("EMPTY_PARAM", "akuma requires subcommand: ls or
|
|
106
|
+
throw new FlowError("EMPTY_PARAM", "akuma requires subcommand: ls or show");
|
|
106
107
|
}
|
|
107
108
|
if (command === "skills") {
|
|
108
109
|
throw new FlowError("EMPTY_PARAM", "skills requires subcommand: install");
|
|
@@ -110,12 +111,19 @@ export function parseCliArgs(tokens) {
|
|
|
110
111
|
if (command === "task") {
|
|
111
112
|
throw new FlowError("EMPTY_PARAM", `task requires subcommand: ${TASK_SUBCOMMANDS.join(", ")}`);
|
|
112
113
|
}
|
|
113
|
-
if (
|
|
114
|
+
if (seenFlagNames.has("place")) {
|
|
115
|
+
if (command === "bind") {
|
|
116
|
+
throw new FlowError("EMPTY_PARAM", "bind no longer accepts --place; use --title <text>");
|
|
117
|
+
}
|
|
114
118
|
throw new FlowError("EMPTY_PARAM", "unknown option --place; use @addr or --contract <addr>");
|
|
115
119
|
}
|
|
116
120
|
for (const name of seenFlagNames) {
|
|
117
121
|
assertAllowedFlag(command, name);
|
|
118
122
|
}
|
|
123
|
+
if (command === "bind" && flags.taskTitle !== undefined) {
|
|
124
|
+
flags.bindTitle = flags.taskTitle;
|
|
125
|
+
delete flags.taskTitle;
|
|
126
|
+
}
|
|
119
127
|
if (command === "call" && flags.detach && flags.timeoutMs !== undefined) {
|
|
120
128
|
throw new FlowError("EMPTY_PARAM", "call cannot combine --detach and --wait");
|
|
121
129
|
}
|
|
@@ -128,9 +136,14 @@ export function parseCliArgs(tokens) {
|
|
|
128
136
|
if (command === "task update" && flags.taskParent !== undefined && flags.taskNoParent) {
|
|
129
137
|
throw new FlowError("EMPTY_PARAM", "task update cannot combine --parent and --no-parent");
|
|
130
138
|
}
|
|
131
|
-
if (command === "task update" && flags.
|
|
139
|
+
if (command === "task update" && flags.taskBody !== undefined && flags.taskAppend !== undefined) {
|
|
140
|
+
throw new FlowError("EMPTY_PARAM", "task update cannot combine --body and --append");
|
|
141
|
+
}
|
|
142
|
+
if (command === "task update" && flags.taskTitle === undefined && flags.taskBody === undefined && flags.taskAppend === undefined
|
|
132
143
|
&& flags.taskPri === undefined && flags.taskNeeds === undefined && flags.taskDropNeeds === undefined
|
|
133
|
-
&& flags.taskParent === undefined && !flags.taskNoParent && flags.taskFrom === undefined
|
|
144
|
+
&& flags.taskParent === undefined && !flags.taskNoParent && flags.taskFrom === undefined
|
|
145
|
+
&& flags.taskSupersedes === undefined && flags.taskDropSupersedes === undefined
|
|
146
|
+
&& flags.taskRelatesTo === undefined && flags.taskDropRelatesTo === undefined) {
|
|
134
147
|
throw new FlowError("EMPTY_PARAM", "task update requires at least one change");
|
|
135
148
|
}
|
|
136
149
|
if (command === "petition" && flags.json && !flags.dryRun) {
|
|
@@ -140,9 +153,9 @@ export function parseCliArgs(tokens) {
|
|
|
140
153
|
throw new FlowError("EMPTY_PARAM", "petition --dry-run does not accept --append-scope");
|
|
141
154
|
}
|
|
142
155
|
if (command === "renew") {
|
|
143
|
-
const recoveryModes = [flags.
|
|
156
|
+
const recoveryModes = [flags.renewContinue, flags.renewAbort].filter(Boolean).length;
|
|
144
157
|
if (recoveryModes > 1) {
|
|
145
|
-
throw new FlowError("EMPTY_PARAM", "renew accepts only one of --
|
|
158
|
+
throw new FlowError("EMPTY_PARAM", "renew accepts only one of --continue or --abort");
|
|
146
159
|
}
|
|
147
160
|
if (flags.renewAbort && (flags.appendScope?.length ?? 0) > 0) {
|
|
148
161
|
throw new FlowError("EMPTY_PARAM", "renew --abort does not accept --append-scope");
|
|
@@ -151,6 +164,27 @@ export function parseCliArgs(tokens) {
|
|
|
151
164
|
assertCommissionSelectorAllowed(command, flags);
|
|
152
165
|
assertProjectionSelectorPresent(command, flags, atTokens, contractFlagRaws, rest.length, payload.length);
|
|
153
166
|
const positional = [...rest, ...payload];
|
|
167
|
+
if (command === "bind" && flags.contractId !== undefined) {
|
|
168
|
+
if (!isCommissionId(flags.contractId)) {
|
|
169
|
+
throw new FlowError("EMPTY_PARAM", `bind replay requires a full canonical contract id; got ${flags.contractId}`);
|
|
170
|
+
}
|
|
171
|
+
const hasReplayInput = positional.length > 0
|
|
172
|
+
|| flags.bindTaskIds !== undefined
|
|
173
|
+
|| flags.after !== undefined
|
|
174
|
+
|| flags.exclusive === true
|
|
175
|
+
|| flags.draftOnly === true
|
|
176
|
+
|| flags.dryRun === true
|
|
177
|
+
|| flags.bindTitle !== undefined
|
|
178
|
+
|| flags.bindContext !== undefined
|
|
179
|
+
|| flags.bindObjective !== undefined
|
|
180
|
+
|| flags.bindDesign !== undefined
|
|
181
|
+
|| flags.bindScope !== undefined
|
|
182
|
+
|| flags.bindCriteria !== undefined
|
|
183
|
+
|| flags.bindVerification !== undefined;
|
|
184
|
+
if (hasReplayInput) {
|
|
185
|
+
throw new FlowError("EMPTY_PARAM", "addressed bind is replay-only and accepts no draft or creation input");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
154
188
|
if (command === "wait") {
|
|
155
189
|
if (positional.length === 0 && !flags.contractId) {
|
|
156
190
|
throw new FlowError("EMPTY_PARAM", "wait requires <projection-address>");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { AddressResolutionError, buildObjectResolutionAttempt, } from "../core/addressing.js";
|
|
4
|
-
import { assertProjectionTellable, resolveProjectionCoordinate } from "../core/projection/index.js";
|
|
5
|
-
import { isProjectionId
|
|
6
|
-
import { isProjectionAlias,
|
|
4
|
+
import { assertProjectionTellable, projectionAliasRootAtCoordinate, projectionDirAtCoordinate, resolveProjectionCoordinate, } from "../core/projection/index.js";
|
|
5
|
+
import { isProjectionId } from "../core/projection/index.js";
|
|
6
|
+
import { isProjectionAlias, readProjectionAliasAtRoot } from "../core/projection/index.js";
|
|
7
7
|
import { readProjectionIdentity } from "../core/projection/index.js";
|
|
8
8
|
import { isResponseArtifactId } from "../core/response-artifact-id.js";
|
|
9
9
|
import { isErrnoException } from "../errno.js";
|
|
@@ -22,11 +22,14 @@ export async function resolveProjectionAddress(input) {
|
|
|
22
22
|
// Scoped lookup reuses the commission carrier's repository root: zero Git probes.
|
|
23
23
|
// Unscoped lookup performs exactly one coordinate probe.
|
|
24
24
|
let repo;
|
|
25
|
-
let
|
|
25
|
+
let coordinate;
|
|
26
26
|
let attempt;
|
|
27
27
|
if (input.scope) {
|
|
28
28
|
repo = input.scope.repo;
|
|
29
|
-
|
|
29
|
+
coordinate = {
|
|
30
|
+
physicalRoot: input.scope.repo.stableRoot,
|
|
31
|
+
authority: { kind: "repository", stableRoot: input.scope.repo.stableRoot },
|
|
32
|
+
};
|
|
30
33
|
attempt = buildObjectResolutionAttempt({
|
|
31
34
|
repo,
|
|
32
35
|
workdir,
|
|
@@ -40,11 +43,10 @@ export async function resolveProjectionAddress(input) {
|
|
|
40
43
|
});
|
|
41
44
|
}
|
|
42
45
|
else {
|
|
43
|
-
|
|
46
|
+
coordinate = input.coordinate ?? await resolveProjectionCoordinate(input.cwd);
|
|
44
47
|
repo = coordinate.authority.kind === "repository"
|
|
45
48
|
? { kind: "repository", stableRoot: coordinate.authority.stableRoot }
|
|
46
49
|
: { kind: "user" };
|
|
47
|
-
physicalRoot = coordinate.physicalRoot;
|
|
48
50
|
attempt = buildObjectResolutionAttempt({
|
|
49
51
|
repo,
|
|
50
52
|
workdir,
|
|
@@ -69,13 +71,13 @@ export async function resolveProjectionAddress(input) {
|
|
|
69
71
|
else {
|
|
70
72
|
if (!isProjectionAlias(input.address))
|
|
71
73
|
throw new AddressResolutionError("EMPTY_PARAM", `projection alias ${input.address} has no match ${suffix}`, attempt);
|
|
72
|
-
const target = await
|
|
74
|
+
const target = await readProjectionAliasAtRoot(projectionAliasRootAtCoordinate(coordinate), input.address);
|
|
73
75
|
if (!target)
|
|
74
76
|
throw new AddressResolutionError("EMPTY_PARAM", `projection alias ${input.address} has no match ${suffix}`, attempt);
|
|
75
77
|
id = target;
|
|
76
78
|
alias = input.address;
|
|
77
79
|
}
|
|
78
|
-
const directory =
|
|
80
|
+
const directory = projectionDirAtCoordinate(coordinate, id);
|
|
79
81
|
if (!isRealDirectory(directory)) {
|
|
80
82
|
const subject = alias ? `projection alias ${alias} points to missing projection ${id}` : `projection ${id}`;
|
|
81
83
|
throw new AddressResolutionError("EMPTY_PARAM", `${subject} has no match ${suffix}`, attempt);
|
|
@@ -99,5 +101,5 @@ export async function resolveProjectionAddress(input) {
|
|
|
99
101
|
if (input.scope && (identity.binding.kind !== "commission" || identity.binding.commissionId !== input.scope.binding.commissionId)) {
|
|
100
102
|
throw new AddressResolutionError("EMPTY_PARAM", `projection ${id} has no match ${suffix}`, attempt);
|
|
101
103
|
}
|
|
102
|
-
return { id, ...(alias ? { alias } : {}) };
|
|
104
|
+
return { id, directory, ...(alias ? { alias } : {}) };
|
|
103
105
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function renderAmendmentWarning(warning) {
|
|
2
|
+
return [
|
|
3
|
+
`You have amended this contract ${warning.amendmentCount} times. Consider whether its intent has drifted.`,
|
|
4
|
+
"If the original intent is complete, move the remaining work to a task and start a new Keiyaku.",
|
|
5
|
+
"If this contract no longer fits the work, forfeit it and bind a new one.",
|
|
6
|
+
"If the amendments are intentional and the contract still fits, continue.",
|
|
7
|
+
].join(" ");
|
|
8
|
+
}
|
package/build/cli/render/arc.js
CHANGED
|
@@ -4,6 +4,7 @@ import { assembleResponse, buildPayload, buildSection, formatHints, formatList,
|
|
|
4
4
|
import { DIFF_OVERVIEW_SECTION_TITLE, RESPONSE_MARKERS, WARNING_SECTION_TITLE } from "./response-style.js";
|
|
5
5
|
import { appendPersistenceSummary, CONTENT_SECTION_TITLE, HINTS_LIST_MAX_ITEMS, HINTS_SECTION_TITLE, INFO_COMMIT_MAX_CHARS, INFO_PLEA_MAX_CHARS, INFO_SECTION_TITLE, } from "./shared.js";
|
|
6
6
|
import { prependAddressReceipt } from "./address.js";
|
|
7
|
+
import { renderAmendmentWarning } from "./amendment-warning.js";
|
|
7
8
|
function sealLines(result) {
|
|
8
9
|
if (!result.sealed)
|
|
9
10
|
return ["nothing sealed"];
|
|
@@ -55,7 +56,7 @@ export function buildRenewAbortResponse(result) {
|
|
|
55
56
|
const payload = {
|
|
56
57
|
contractId: result.contractId,
|
|
57
58
|
oldHead: result.oldHead,
|
|
58
|
-
|
|
59
|
+
scratchName: result.scratchName,
|
|
59
60
|
summary: result.summary,
|
|
60
61
|
};
|
|
61
62
|
return prependAddressReceipt({ text: result.summary, payload }, result.address);
|
|
@@ -68,8 +69,11 @@ export function buildAmendResponse(result) {
|
|
|
68
69
|
...formatMaybe("Amendment", String(result.amendmentNumber), INFO_COMMIT_MAX_CHARS),
|
|
69
70
|
...formatMaybe("Ledger Commit", renderedLedgerCommit, INFO_COMMIT_MAX_CHARS),
|
|
70
71
|
]);
|
|
72
|
+
const warningSection = result.amendmentWarning
|
|
73
|
+
? buildSection(WARNING_SECTION_TITLE, renderAmendmentWarning(result.amendmentWarning))
|
|
74
|
+
: null;
|
|
71
75
|
return prependAddressReceipt({
|
|
72
|
-
text: assembleResponse(`${RESPONSE_MARKERS.arc} Amended`, `Amended contract ledger with Amendment ${result.amendmentNumber} [${renderedLedgerCommit}].`, [buildSection(CONTENT_SECTION_TITLE, result.summary), infoSection].filter((section) => section !== null)),
|
|
76
|
+
text: assembleResponse(`${RESPONSE_MARKERS.arc} Amended`, `Amended contract ledger with Amendment ${result.amendmentNumber} [${renderedLedgerCommit}].`, [buildSection(CONTENT_SECTION_TITLE, result.summary), infoSection, warningSection].filter((section) => section !== null)),
|
|
73
77
|
payload: buildPayload(payload),
|
|
74
78
|
}, result.address);
|
|
75
79
|
}
|