@astrosheep/keiyaku 4.0.5 → 4.0.6
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 +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +15 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +10 -4
- package/build/src/akuma/akuma.d.ts +2 -0
- package/build/src/akuma/akuma.js +26 -3
- package/build/src/akuma/archetype.d.ts +3 -1
- package/build/src/akuma/archetype.js +11 -6
- package/build/src/akuma/body-turn.d.ts +64 -0
- package/build/src/akuma/body-turn.js +449 -0
- package/build/src/akuma/body.d.ts +3 -7
- package/build/src/akuma/body.js +9 -420
- package/build/src/akuma/heart/facts.d.ts +2 -0
- package/build/src/akuma/heart/facts.js +3 -1
- package/build/src/akuma/heart/index.js +12 -2
- package/build/src/akuma/heart/rows.js +4 -1
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +3 -2
- package/build/src/akuma/heart/timeline.d.ts +1 -0
- package/build/src/akuma/heart/timeline.js +19 -0
- package/build/src/akuma/nuke.d.ts +2 -0
- package/build/src/akuma/nuke.js +152 -0
- package/build/src/akuma/provider.d.ts +3 -1
- package/build/src/akuma/providers/acp/config.d.ts +8 -0
- package/build/src/akuma/providers/acp/config.js +37 -0
- package/build/src/akuma/providers/acp/core.js +6 -0
- package/build/src/akuma/providers/acp/index.d.ts +1 -8
- package/build/src/akuma/providers/acp/index.js +2 -37
- package/build/src/akuma/providers/claude/index.js +5 -0
- package/build/src/akuma/providers/codex-app-server/index.js +5 -0
- package/build/src/akuma/providers/grok-build/index.js +1 -1
- package/build/src/akuma/providers/index.d.ts +3 -2
- package/build/src/akuma/providers/index.js +36 -36
- package/build/src/akuma/providers/opencode-sdk/index.js +6 -0
- 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.d.ts +1 -1
- package/build/src/akuma/providers/pi/index.js +27 -11
- package/build/src/akuma/request-serve.d.ts +1 -0
- package/build/src/akuma/request-serve.js +31 -31
- package/build/src/akuma/request-wire.d.ts +3 -2
- package/build/src/akuma/request-wire.js +5 -2
- package/build/src/akuma-body.js +15 -1
- package/build/src/alias/index.d.ts +1 -0
- package/build/src/alias/index.js +34 -1
- package/build/src/cli/accepted.js +4 -0
- package/build/src/cli/commands/akuma-invoke.js +1 -0
- package/build/src/cli/commands/akuma.d.ts +1 -0
- package/build/src/cli/commands/akuma.js +11 -8
- package/build/src/cli/commands/contract.d.ts +25 -14
- package/build/src/cli/commands/contract.js +23 -17
- package/build/src/cli/commands/install.d.ts +2 -2
- package/build/src/cli/commands/install.js +6 -6
- package/build/src/cli/commands/nuke.d.ts +10 -0
- package/build/src/cli/commands/nuke.js +20 -0
- package/build/src/cli/commands/task-invoke.d.ts +15 -0
- package/build/src/cli/commands/task-invoke.js +57 -26
- package/build/src/cli/commands/task-query.d.ts +2 -2
- package/build/src/cli/commands/task-query.js +1 -2
- package/build/src/cli/commands/task.js +22 -22
- package/build/src/cli/coordinates.d.ts +5 -2
- package/build/src/cli/coordinates.js +5 -52
- package/build/src/cli/invoke.d.ts +5 -4
- package/build/src/cli/invoke.js +89 -59
- package/build/src/cli/main.d.ts +0 -2
- package/build/src/cli/main.js +4 -140
- package/build/src/cli/parse.d.ts +15 -2
- package/build/src/cli/parse.js +73 -8
- package/build/src/cli/render/akuma.js +55 -40
- package/build/src/cli/render/contract.js +49 -48
- package/build/src/cli/render/kanshi.js +15 -5
- package/build/src/cli/render/nuke.d.ts +3 -0
- package/build/src/cli/render/nuke.js +8 -0
- package/build/src/cli/render/refusal.d.ts +2 -1
- package/build/src/cli/render/refusal.js +31 -0
- package/build/src/cli/render/text.js +6 -1
- package/build/src/cli/result.d.ts +21 -2
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +140 -0
- package/build/src/cli/usage.d.ts +0 -2
- package/build/src/cli/usage.js +0 -4
- package/build/src/contract-worktree.d.ts +28 -12
- package/build/src/contract-worktree.js +129 -63
- package/build/src/git/hooks.d.ts +2 -0
- package/build/src/git/hooks.js +34 -1
- package/build/src/git/integration.d.ts +4 -0
- package/build/src/git/integration.js +38 -0
- package/build/src/git/nuke.d.ts +2 -0
- package/build/src/git/nuke.js +97 -0
- package/build/src/git/process.d.ts +2 -0
- package/build/src/git/reconcile.d.ts +2 -0
- package/build/src/git/reconcile.js +33 -2
- package/build/src/git/repository.js +4 -1
- package/build/src/git/target-placement.d.ts +2 -1
- package/build/src/git/target-placement.js +6 -7
- package/build/src/git/tender.d.ts +1 -0
- package/build/src/git/tender.js +2 -2
- package/build/src/git/workspace.d.ts +3 -0
- package/build/src/kanshi/read.js +5 -1
- package/build/src/library/akuma-creation.d.ts +1 -0
- package/build/src/library/akuma-creation.js +8 -1
- package/build/src/library/audit.d.ts +1 -0
- package/build/src/library/audit.js +1 -0
- package/build/src/library/contract.d.ts +6 -4
- package/build/src/library/contract.js +56 -34
- package/build/src/library/delivery.d.ts +3 -1
- package/build/src/library/keiyaku.d.ts +5 -1
- package/build/src/library/keiyaku.js +2 -0
- package/build/src/library/mutation.d.ts +1 -0
- package/build/src/library/mutation.js +3 -0
- package/build/src/library/nuke.d.ts +14 -0
- package/build/src/library/nuke.js +54 -0
- package/build/src/library/reconcile.js +5 -2
- package/build/src/library/refusal.d.ts +10 -1
- package/build/src/library/repo.d.ts +1 -0
- package/build/src/library/repo.js +2 -0
- package/build/src/protocol/audit.js +12 -5
- package/build/src/protocol/completion.d.ts +11 -1
- package/build/src/protocol/completion.js +68 -15
- package/build/src/protocol/deliver.d.ts +14 -2
- package/build/src/protocol/deliver.js +107 -6
- package/build/src/protocol/intent.d.ts +1 -0
- package/build/src/protocol/intent.js +7 -1
- package/build/src/protocol/operations.d.ts +30 -3
- package/build/src/protocol/operations.js +2 -2
- package/build/src/protocol/placement.d.ts +9 -1
- package/build/src/protocol/placement.js +5 -4
- package/build/src/protocol/read/status.d.ts +16 -4
- package/build/src/protocol/read/status.js +54 -12
- package/build/src/protocol/review.d.ts +1 -0
- package/build/src/protocol/review.js +8 -0
- package/build/src/runtime/proc/run.js +9 -5
- package/build/src/settlement/fence.d.ts +2 -0
- package/build/src/settlement/fence.js +24 -0
- package/build/src/settlement/settle.js +1 -2
- package/build/src/task/compose.d.ts +1 -1
- package/build/src/task/compose.js +2 -7
- package/build/src/task/context.d.ts +14 -2
- package/build/src/task/context.js +30 -7
- package/build/src/task/index.d.ts +6 -5
- package/build/src/task/index.js +15 -18
- package/build/src/task/mutation.d.ts +7 -2
- package/build/src/task/mutation.js +14 -6
- package/build/src/task/operations.d.ts +12 -6
- package/build/src/task/operations.js +22 -46
- package/build/src/task/store.d.ts +1 -0
- package/build/src/task/store.js +91 -1
- package/build/src/workspace-place.d.ts +2 -0
- package/build/src/workspace-place.js +27 -1
- package/package.json +1 -1
package/build/src/cli/parse.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { isTaskAction, parseTaskCommand, renderTaskUsage, } from "./commands/task.js";
|
|
2
|
-
import { isAkumaAction, parseAkumaCatalogPath, parseAkumaCommand, renderAkumaRootRows, renderAkumaUsage, } from "./commands/akuma.js";
|
|
1
|
+
import { isTaskAction, parseTaskCommand, renderTaskHelp, renderTaskUsage, } from "./commands/task.js";
|
|
2
|
+
import { isAkumaAction, parseAkumaCatalogPath, parseAkumaCommand, renderAkumaHelp, renderAkumaRootRows, renderAkumaUsage, } from "./commands/akuma.js";
|
|
3
3
|
import { INSTALL_USAGE, parseInstallCommand, renderInstallHelp } from "./commands/install.js";
|
|
4
|
-
import {
|
|
5
|
-
import { CliUsageError, isBlankInput, usageLine
|
|
4
|
+
import { AMEND_OPERATIONS_HELP, CONTRACT_COMMAND_SPECS, } from "./commands/contract.js";
|
|
5
|
+
import { CliUsageError, isBlankInput, usageLine } 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 ...] [-]";
|
|
8
8
|
export function renderRootHelp() {
|
|
9
|
-
return
|
|
9
|
+
return [
|
|
10
10
|
ROOT_USAGE,
|
|
11
11
|
"",
|
|
12
12
|
"global options:",
|
|
@@ -20,12 +20,12 @@ export function renderRootHelp() {
|
|
|
20
20
|
" task ...",
|
|
21
21
|
" Task coordination; see `keiyaku task --help`.",
|
|
22
22
|
...renderAkumaRootRows(),
|
|
23
|
-
].join("\n")
|
|
23
|
+
].join("\n");
|
|
24
24
|
}
|
|
25
25
|
export function renderContractHelp(command) {
|
|
26
26
|
const spec = CONTRACT_COMMAND_SPECS[command];
|
|
27
27
|
const help = `${spec.purpose}\n\n${usageLine(spec.usage)}`;
|
|
28
|
-
return
|
|
28
|
+
return command === "amend" ? `${help}\n\n${AMEND_OPERATIONS_HELP}` : help;
|
|
29
29
|
}
|
|
30
30
|
function contractUsage(command) {
|
|
31
31
|
return usageLine(CONTRACT_COMMAND_SPECS[command].usage);
|
|
@@ -39,6 +39,65 @@ export function renderCommandUsage(command) {
|
|
|
39
39
|
return renderAkumaUsage(command.command);
|
|
40
40
|
return contractUsage(command.command);
|
|
41
41
|
}
|
|
42
|
+
export function renderHelp(coordinate) {
|
|
43
|
+
switch (coordinate.kind) {
|
|
44
|
+
case "root": return renderRootHelp();
|
|
45
|
+
case "contract": return renderContractHelp(coordinate.command);
|
|
46
|
+
case "task": return renderTaskHelp(coordinate.action);
|
|
47
|
+
case "install": return renderInstallHelp();
|
|
48
|
+
case "akuma": return renderAkumaHelp(coordinate.action);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export function commandRepoPolicy(command) {
|
|
52
|
+
switch (command.command) {
|
|
53
|
+
case "bind":
|
|
54
|
+
case "amend":
|
|
55
|
+
case "deliver":
|
|
56
|
+
case "review":
|
|
57
|
+
case "arc":
|
|
58
|
+
case "abandon":
|
|
59
|
+
case "audit":
|
|
60
|
+
case "reconcile":
|
|
61
|
+
case "show":
|
|
62
|
+
case "region":
|
|
63
|
+
return { use: "required", acceptsExplicit: true };
|
|
64
|
+
case "ls":
|
|
65
|
+
return { use: command.query.kind === "contracts" ? "required" : "none", acceptsExplicit: false };
|
|
66
|
+
case "status":
|
|
67
|
+
case "tell":
|
|
68
|
+
return { use: "optional", acceptsExplicit: false };
|
|
69
|
+
case "history":
|
|
70
|
+
return "contract" in command
|
|
71
|
+
? { use: "required", acceptsExplicit: true }
|
|
72
|
+
: { use: "optional", acceptsExplicit: false };
|
|
73
|
+
case "fork":
|
|
74
|
+
return { use: "optional", acceptsExplicit: true };
|
|
75
|
+
case "wait":
|
|
76
|
+
case "kill": {
|
|
77
|
+
const contractSelector = command.akuma.some((selector) => selector.startsWith("kei/"));
|
|
78
|
+
return { use: contractSelector ? "required" : "optional", acceptsExplicit: contractSelector };
|
|
79
|
+
}
|
|
80
|
+
case "call":
|
|
81
|
+
return {
|
|
82
|
+
use: command.contract === undefined ? "none" : "required",
|
|
83
|
+
acceptsExplicit: command.contract !== undefined,
|
|
84
|
+
};
|
|
85
|
+
case "settings":
|
|
86
|
+
case "nuke":
|
|
87
|
+
case "task":
|
|
88
|
+
case "install":
|
|
89
|
+
return { use: "none", acceptsExplicit: false };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function refuseUnusedRepo(command) {
|
|
93
|
+
if (command.command === "call")
|
|
94
|
+
throw new CliUsageError("--repo has no consumer without --contract");
|
|
95
|
+
throw new CliUsageError(`--repo has no consumer for ${command.command}`);
|
|
96
|
+
}
|
|
97
|
+
export function assertExplicitRepoUse(command, repo) {
|
|
98
|
+
if (repo !== undefined && !commandRepoPolicy(command).acceptsExplicit)
|
|
99
|
+
refuseUnusedRepo(command);
|
|
100
|
+
}
|
|
42
101
|
function optionalFlag(flags, name) {
|
|
43
102
|
const value = flags[name];
|
|
44
103
|
return typeof value === "string" ? value : undefined;
|
|
@@ -175,6 +234,7 @@ function parseDeliver(parts) {
|
|
|
175
234
|
...(parts.actor === undefined ? {} : { actor: parts.actor }),
|
|
176
235
|
...(message === undefined ? {} : { message }),
|
|
177
236
|
includeDirty: parts.flags["include-dirty"] === true,
|
|
237
|
+
materializeConflict: parts.flags["materialize-conflict"] === true,
|
|
178
238
|
output: parts.output,
|
|
179
239
|
};
|
|
180
240
|
}
|
|
@@ -356,6 +416,10 @@ function parseCommand(parts) {
|
|
|
356
416
|
output: parts.output,
|
|
357
417
|
};
|
|
358
418
|
}
|
|
419
|
+
case "nuke": {
|
|
420
|
+
const confirm = optionalFlag(parts.flags, "confirm");
|
|
421
|
+
return { command: "nuke", ...(confirm === undefined ? {} : { confirm }), output: parts.output };
|
|
422
|
+
}
|
|
359
423
|
case "settings": return { command: "settings", output: parts.output };
|
|
360
424
|
case "region": return parseRegion(parts);
|
|
361
425
|
}
|
|
@@ -379,9 +443,10 @@ export function parseArgv(argv) {
|
|
|
379
443
|
const akuma = isAkumaAction(invocation.commandArgv[0])
|
|
380
444
|
? parseAkumaCommand(invocation.commandArgv)
|
|
381
445
|
: undefined;
|
|
382
|
-
|
|
446
|
+
const parsed = {
|
|
383
447
|
...(invocation.cwd === undefined ? {} : { cwd: invocation.cwd }),
|
|
384
448
|
...(invocation.repo === undefined ? {} : { repo: invocation.repo }),
|
|
385
449
|
command: task ?? akuma ?? install ?? parseCommand(scanArgv(invocation.commandArgv)),
|
|
386
450
|
};
|
|
451
|
+
return parsed;
|
|
387
452
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toolRepr } from "./akuma-tool.js";
|
|
2
|
-
import { displayColumns, renderBoundedTextBlock,
|
|
2
|
+
import { displayColumns, renderBoundedTextBlock, safeText, truncateMiddleDisplayText, } from "./terminal.js";
|
|
3
3
|
const DEFAULT_CONTEXT = { columns: 80, color: false };
|
|
4
4
|
const OPENING_STROKE = "─────";
|
|
5
5
|
const TIME_WIDTH = 5;
|
|
@@ -30,7 +30,7 @@ function unobservedText(id, diagnostic) {
|
|
|
30
30
|
}
|
|
31
31
|
function lifeLabel(life) {
|
|
32
32
|
if (life === "running")
|
|
33
|
-
return "●
|
|
33
|
+
return "● STILL RUNNING";
|
|
34
34
|
if (life === "asleep")
|
|
35
35
|
return "○ asleep";
|
|
36
36
|
if (life === "killed")
|
|
@@ -70,7 +70,7 @@ function mark(row) {
|
|
|
70
70
|
return "?";
|
|
71
71
|
return row.state.status === "ok" ? "✓" : "!";
|
|
72
72
|
}
|
|
73
|
-
return "
|
|
73
|
+
return "│";
|
|
74
74
|
}
|
|
75
75
|
function rowText(row) {
|
|
76
76
|
if (row.kind === "said" || row.kind === "thought" || row.kind === "note" || row.kind === "call" || row.kind === "tell") {
|
|
@@ -160,47 +160,59 @@ function taskDispositionMark(disposition) {
|
|
|
160
160
|
return "●";
|
|
161
161
|
return disposition === "blocked" ? "‖" : "○";
|
|
162
162
|
}
|
|
163
|
-
function
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
for (const change of snapshot.reportedChanges) {
|
|
172
|
-
const scan = ` ${changeOp(change.op)}`;
|
|
173
|
-
const path = safeText(change.path);
|
|
174
|
-
const stat = change.diffstat === undefined
|
|
175
|
-
? ""
|
|
176
|
-
: ` — +${change.diffstat.added} -${change.diffstat.removed}`;
|
|
177
|
-
const inline = `${scan} ${path}${stat}`;
|
|
178
|
-
if (displayColumns(inline) <= columns)
|
|
179
|
-
lines.push(inline);
|
|
180
|
-
else
|
|
181
|
-
lines.push(`${scan}`, ...renderTextBlock(`${path}${stat}`, " ", columns));
|
|
163
|
+
function changeStat(group) {
|
|
164
|
+
let added = 0;
|
|
165
|
+
let removed = 0;
|
|
166
|
+
for (const change of group) {
|
|
167
|
+
if (change.diffstat === undefined)
|
|
168
|
+
return "+? -?";
|
|
169
|
+
added += change.diffstat.added;
|
|
170
|
+
removed += change.diffstat.removed;
|
|
182
171
|
}
|
|
183
|
-
|
|
184
|
-
|
|
172
|
+
return `+${added} -${removed}`;
|
|
173
|
+
}
|
|
174
|
+
function groupedChangeRows(changes) {
|
|
175
|
+
const groups = [];
|
|
176
|
+
const seen = new Map();
|
|
177
|
+
for (const change of changes) {
|
|
178
|
+
const index = seen.get(change.path);
|
|
179
|
+
if (index === undefined) {
|
|
180
|
+
seen.set(change.path, groups.length);
|
|
181
|
+
groups.push([change]);
|
|
182
|
+
}
|
|
183
|
+
else
|
|
184
|
+
groups[index].push(change);
|
|
185
185
|
}
|
|
186
|
-
return
|
|
186
|
+
return groups.map((group) => ({ path: group[0].path, stat: changeStat(group) }));
|
|
187
|
+
}
|
|
188
|
+
function renderReportedChangeLines(snapshot) {
|
|
189
|
+
const rows = groupedChangeRows(snapshot.reportedChanges);
|
|
190
|
+
const width = rows.reduce((max, row) => Math.max(max, row.stat.length), 0);
|
|
191
|
+
return [
|
|
192
|
+
`changes ${snapshot.reportedChanges.length + snapshot.reportedChangesOmitted}`,
|
|
193
|
+
...rows.map((row) => ` ${row.stat.padEnd(width)} ${safeText(row.path)}`),
|
|
194
|
+
...(snapshot.reportedChangesOmitted > 0 ? [` ⋮ ${snapshot.reportedChangesOmitted} earlier changes`] : []),
|
|
195
|
+
];
|
|
196
|
+
}
|
|
197
|
+
function renderTaskRow(row, columns) {
|
|
198
|
+
const prefix = ` ${taskDispositionMark(row.disposition)} ${row.id} · `;
|
|
199
|
+
const body = `${safeText(row.title)} · ${row.disposition} · P${row.priority}`;
|
|
200
|
+
const inline = `${prefix}${body}`;
|
|
201
|
+
if (displayColumns(inline) <= columns)
|
|
202
|
+
return [inline];
|
|
203
|
+
return renderBoundedTextBlock(body, {
|
|
204
|
+
first: prefix,
|
|
205
|
+
continuation: " ",
|
|
206
|
+
columns,
|
|
207
|
+
lines: Number.MAX_SAFE_INTEGER,
|
|
208
|
+
});
|
|
187
209
|
}
|
|
188
210
|
function renderTaskContextLines(created, columns) {
|
|
189
211
|
if (created === undefined)
|
|
190
212
|
return [];
|
|
191
213
|
if (created.kind === "failed")
|
|
192
214
|
return [`! tasks failed ${safeText(created.diagnostic)}`];
|
|
193
|
-
|
|
194
|
-
for (const row of created.rows) {
|
|
195
|
-
const scan = ` ${taskScanLine(row)}`;
|
|
196
|
-
const title = safeText(row.title);
|
|
197
|
-
const inline = `${scan} — ${title}`;
|
|
198
|
-
if (displayColumns(inline) <= columns)
|
|
199
|
-
lines.push(inline);
|
|
200
|
-
else
|
|
201
|
-
lines.push(`${scan} —`, ...renderTextBlock(title, " ", columns));
|
|
202
|
-
}
|
|
203
|
-
return lines;
|
|
215
|
+
return [`tasks ${created.rows.length}`, ...created.rows.flatMap((row) => renderTaskRow(row, columns))];
|
|
204
216
|
}
|
|
205
217
|
function snapshotText(view, context, options = {}) {
|
|
206
218
|
const snapshot = view.status.timeline;
|
|
@@ -215,14 +227,14 @@ function snapshotText(view, context, options = {}) {
|
|
|
215
227
|
...contractFacts(view.contract),
|
|
216
228
|
...(options.facts ?? []),
|
|
217
229
|
];
|
|
218
|
-
const footer = options.showLife === false ? [] : [
|
|
230
|
+
const footer = options.showLife === false ? [] : ["", lifeLabel(view.status.life)];
|
|
219
231
|
return [
|
|
220
232
|
...snapshotHeading(view.status.id, options.alias, view.contract),
|
|
221
233
|
...facts,
|
|
222
234
|
...activity,
|
|
223
|
-
...footer,
|
|
224
|
-
...renderReportedChangeLines(snapshot, context.columns),
|
|
225
235
|
...renderTaskContextLines(view.createdTasks, context.columns),
|
|
236
|
+
...renderReportedChangeLines(snapshot),
|
|
237
|
+
...footer,
|
|
226
238
|
].join("\n");
|
|
227
239
|
}
|
|
228
240
|
function observationStageText(id, observation, context, options = {}) {
|
|
@@ -291,6 +303,9 @@ export function akumaRawAnswer(result) {
|
|
|
291
303
|
function executionCwdLine(result) {
|
|
292
304
|
return result.execution.source === "contract-worktree" ? [`cwd ${result.execution.cwd}`] : [];
|
|
293
305
|
}
|
|
306
|
+
function posixShellArgument(value) {
|
|
307
|
+
return `'${value.replace(/'/g, `'\"'\"'`)}'`;
|
|
308
|
+
}
|
|
294
309
|
function callText(result, context) {
|
|
295
310
|
const alias = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : undefined;
|
|
296
311
|
const contractId = result.result.dispatch.kind === "dispatched" ? result.result.dispatch.dispatch.contractId : undefined;
|
|
@@ -305,7 +320,7 @@ function callText(result, context) {
|
|
|
305
320
|
: { kind: "associated", contractId }), ...cwd, ...restraint, ...facts];
|
|
306
321
|
if (!callFailed(result.result)) {
|
|
307
322
|
const selector = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : result.result.akuma;
|
|
308
|
-
lines.push(`$ keiyaku -C ${result.world} wait ${selector} --timeout 5m`);
|
|
323
|
+
lines.push(`$ keiyaku -C ${posixShellArgument(result.world)} wait ${selector} --timeout 5m`);
|
|
309
324
|
}
|
|
310
325
|
return lines.join("\n");
|
|
311
326
|
}
|
|
@@ -113,11 +113,20 @@ function acceptedRecord(result, columns) {
|
|
|
113
113
|
const record = [];
|
|
114
114
|
for (const fact of result.facts) {
|
|
115
115
|
const contract = fact.contract === result.contract ? [] : [{ text: fact.contract, opaque: true }];
|
|
116
|
-
receiptRow(record, " ", "journal",
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
receiptRow(record, " ", "journal", fact.kind === "reintegrated"
|
|
117
|
+
? [
|
|
118
|
+
...contract,
|
|
119
|
+
{ text: fact.entry, opaque: true },
|
|
120
|
+
{ text: "· reintegrated" },
|
|
121
|
+
{ text: fact.data.predecessor, opaque: true },
|
|
122
|
+
{ text: "->" },
|
|
123
|
+
{ text: fact.data.snapshot, opaque: true },
|
|
124
|
+
]
|
|
125
|
+
: [
|
|
126
|
+
...contract,
|
|
127
|
+
{ text: fact.entry, opaque: true },
|
|
128
|
+
{ text: `· ${fact.kind}` },
|
|
129
|
+
], columns);
|
|
121
130
|
}
|
|
122
131
|
receiptRow(record, " ", "head", [{ text: result.head, opaque: true }], columns);
|
|
123
132
|
if (result.verb === "deliver") {
|
|
@@ -176,11 +185,36 @@ function recordBlock(result, columns) {
|
|
|
176
185
|
const rows = [...acceptedRecord(result, columns), ...acceptedLagRows(result, columns)];
|
|
177
186
|
return [" record", ...indentRecord(rows)];
|
|
178
187
|
}
|
|
179
|
-
function
|
|
188
|
+
function completionLines(result, columns) {
|
|
180
189
|
const lines = [];
|
|
181
|
-
|
|
182
|
-
|
|
190
|
+
const completion = result.completion;
|
|
191
|
+
if (completion === undefined)
|
|
192
|
+
return lines;
|
|
193
|
+
const verification = completion.verification;
|
|
194
|
+
receiptRow(lines, " ", "target", [
|
|
195
|
+
{ text: "->" },
|
|
196
|
+
{ text: completion.integration, opaque: true },
|
|
197
|
+
...(verification?.verdict === "satisfied"
|
|
198
|
+
? [{ text: `· verified (${verification.mode})` }]
|
|
199
|
+
: []),
|
|
183
200
|
], columns);
|
|
201
|
+
if (verification?.verdict === "unsatisfied") {
|
|
202
|
+
receiptRow(lines, "!", "verification", [
|
|
203
|
+
{ text: "unsatisfied" },
|
|
204
|
+
{ text: `(${verification.mode})` },
|
|
205
|
+
], columns);
|
|
206
|
+
if (result.verificationSummary !== undefined) {
|
|
207
|
+
receiptPayload(lines, " summary", result.verificationSummary);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return lines;
|
|
211
|
+
}
|
|
212
|
+
function movementLines(result, columns) {
|
|
213
|
+
const count = result.facts.filter((fact) => fact.kind === "reintegrated").length;
|
|
214
|
+
if (count === 0)
|
|
215
|
+
return [];
|
|
216
|
+
const lines = [];
|
|
217
|
+
receiptRow(lines, "~", "target", [{ text: `moved · re-integrated x${count}` }], columns);
|
|
184
218
|
return lines;
|
|
185
219
|
}
|
|
186
220
|
function renderAcceptedBind(result, columns) {
|
|
@@ -201,51 +235,19 @@ function renderAcceptedAmend(result, columns) {
|
|
|
201
235
|
lines.push(...acceptedDeviations(result, columns), ...recordBlock(result, columns));
|
|
202
236
|
return lines.join("\n");
|
|
203
237
|
}
|
|
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
|
-
}
|
|
230
238
|
function renderAcceptedDeliver(result, columns) {
|
|
231
|
-
const complete = result.
|
|
239
|
+
const complete = result.completion !== undefined;
|
|
232
240
|
const title = complete ? "delivered" : "deliver — not complete";
|
|
233
241
|
const lines = titleLines("✓", title, result.contract, columns);
|
|
234
|
-
lines.push(...
|
|
242
|
+
lines.push(...movementLines(result, columns), ...completionLines(result, columns));
|
|
235
243
|
if (!complete)
|
|
236
244
|
receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
|
|
237
245
|
if (result.verification !== undefined) {
|
|
238
246
|
lines.push(...stopLines("verification", result.verification, columns, result.contract));
|
|
239
247
|
}
|
|
240
|
-
else if (result.verificationVerdict !== undefined) {
|
|
241
|
-
lines.push(...verificationVerdictLine(result.verificationVerdict, columns));
|
|
242
|
-
}
|
|
243
248
|
if (!complete && result.placement !== undefined) {
|
|
244
249
|
lines.push(...stopLines("completion", result.placement, columns, result.contract));
|
|
245
250
|
}
|
|
246
|
-
else if (!complete && (result.verification !== undefined || result.verificationVerdict === "unsatisfied")) {
|
|
247
|
-
receiptRow(lines, "·", "completion", [{ text: "not attempted" }], columns);
|
|
248
|
-
}
|
|
249
251
|
if (result.cleanup !== undefined)
|
|
250
252
|
pushBlock(lines, cleanupLines(result.cleanup, columns));
|
|
251
253
|
if (result.leak !== undefined)
|
|
@@ -254,12 +256,11 @@ function renderAcceptedDeliver(result, columns) {
|
|
|
254
256
|
return lines.join("\n");
|
|
255
257
|
}
|
|
256
258
|
function renderAcceptedReview(result, columns) {
|
|
257
|
-
const complete = result.
|
|
258
|
-
const lines = titleLines("✓", `review ${result.verdict}`, result.contract, columns);
|
|
259
|
-
lines.push(...
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
], columns);
|
|
259
|
+
const complete = result.completion !== undefined;
|
|
260
|
+
const lines = titleLines("✓", `review ${result.verdict} — ${complete ? "complete" : "not complete"}`, result.contract, columns);
|
|
261
|
+
lines.push(...movementLines(result, columns), ...completionLines(result, columns));
|
|
262
|
+
if (!complete)
|
|
263
|
+
receiptRow(lines, " ", "candidate", [{ text: "kept" }], columns);
|
|
263
264
|
if (result.placement !== undefined) {
|
|
264
265
|
lines.push(...stopLines("completion", result.placement, columns, result.contract));
|
|
265
266
|
}
|
|
@@ -85,8 +85,13 @@ function targetFacts(row) {
|
|
|
85
85
|
}
|
|
86
86
|
function workspaceState(row) {
|
|
87
87
|
const observation = row.workspaceObservation;
|
|
88
|
+
if (row.workspace === "here" && observation.kind === "failed") {
|
|
89
|
+
return `workspace here · failed · ${observation.diagnostic}`;
|
|
90
|
+
}
|
|
88
91
|
if (row.workspace === "here")
|
|
89
92
|
return `workspace here · ${observation.kind}`;
|
|
93
|
+
if (observation.kind === "failed")
|
|
94
|
+
return `worktree unavailable · ${observation.diagnostic}`;
|
|
90
95
|
if (observation.kind === "unappointed")
|
|
91
96
|
return "worktree unappointed";
|
|
92
97
|
if (observation.kind === "unavailable")
|
|
@@ -106,7 +111,7 @@ function showWorkspacePath(row, hot) {
|
|
|
106
111
|
return false;
|
|
107
112
|
if (row.workspaceObservation.kind === "unappointed")
|
|
108
113
|
return false;
|
|
109
|
-
if (row.workspaceObservation.kind !== "clean")
|
|
114
|
+
if (row.workspaceObservation.kind !== "clean" && row.workspaceObservation.kind !== "failed")
|
|
110
115
|
return true;
|
|
111
116
|
return hot;
|
|
112
117
|
}
|
|
@@ -219,13 +224,15 @@ function renderContractRow(row, report, context, selection) {
|
|
|
219
224
|
const compact = !hot && selection !== "contract";
|
|
220
225
|
const title = row.title ?? "title unavailable";
|
|
221
226
|
const phase = `${row.phase} · ${formatAge(row.phaseAt, report.observedAt)}`;
|
|
227
|
+
const journal = `journal ${formatAge(row.lastJournalAt, report.observedAt)}`;
|
|
222
228
|
const lines = [identityLine(contractMark(row), row.id)];
|
|
223
|
-
lines.push(...plumbFacts(compact ? [title, phase, ...targetFacts(row)] : [title], context.columns));
|
|
229
|
+
lines.push(...plumbFacts(compact ? [title, phase, journal, ...targetFacts(row)] : [title], context.columns));
|
|
224
230
|
if (!compact)
|
|
225
|
-
lines.push(...plumbFacts([phase, ...targetFacts(row)], context.columns));
|
|
231
|
+
lines.push(...plumbFacts([phase, journal, ...targetFacts(row)], context.columns));
|
|
226
232
|
lines.push(...plumbFacts([workspaceState(row)], context.columns));
|
|
227
233
|
if (showWorkspacePath(row, hot || selection === "contract")
|
|
228
234
|
&& row.workspaceObservation.kind !== "unappointed"
|
|
235
|
+
&& row.workspaceObservation.kind !== "failed"
|
|
229
236
|
&& row.workspaceObservation.location.kind === "worktree") {
|
|
230
237
|
lines.push(plumbPath(row.workspaceObservation.location.path));
|
|
231
238
|
}
|
|
@@ -320,9 +327,12 @@ function renderAkuma(report, context) {
|
|
|
320
327
|
lines.push(identityLine(akumaMark(row.life), row.id, akumaLabel(row)));
|
|
321
328
|
const lifeAt = "lifeAt" in row ? row.lifeAt : null;
|
|
322
329
|
const life = `${row.life} · ${formatAge(lifeAt, report.observedAt)}`;
|
|
330
|
+
const activity = "lastActivityAt" in row && row.lastActivityAt !== null
|
|
331
|
+
? [`activity ${formatAge(row.lastActivityAt, report.observedAt)}`]
|
|
332
|
+
: [];
|
|
323
333
|
const key = row.life === "stranded" && "strandedReason" in row && row.strandedReason === "resume-unsupported"
|
|
324
|
-
? [life, "resume unsupported"]
|
|
325
|
-
: [life];
|
|
334
|
+
? [life, ...activity, "resume unsupported"]
|
|
335
|
+
: [life, ...activity];
|
|
326
336
|
const relation = row.contract === undefined
|
|
327
337
|
? ["unbound"]
|
|
328
338
|
: [endpointFact(row.contract.id, row.contract.observed)];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BindDraftReceipt, RefusedResult } from "../result.js";
|
|
2
|
-
import type { KeiyakuRefusal } from "../../index.js";
|
|
2
|
+
import type { IntegrationConflictMaterialized, KeiyakuRefusal } from "../../index.js";
|
|
3
3
|
import { type TextRenderContext } from "./terminal.js";
|
|
4
4
|
type DirtyWithOption = Extract<KeiyakuRefusal, {
|
|
5
5
|
kind: "dirty-workspace";
|
|
@@ -12,5 +12,6 @@ type DirtyWithOption = Extract<KeiyakuRefusal, {
|
|
|
12
12
|
export type RenderableRefusal = KeiyakuRefusal | DirtyWithOption;
|
|
13
13
|
export declare function renderRefusalFacts(refusal: RenderableRefusal, indent: string, columns: number, addressed?: string): readonly string[];
|
|
14
14
|
export declare function renderRefusal(result: RefusedResult, context?: TextRenderContext): string;
|
|
15
|
+
export declare function renderConflictMaterialized(result: IntegrationConflictMaterialized, context?: TextRenderContext): string;
|
|
15
16
|
export declare function renderBindDraftReceipt(receipt: BindDraftReceipt): string;
|
|
16
17
|
export {};
|
|
@@ -38,6 +38,18 @@ function renderDirtyRefusal(refusal, indent, columns, identity) {
|
|
|
38
38
|
}
|
|
39
39
|
export function renderRefusalFacts(refusal, indent, columns, addressed) {
|
|
40
40
|
const identity = refusalIdentity(refusal, addressed);
|
|
41
|
+
if (refusal.kind === "nuke-confirmation-mismatch") {
|
|
42
|
+
return [
|
|
43
|
+
...renderOpaqueBlock(`nuke confirmation mismatch world=${refusal.world} confirmation=${refusal.confirmation}`, indent, columns),
|
|
44
|
+
...renderOpaqueBlock(`keiyaku nuke --confirm ${refusal.world}`, indent, columns),
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
if (refusal.kind === "nuke-confirmation-required") {
|
|
48
|
+
return [
|
|
49
|
+
...renderOpaqueBlock(`nuke confirmation required world=${refusal.world}`, indent, columns),
|
|
50
|
+
...renderOpaqueBlock(`keiyaku nuke --confirm ${refusal.world}`, indent, columns),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
41
53
|
if (refusal.kind === "dirty-workspace")
|
|
42
54
|
return renderDirtyRefusal(refusal, indent, columns, identity);
|
|
43
55
|
if (refusal.kind === "integration-failed") {
|
|
@@ -46,8 +58,18 @@ export function renderRefusalFacts(refusal, indent, columns, addressed) {
|
|
|
46
58
|
];
|
|
47
59
|
if (refusal.conflictPaths !== undefined)
|
|
48
60
|
lines.push(...collectionLines("conflictPaths", refusal.conflictPaths, indent, columns));
|
|
61
|
+
if ("recovery" in refusal && refusal.recovery !== undefined) {
|
|
62
|
+
wrap(lines, `recovery materialize conflicts · ${refusal.recovery.materialize}`, indent, columns);
|
|
63
|
+
wrap(lines, `recovery continue after resolve and commit · ${refusal.recovery.continue}`, indent, columns);
|
|
64
|
+
}
|
|
49
65
|
return lines;
|
|
50
66
|
}
|
|
67
|
+
if (refusal.kind === "merge-state-present") {
|
|
68
|
+
return renderOpaqueBlock(refusalHead(refusal.kind, identity, [
|
|
69
|
+
`workspace=${refusal.workspace.kind}`,
|
|
70
|
+
`path=${refusal.workspace.path}`,
|
|
71
|
+
]), indent, columns);
|
|
72
|
+
}
|
|
51
73
|
if (refusal.kind === "integration-unsupported") {
|
|
52
74
|
return renderOpaqueBlock(refusalHead(refusal.kind, identity, [`requiredGit=${refusal.requiredGit}`]), indent, columns);
|
|
53
75
|
}
|
|
@@ -81,6 +103,15 @@ export function renderRefusal(result, context) {
|
|
|
81
103
|
const output = lines.join("\n");
|
|
82
104
|
return result.draft === undefined ? output : `${output}\n${renderBindDraftReceipt(result.draft)}`;
|
|
83
105
|
}
|
|
106
|
+
export function renderConflictMaterialized(result, context) {
|
|
107
|
+
const columns = context?.columns ?? 80;
|
|
108
|
+
const indent = " ";
|
|
109
|
+
return [
|
|
110
|
+
...renderOpaqueBlock(`integration-conflict-materialized targetHead=${result.targetHead}`, "", columns),
|
|
111
|
+
...collectionLines("conflictPaths", result.conflictPaths, indent, columns),
|
|
112
|
+
...renderOpaqueBlock(`workspace ${result.workspace.kind} ${result.workspace.path}`, indent, columns),
|
|
113
|
+
].join("\n");
|
|
114
|
+
}
|
|
84
115
|
export function renderBindDraftReceipt(receipt) {
|
|
85
116
|
return [
|
|
86
117
|
...(receipt.path === undefined ? [] : [`draft preserved: ${receipt.path}`]),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { renderObservation } from "./board.js";
|
|
2
2
|
import { renderAccepted, renderContractHistory, renderRetry } from "./contract.js";
|
|
3
3
|
import { renderKanshiText } from "./kanshi.js";
|
|
4
|
-
import { renderRefusal } from "./refusal.js";
|
|
4
|
+
import { renderConflictMaterialized, renderRefusal } from "./refusal.js";
|
|
5
5
|
import { renderCatalogText } from "./catalog.js";
|
|
6
|
+
import { renderNukeText } from "./nuke.js";
|
|
6
7
|
import { renderRegionText } from "./region.js";
|
|
7
8
|
export function renderText(result, context) {
|
|
8
9
|
if (result.kind === "guidance")
|
|
@@ -15,11 +16,15 @@ export function renderText(result, context) {
|
|
|
15
16
|
return renderContractHistory(result.history);
|
|
16
17
|
if (result.kind === "region")
|
|
17
18
|
return renderRegionText(result.region);
|
|
19
|
+
if (result.kind === "nuke")
|
|
20
|
+
return renderNukeText(result.result);
|
|
18
21
|
if (result.kind === "accepted")
|
|
19
22
|
return renderAccepted(result, context);
|
|
20
23
|
if (result.kind === "refused")
|
|
21
24
|
return renderRefusal(result, context);
|
|
22
25
|
if (result.kind === "retry")
|
|
23
26
|
return renderRetry(result, context);
|
|
27
|
+
if (result.kind === "integration-conflict-materialized")
|
|
28
|
+
return renderConflictMaterialized(result, context);
|
|
24
29
|
return renderObservation(result);
|
|
25
30
|
}
|