@astrosheep/keiyaku 4.1.1 → 4.1.2
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/src/akuma/akuma-errors.d.ts +6 -0
- package/build/src/akuma/akuma-errors.js +9 -0
- package/build/src/akuma/akuma-handle.d.ts +39 -0
- package/build/src/akuma/akuma-handle.js +263 -0
- package/build/src/akuma/akuma-observe.d.ts +19 -0
- package/build/src/akuma/akuma-observe.js +74 -0
- package/build/src/akuma/akuma-product-symbols.d.ts +1 -0
- package/build/src/akuma/akuma-product-symbols.js +1 -0
- package/build/src/akuma/akuma-product.d.ts +18 -0
- package/build/src/akuma/akuma-product.js +154 -0
- package/build/src/akuma/akuma.d.ts +23 -70
- package/build/src/akuma/akuma.js +17 -433
- package/build/src/akuma/body-supervisor.d.ts +26 -0
- package/build/src/akuma/body-supervisor.js +89 -0
- package/build/src/akuma/body.d.ts +1 -1
- package/build/src/akuma/body.js +3 -2
- package/build/src/akuma/projection-read.d.ts +17 -0
- package/build/src/akuma/projection-read.js +135 -0
- package/build/src/akuma/projection.d.ts +1 -18
- package/build/src/akuma/projection.js +21 -155
- package/build/src/akuma/request-execution.d.ts +6 -0
- package/build/src/akuma/request-execution.js +86 -0
- package/build/src/akuma/request-serve.d.ts +12 -1
- package/build/src/akuma/request-serve.js +2 -102
- package/build/src/akuma/{body-turn.d.ts → turn-drive.d.ts} +2 -25
- package/build/src/akuma/{body-turn.js → turn-drive.js} +4 -99
- package/build/src/cli/commands/akuma.d.ts +0 -6
- package/build/src/cli/commands/akuma.js +1 -11
- package/build/src/cli/commands/contract-invoke.d.ts +25 -0
- package/build/src/cli/commands/contract-invoke.js +193 -0
- package/build/src/cli/commands/contract.d.ts +12 -0
- package/build/src/cli/commands/contract.js +229 -0
- package/build/src/cli/invoke.js +24 -184
- package/build/src/cli/parse.d.ts +1 -1
- package/build/src/cli/parse.js +8 -222
- package/build/src/cli/render/akuma-activity.d.ts +38 -0
- package/build/src/cli/render/akuma-activity.js +362 -0
- package/build/src/cli/render/akuma.d.ts +1 -1
- package/build/src/cli/render/akuma.js +14 -371
- package/build/src/cli/render/contract-history.d.ts +2 -0
- package/build/src/cli/render/contract-history.js +83 -0
- package/build/src/cli/render/contract.d.ts +1 -2
- package/build/src/cli/render/contract.js +1 -83
- package/build/src/git/reconcile.d.ts +8 -1
- package/build/src/git/reconcile.js +13 -301
- package/build/src/git/scratch.d.ts +8 -5
- package/build/src/git/scratch.js +29 -2
- package/build/src/git/terminal-reconcile.d.ts +21 -0
- package/build/src/git/terminal-reconcile.js +278 -0
- package/build/src/library/contract-bind.d.ts +26 -0
- package/build/src/library/contract-bind.js +106 -0
- package/build/src/library/contract-operations.d.ts +77 -0
- package/build/src/library/contract-operations.js +130 -0
- package/build/src/library/contract-types.d.ts +95 -0
- package/build/src/library/contract-types.js +1 -0
- package/build/src/library/contract.d.ts +11 -136
- package/build/src/library/contract.js +9 -222
- package/package.json +1 -1
|
@@ -1,340 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const DEFAULT_CONTEXT = { columns: 80, color: false };
|
|
5
|
-
const SNAPSHOT_RULER = "────────────";
|
|
6
|
-
const TIME_WIDTH = 5;
|
|
7
|
-
const VERB_WIDTH = 6;
|
|
8
|
-
function identity(id, alias) {
|
|
9
|
-
return `${id}${alias === undefined ? "" : ` (${alias})`}`;
|
|
10
|
-
}
|
|
11
|
-
function associatedContractId(contract) {
|
|
12
|
-
return contract.kind === "associated" ? contract.contractId : undefined;
|
|
13
|
-
}
|
|
14
|
-
function associatedIdentity(id, alias, contract) {
|
|
15
|
-
const contractId = contract === undefined ? undefined : associatedContractId(contract);
|
|
16
|
-
return `${identity(id, alias)}${contractId === undefined ? "" : ` [${contractId}]`}`;
|
|
17
|
-
}
|
|
18
|
-
function snapshotHeading(id, alias, contract) {
|
|
19
|
-
const contractId = contract === undefined ? undefined : associatedContractId(contract);
|
|
20
|
-
return [identity(id, alias), SNAPSHOT_RULER, ...(contractId === undefined ? [] : [`└─ ${contractId}`])];
|
|
21
|
-
}
|
|
22
|
-
function answeredHeading(id, alias) {
|
|
23
|
-
return [`✓ came back ${identity(id, alias)}`, SNAPSHOT_RULER].join("\n");
|
|
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
|
-
}
|
|
31
|
-
function lifeLabel(life) {
|
|
32
|
-
if (life === "running")
|
|
33
|
-
return "● STILL RUNNING";
|
|
34
|
-
if (life === "asleep")
|
|
35
|
-
return "✓ came back";
|
|
36
|
-
if (life === "killed")
|
|
37
|
-
return "× killed";
|
|
38
|
-
return `? ${life}`;
|
|
39
|
-
}
|
|
40
|
-
function pendingWithoutLiveBody(status) {
|
|
41
|
-
if (status.life === "running")
|
|
42
|
-
return 0;
|
|
43
|
-
return status.timeline.entries.reduce((count, entry) => count + (entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending" ? 1 : 0), 0);
|
|
44
|
-
}
|
|
45
|
-
function clock(at) {
|
|
46
|
-
const date = new Date(at);
|
|
47
|
-
return Number.isFinite(date.getTime())
|
|
48
|
-
? `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`
|
|
49
|
-
: "unknown";
|
|
50
|
-
}
|
|
51
|
-
function label(row) {
|
|
52
|
-
if (row.kind === "said")
|
|
53
|
-
return "say";
|
|
54
|
-
if (row.kind === "thought")
|
|
55
|
-
return "think";
|
|
56
|
-
if (row.kind === "note")
|
|
57
|
-
return "note";
|
|
58
|
-
if (row.kind === "call")
|
|
59
|
-
return "call";
|
|
60
|
-
if (row.kind === "tell")
|
|
61
|
-
return "tell";
|
|
62
|
-
if (row.kind === "outcome")
|
|
63
|
-
return row.outcome.kind === "answered" ? "say" : "error";
|
|
64
|
-
if (row.kind === "turn")
|
|
65
|
-
return "call";
|
|
66
|
-
return toolRepr(row).label;
|
|
67
|
-
}
|
|
68
|
-
function mark(row) {
|
|
69
|
-
if (row.kind === "outcome")
|
|
70
|
-
return row.outcome.kind === "answered" ? "✓" : "!";
|
|
71
|
-
if (row.kind === "tell" && row.state === "pending")
|
|
72
|
-
return "⧗";
|
|
73
|
-
if (row.kind === "tool") {
|
|
74
|
-
if (row.state === "active")
|
|
75
|
-
return "⧖";
|
|
76
|
-
if (row.state === "unsettled")
|
|
77
|
-
return "?";
|
|
78
|
-
return row.state.status === "ok" ? "✓" : "!";
|
|
79
|
-
}
|
|
80
|
-
return "│";
|
|
81
|
-
}
|
|
82
|
-
function rowText(row) {
|
|
83
|
-
if (row.kind === "said" ||
|
|
84
|
-
row.kind === "thought" ||
|
|
85
|
-
row.kind === "note" ||
|
|
86
|
-
row.kind === "call" ||
|
|
87
|
-
row.kind === "tell") {
|
|
88
|
-
return {
|
|
89
|
-
text: row.text,
|
|
90
|
-
lines: row.kind === "said" || row.kind === "thought" ? 2 : row.kind === "tell" || row.kind === "call" ? 1 : 2,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
if (row.kind === "outcome")
|
|
94
|
-
return row.outcome.kind === "answered"
|
|
95
|
-
? { text: row.outcome.answer, lines: 3 }
|
|
96
|
-
: { text: row.outcome.diagnostic, lines: 2 };
|
|
97
|
-
if (row.kind === "turn")
|
|
98
|
-
return { text: "", lines: 1 };
|
|
99
|
-
const repr = toolRepr(row);
|
|
100
|
-
return {
|
|
101
|
-
text: repr.text,
|
|
102
|
-
lines: 2,
|
|
103
|
-
...(repr.overflow === "middle-ellipsis" ? { middle: true } : {}),
|
|
104
|
-
...(repr.suffix === undefined ? {} : { suffix: repr.suffix }),
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function eventPrefix(glyph, verb, time) {
|
|
108
|
-
const gutter = time === undefined ? " ".repeat(TIME_WIDTH) : time.padEnd(TIME_WIDTH);
|
|
109
|
-
return `${gutter} ${glyph} ${verb.padEnd(VERB_WIDTH)} `;
|
|
110
|
-
}
|
|
111
|
-
function continuationPrefix() {
|
|
112
|
-
return eventPrefix("│", "");
|
|
113
|
-
}
|
|
114
|
-
function quotedBody(row) {
|
|
115
|
-
return (row.kind === "said" ||
|
|
116
|
-
row.kind === "thought" ||
|
|
117
|
-
row.kind === "tell" ||
|
|
118
|
-
(row.kind === "outcome" && row.outcome.kind === "answered"));
|
|
119
|
-
}
|
|
120
|
-
function quoteLines(lines, prefix) {
|
|
121
|
-
const prefixWidth = prefix.length;
|
|
122
|
-
return lines.map((line) => {
|
|
123
|
-
const body = line.slice(prefixWidth);
|
|
124
|
-
if (body.length === 0)
|
|
125
|
-
return line;
|
|
126
|
-
return `${line.slice(0, prefixWidth)}“${body}”`;
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
function renderMiddleEllipsis(first, text, suffix, columns) {
|
|
130
|
-
const prefixWidth = displayColumns(first);
|
|
131
|
-
const remaining = columns - prefixWidth;
|
|
132
|
-
const suffixWidth = displayColumns(suffix);
|
|
133
|
-
const withSuffix = remaining - suffixWidth;
|
|
134
|
-
// `$ ` + one head char + ellipsis + tail; cue and ellipsis alone are not a subject.
|
|
135
|
-
const showSuffix = suffix.length > 0 && withSuffix >= 6;
|
|
136
|
-
return `${first}${truncateMiddleDisplayText(text, Math.max(0, showSuffix ? withSuffix : remaining))}${showSuffix ? suffix : ""}`;
|
|
137
|
-
}
|
|
138
|
-
function renderRow(row, context, history, first) {
|
|
139
|
-
const value = rowText(row);
|
|
140
|
-
const quoted = quotedBody(row);
|
|
141
|
-
const quoteWidth = quoted ? 2 : 0;
|
|
142
|
-
if (value.middle === true) {
|
|
143
|
-
return [renderMiddleEllipsis(first, value.text, value.suffix ?? "", context.columns - quoteWidth)];
|
|
144
|
-
}
|
|
145
|
-
const lines = renderBoundedTextBlock(value.text, {
|
|
146
|
-
first,
|
|
147
|
-
continuation: continuationPrefix(),
|
|
148
|
-
columns: context.columns - quoteWidth,
|
|
149
|
-
lines: history ? Number.MAX_SAFE_INTEGER : value.lines,
|
|
150
|
-
...("truncated" in row && row.truncated === true ? { truncated: true } : {}),
|
|
151
|
-
});
|
|
152
|
-
return quoted ? quoteLines(lines, first) : lines;
|
|
153
|
-
}
|
|
154
|
-
function groupedEntries(entries, context, history = false) {
|
|
155
|
-
const lines = [];
|
|
156
|
-
let previousClock;
|
|
157
|
-
for (const entry of entries) {
|
|
158
|
-
if (entry.kind === "gap") {
|
|
159
|
-
lines.push(`${" ".repeat(TIME_WIDTH)} ⋮ ${entry.count} omitted`);
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
const row = entry.row;
|
|
163
|
-
const at = clock(row.at);
|
|
164
|
-
const changed = previousClock === undefined || at !== previousClock;
|
|
165
|
-
lines.push(...renderRow(row, context, history, eventPrefix(mark(row), label(row), changed ? at : undefined)));
|
|
166
|
-
previousClock = at;
|
|
167
|
-
}
|
|
168
|
-
return lines;
|
|
169
|
-
}
|
|
170
|
-
function groupedRows(rows, context, history = false) {
|
|
171
|
-
return groupedEntries(rows.filter((row) => row.kind !== "turn").map((row) => ({ kind: "row", row })), context, history);
|
|
172
|
-
}
|
|
173
|
-
function taskDispositionMark(disposition) {
|
|
174
|
-
if (disposition === "done")
|
|
175
|
-
return "✓";
|
|
176
|
-
if (disposition === "drop")
|
|
177
|
-
return "×";
|
|
178
|
-
if (disposition === "on_hold")
|
|
179
|
-
return "⧗";
|
|
180
|
-
if (disposition === "in_progress")
|
|
181
|
-
return "●";
|
|
182
|
-
return disposition === "blocked" ? "‖" : "○";
|
|
183
|
-
}
|
|
184
|
-
function changeStat(group) {
|
|
185
|
-
let added = 0;
|
|
186
|
-
let removed = 0;
|
|
187
|
-
for (const change of group) {
|
|
188
|
-
if (change.diffstat === undefined)
|
|
189
|
-
return "+? -?";
|
|
190
|
-
added += change.diffstat.added;
|
|
191
|
-
removed += change.diffstat.removed;
|
|
192
|
-
}
|
|
193
|
-
return `+${added} -${removed}`;
|
|
194
|
-
}
|
|
195
|
-
function groupedChangeRows(changes) {
|
|
196
|
-
const groups = [];
|
|
197
|
-
const seen = new Map();
|
|
198
|
-
for (const change of changes) {
|
|
199
|
-
const index = seen.get(change.path);
|
|
200
|
-
if (index === undefined) {
|
|
201
|
-
seen.set(change.path, groups.length);
|
|
202
|
-
groups.push([change]);
|
|
203
|
-
}
|
|
204
|
-
else
|
|
205
|
-
groups[index].push(change);
|
|
206
|
-
}
|
|
207
|
-
return groups.map((group) => ({ path: group[0].path, stat: changeStat(group) }));
|
|
208
|
-
}
|
|
209
|
-
function renderReportedChangeLines(snapshot) {
|
|
210
|
-
const rows = groupedChangeRows(snapshot.reportedChanges);
|
|
211
|
-
const width = rows.reduce((max, row) => Math.max(max, row.stat.length), 0);
|
|
212
|
-
return [
|
|
213
|
-
`changes ${snapshot.reportedChanges.length + snapshot.reportedChangesOmitted}`,
|
|
214
|
-
...rows.map((row) => ` ${row.stat.padEnd(width)} ${safeText(row.path)}`),
|
|
215
|
-
...(snapshot.reportedChangesOmitted > 0 ? [` ⋮ ${snapshot.reportedChangesOmitted} earlier changes`] : []),
|
|
216
|
-
];
|
|
217
|
-
}
|
|
218
|
-
function renderTaskRow(row, columns) {
|
|
219
|
-
const prefix = ` ${taskDispositionMark(row.disposition)} ${row.id} · `;
|
|
220
|
-
const body = `${safeText(row.title)} · ${row.disposition} · P${row.priority}`;
|
|
221
|
-
const inline = `${prefix}${body}`;
|
|
222
|
-
if (displayColumns(inline) <= columns)
|
|
223
|
-
return [inline];
|
|
224
|
-
return renderBoundedTextBlock(body, {
|
|
225
|
-
first: prefix,
|
|
226
|
-
continuation: " ",
|
|
227
|
-
columns,
|
|
228
|
-
lines: Number.MAX_SAFE_INTEGER,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
function renderTaskContextLines(created, columns) {
|
|
232
|
-
if (created === undefined)
|
|
233
|
-
return [];
|
|
234
|
-
if (created.kind === "failed")
|
|
235
|
-
return [`! tasks failed ${safeText(created.diagnostic)}`];
|
|
236
|
-
return [`tasks ${created.rows.length}`, ...created.rows.flatMap((row) => renderTaskRow(row, columns))];
|
|
237
|
-
}
|
|
238
|
-
function answerContextLines(observation, columns) {
|
|
239
|
-
return [
|
|
240
|
-
...renderTaskContextLines(observation.createdTasks, columns),
|
|
241
|
-
...renderReportedChangeLines(observation.status.timeline),
|
|
242
|
-
];
|
|
243
|
-
}
|
|
244
|
-
function answeredBlock(observation, answer, alias, columns) {
|
|
245
|
-
const context = answerContextLines(observation, columns).join("\n");
|
|
246
|
-
if (context.length === 0)
|
|
247
|
-
return `${answeredHeading(observation.status.id, alias)}\n${answer}`;
|
|
248
|
-
const separator = answer.endsWith("\n") ? "\n" : "\n\n";
|
|
249
|
-
return `${answeredHeading(observation.status.id, alias)}\n${answer}${separator}${context}`;
|
|
250
|
-
}
|
|
251
|
-
function snapshotCore(view, context, options) {
|
|
252
|
-
const snapshot = view.status.timeline;
|
|
253
|
-
const activity = snapshot.kind === "idle" && snapshot.outcome !== undefined
|
|
254
|
-
? groupedRows([
|
|
255
|
-
...snapshot.entries.filter((entry) => entry.kind === "row").map((entry) => entry.row),
|
|
256
|
-
snapshot.outcome,
|
|
257
|
-
].sort((left, right) => left.sequence - right.sequence), context)
|
|
258
|
-
: groupedEntries(snapshot.entries, context);
|
|
259
|
-
const facts = [
|
|
260
|
-
...(view.status.readonly?.enforcement === "none" ? [`! ${safeText(view.status.readonly.diagnostic)}`] : []),
|
|
261
|
-
...contractFacts(view.contract),
|
|
262
|
-
...(options.facts ?? []),
|
|
263
|
-
];
|
|
264
|
-
const pending = pendingWithoutLiveBody(view.status);
|
|
265
|
-
return {
|
|
266
|
-
activity,
|
|
267
|
-
lines: [
|
|
268
|
-
...snapshotHeading(view.status.id, options.alias, view.contract),
|
|
269
|
-
...facts,
|
|
270
|
-
...activity,
|
|
271
|
-
...(pending === 0 ? [] : [`pending ${pending} tells · no live body`]),
|
|
272
|
-
],
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
function snapshotText(view, context, options = {}) {
|
|
276
|
-
const core = snapshotCore(view, context, options);
|
|
277
|
-
const taskContext = renderTaskContextLines(view.createdTasks, context.columns);
|
|
278
|
-
return [
|
|
279
|
-
...core.lines,
|
|
280
|
-
...(core.activity.length > 0 && taskContext.length > 0 ? [""] : []),
|
|
281
|
-
...taskContext,
|
|
282
|
-
...renderReportedChangeLines(view.status.timeline),
|
|
283
|
-
"",
|
|
284
|
-
lifeLabel(view.status.life),
|
|
285
|
-
].join("\n");
|
|
286
|
-
}
|
|
287
|
-
function mutationSnapshotText(view, context, options = {}) {
|
|
288
|
-
const core = snapshotCore(view, context, options);
|
|
289
|
-
return [...core.lines, ...(options.showLife === false ? [] : ["", lifeLabel(view.status.life)])].join("\n");
|
|
290
|
-
}
|
|
291
|
-
function mutationObservationStageText(id, observation, context, options = {}) {
|
|
292
|
-
if (observation.kind === "unobserved")
|
|
293
|
-
return unobservedText(id, observation.diagnostic);
|
|
294
|
-
return mutationSnapshotText(observation, context, options);
|
|
295
|
-
}
|
|
296
|
-
function waitText(result, context) {
|
|
297
|
-
const alias = result.alias;
|
|
298
|
-
const total = result.result.observations.length + result.result.unobserved.length;
|
|
299
|
-
const done = result.result.observations.filter((observation) => defaultWaitComplete(observation.status)).length;
|
|
300
|
-
const blocks = [
|
|
301
|
-
...result.result.observations.map((observation) => {
|
|
302
|
-
const answer = statusAnswer(observation);
|
|
303
|
-
if (answer !== undefined)
|
|
304
|
-
return answeredBlock(observation, answer, alias, context.columns);
|
|
305
|
-
return snapshotText(observation, context, { ...(alias === undefined ? {} : { alias }) });
|
|
306
|
-
}),
|
|
307
|
-
...result.result.unobserved.map((member) => unobservedText(member.id, member.diagnostic)),
|
|
308
|
-
];
|
|
309
|
-
if (total <= 1)
|
|
310
|
-
return blocks.join("\n\n");
|
|
311
|
-
return [...blocks, `${done} of ${total} done`].join("\n\n");
|
|
312
|
-
}
|
|
313
|
-
function historyText(command, result, context) {
|
|
314
|
-
if (command.last)
|
|
315
|
-
return result.mode === "last" ? result.answer : "no answer retained";
|
|
316
|
-
if (result.mode !== "page")
|
|
317
|
-
throw new Error("history result lacks page");
|
|
318
|
-
return [
|
|
319
|
-
...snapshotHeading(result.akuma, result.alias, result.historyResult.contract),
|
|
320
|
-
...groupedRows(result.history.rows, context, true),
|
|
321
|
-
].join("\n");
|
|
322
|
-
}
|
|
323
|
-
function tellText(result, context) {
|
|
324
|
-
const wake = result.result.tell.wake;
|
|
325
|
-
const facts = wake.kind === "failed"
|
|
326
|
-
? [
|
|
327
|
-
`! wake failed · ${safeText(wake.diagnostic)}${wake.child === undefined ? "" : ` · log ${wake.child.log.path} ${wake.child.log.from}..${wake.child.log.to}`}`,
|
|
328
|
-
]
|
|
329
|
-
: wake.kind === "pursuing"
|
|
330
|
-
? []
|
|
331
|
-
: [`wake ${wake.kind}`];
|
|
332
|
-
return mutationObservationStageText(result.result.akuma, result.result.observation, context, {
|
|
333
|
-
...(result.alias === undefined ? {} : { alias: result.alias }),
|
|
334
|
-
facts,
|
|
335
|
-
showLife: false,
|
|
336
|
-
});
|
|
337
|
-
}
|
|
1
|
+
import { DEFAULT_CONTEXT, akumaRawAnswer, associatedIdentity, historyText, mutationObservationStageText, snapshotHeading, snapshotText, tellText, waitText, } from "./akuma-activity.js";
|
|
2
|
+
import { safeText } from "./terminal.js";
|
|
3
|
+
export { akumaRawAnswer } from "./akuma-activity.js";
|
|
338
4
|
function dispatchLines(stage) {
|
|
339
5
|
if (stage.kind === "none" || stage.kind === "dispatched")
|
|
340
6
|
return [];
|
|
@@ -344,32 +10,6 @@ function dispatchLines(stage) {
|
|
|
344
10
|
return ["dispatch failed contention"];
|
|
345
11
|
return [`dispatch failed ${stage.failure.kind} ${safeText(stage.failure.diagnostic)}`];
|
|
346
12
|
}
|
|
347
|
-
function callFailed(result) {
|
|
348
|
-
return result.dispatch.kind === "failed" || result.alias.kind === "failed" || result.readonly?.enforcement === "none";
|
|
349
|
-
}
|
|
350
|
-
function statusAnswer(view) {
|
|
351
|
-
if (!defaultWaitComplete(view.status))
|
|
352
|
-
return undefined;
|
|
353
|
-
if (view.status.life !== "asleep")
|
|
354
|
-
return undefined;
|
|
355
|
-
if (view.status.readonly?.enforcement === "none")
|
|
356
|
-
return undefined;
|
|
357
|
-
const timeline = view.status.timeline;
|
|
358
|
-
if (timeline.kind !== "idle" || timeline.outcome?.outcome.kind !== "answered")
|
|
359
|
-
return undefined;
|
|
360
|
-
return timeline.outcome.outcome.answer;
|
|
361
|
-
}
|
|
362
|
-
export function akumaRawAnswer(result) {
|
|
363
|
-
if (result.action === "call") {
|
|
364
|
-
if (callFailed(result.result) || result.result.observation.kind !== "observed")
|
|
365
|
-
return undefined;
|
|
366
|
-
return statusAnswer({ status: result.result.observation.status });
|
|
367
|
-
}
|
|
368
|
-
if (result.action === "wait" && result.result.observations.length === 1) {
|
|
369
|
-
return statusAnswer(result.result.observations[0]);
|
|
370
|
-
}
|
|
371
|
-
return undefined;
|
|
372
|
-
}
|
|
373
13
|
function executionCwdLine(result) {
|
|
374
14
|
return result.execution.source === "contract-worktree" ? [`cwd ${result.execution.cwd}`] : [];
|
|
375
15
|
}
|
|
@@ -391,7 +31,9 @@ function callText(result, context) {
|
|
|
391
31
|
...restraint,
|
|
392
32
|
...facts,
|
|
393
33
|
];
|
|
394
|
-
if (!
|
|
34
|
+
if (!(result.result.dispatch.kind === "failed" ||
|
|
35
|
+
result.result.alias.kind === "failed" ||
|
|
36
|
+
result.result.readonly?.enforcement === "none")) {
|
|
395
37
|
const selector = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : result.result.akuma;
|
|
396
38
|
lines.push(`$ keiyaku -C ${posixShellArgument(result.world)} wait ${selector} --timeout 5m`);
|
|
397
39
|
}
|
|
@@ -409,10 +51,7 @@ function callText(result, context) {
|
|
|
409
51
|
return snapshotText({
|
|
410
52
|
status: result.result.observation.status,
|
|
411
53
|
contract: contractId === undefined ? { kind: "none" } : { kind: "associated", contractId },
|
|
412
|
-
}, context, {
|
|
413
|
-
...(alias === undefined ? {} : { alias }),
|
|
414
|
-
facts: [...cwd, ...facts],
|
|
415
|
-
});
|
|
54
|
+
}, context, { ...(alias === undefined ? {} : { alias }), facts: [...cwd, ...facts] });
|
|
416
55
|
}
|
|
417
56
|
export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
|
|
418
57
|
const answer = akumaRawAnswer(result);
|
|
@@ -473,9 +112,13 @@ function killExitCode(result) {
|
|
|
473
112
|
: 0;
|
|
474
113
|
}
|
|
475
114
|
function tellExitCode(result) {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
115
|
+
return result.mode === "ordinary"
|
|
116
|
+
? result.result.tell.wake.kind === "failed"
|
|
117
|
+
? 2
|
|
118
|
+
: 0
|
|
119
|
+
: result.result.receipt.kind === "interrupted"
|
|
120
|
+
? 0
|
|
121
|
+
: 1;
|
|
479
122
|
}
|
|
480
123
|
function forkExitCode(result) {
|
|
481
124
|
return result.receipt.kind === "forked" ? 0 : result.receipt.kind === "upstream-forked" ? 2 : 1;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { receiptPayload } from "./receipt.js";
|
|
2
|
+
function journalCount(events, source) {
|
|
3
|
+
return events.filter((event) => event.source === source).length;
|
|
4
|
+
}
|
|
5
|
+
function journalHead(fact) {
|
|
6
|
+
return fact.actor === undefined
|
|
7
|
+
? `${fact.at} ${fact.kind} · ${fact.entry}`
|
|
8
|
+
: `${fact.at} ${fact.kind} · ${fact.entry} · ${fact.actor}`;
|
|
9
|
+
}
|
|
10
|
+
function listFact(label, values) {
|
|
11
|
+
return values.length === 0 ? [` ${label} 0`] : [` ${label} ${values.join(" · ")}`];
|
|
12
|
+
}
|
|
13
|
+
function journalBody(fact) {
|
|
14
|
+
switch (fact.kind) {
|
|
15
|
+
case "bind": {
|
|
16
|
+
const { coordinates, terms } = fact.data;
|
|
17
|
+
return [
|
|
18
|
+
` start ${coordinates.start}`,
|
|
19
|
+
...(coordinates.target === undefined ? [] : [` target ${coordinates.target}`]),
|
|
20
|
+
` workspace ${coordinates.workspace}`,
|
|
21
|
+
` document ${terms.document.key}`,
|
|
22
|
+
...listFact("gates", terms.gates),
|
|
23
|
+
...listFact("after", terms.after),
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
case "amend":
|
|
27
|
+
return [
|
|
28
|
+
` document ${fact.data.document.key}`,
|
|
29
|
+
...listFact("gates", fact.data.gates),
|
|
30
|
+
...listFact("after", fact.data.after),
|
|
31
|
+
];
|
|
32
|
+
case "bound":
|
|
33
|
+
return [];
|
|
34
|
+
case "deliver": {
|
|
35
|
+
const { tenderSnapshot, integration, method, policy } = fact.data;
|
|
36
|
+
return [
|
|
37
|
+
` tender ${tenderSnapshot}`,
|
|
38
|
+
` predecessor ${integration.predecessor}`,
|
|
39
|
+
` snapshot ${integration.snapshot}`,
|
|
40
|
+
` change ${integration.changeId}`,
|
|
41
|
+
` method ${method}`,
|
|
42
|
+
` require-branches-to-be-up-to-date ${String(policy.requireBranchesToBeUpToDate)}`,
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
case "reintegrated":
|
|
46
|
+
return [` predecessor ${fact.data.predecessor}`, ` snapshot ${fact.data.snapshot}`];
|
|
47
|
+
case "attestation": {
|
|
48
|
+
const lines = [` gate ${fact.data.gate}`, ` verdict ${fact.data.verdict}`, ` subject ${fact.data.subject}`];
|
|
49
|
+
if (fact.data.summary !== undefined)
|
|
50
|
+
receiptPayload(lines, "summary", fact.data.summary);
|
|
51
|
+
return lines;
|
|
52
|
+
}
|
|
53
|
+
case "claimed":
|
|
54
|
+
return [` delivery ${fact.data.delivery}`];
|
|
55
|
+
case "arc": {
|
|
56
|
+
const lines = [` sequence ${String(fact.data.seq)}`, ` title ${fact.data.title}`];
|
|
57
|
+
receiptPayload(lines, "objective", fact.data.objective);
|
|
58
|
+
receiptPayload(lines, "brief", fact.data.brief);
|
|
59
|
+
return lines;
|
|
60
|
+
}
|
|
61
|
+
case "abandoned": {
|
|
62
|
+
if (fact.data.note === undefined)
|
|
63
|
+
return [];
|
|
64
|
+
const lines = [];
|
|
65
|
+
receiptPayload(lines, "note", fact.data.note);
|
|
66
|
+
return lines;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function contractHistoryEventLines(event) {
|
|
71
|
+
if (event.source === "dispatch")
|
|
72
|
+
return [`${event.dispatch.dispatchedAt} dispatch · ${event.dispatch.akuId}`];
|
|
73
|
+
return [journalHead(event.fact), ...journalBody(event.fact)];
|
|
74
|
+
}
|
|
75
|
+
export function renderContractHistory(history) {
|
|
76
|
+
const journals = journalCount(history.events, "journal");
|
|
77
|
+
const dispatches = journalCount(history.events, "dispatch");
|
|
78
|
+
return [
|
|
79
|
+
`history ${history.id} · ${journals} journal · ${dispatches} dispatch`,
|
|
80
|
+
"",
|
|
81
|
+
...history.events.flatMap(contractHistoryEventLines),
|
|
82
|
+
].join("\n");
|
|
83
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { ContractHistory } from "../../index.js";
|
|
2
1
|
import type { AcceptedResult, RetryResult } from "../result.js";
|
|
3
2
|
import { type TextRenderContext } from "./terminal.js";
|
|
4
3
|
export declare function renderAccepted(result: AcceptedResult, context?: TextRenderContext): string;
|
|
5
4
|
export declare function renderRetry(result: RetryResult, context?: TextRenderContext): string;
|
|
6
|
-
export
|
|
5
|
+
export { renderContractHistory } from "./contract-history.js";
|
|
@@ -341,86 +341,4 @@ export function renderRetry(result, context) {
|
|
|
341
341
|
: [];
|
|
342
342
|
return [...outcomeLines("?", result.verb, "retry", result.contract, columns), ...detail].join("\n");
|
|
343
343
|
}
|
|
344
|
-
|
|
345
|
-
return events.filter((event) => event.source === source).length;
|
|
346
|
-
}
|
|
347
|
-
function journalHead(fact) {
|
|
348
|
-
return fact.actor === undefined
|
|
349
|
-
? `${fact.at} ${fact.kind} · ${fact.entry}`
|
|
350
|
-
: `${fact.at} ${fact.kind} · ${fact.entry} · ${fact.actor}`;
|
|
351
|
-
}
|
|
352
|
-
function listFact(label, values) {
|
|
353
|
-
return values.length === 0 ? [` ${label} 0`] : [` ${label} ${values.join(" · ")}`];
|
|
354
|
-
}
|
|
355
|
-
function journalBody(fact) {
|
|
356
|
-
switch (fact.kind) {
|
|
357
|
-
case "bind": {
|
|
358
|
-
const { coordinates, terms } = fact.data;
|
|
359
|
-
return [
|
|
360
|
-
` start ${coordinates.start}`,
|
|
361
|
-
...(coordinates.target === undefined ? [] : [` target ${coordinates.target}`]),
|
|
362
|
-
` workspace ${coordinates.workspace}`,
|
|
363
|
-
` document ${terms.document.key}`,
|
|
364
|
-
...listFact("gates", terms.gates),
|
|
365
|
-
...listFact("after", terms.after),
|
|
366
|
-
];
|
|
367
|
-
}
|
|
368
|
-
case "amend":
|
|
369
|
-
return [
|
|
370
|
-
` document ${fact.data.document.key}`,
|
|
371
|
-
...listFact("gates", fact.data.gates),
|
|
372
|
-
...listFact("after", fact.data.after),
|
|
373
|
-
];
|
|
374
|
-
case "bound":
|
|
375
|
-
return [];
|
|
376
|
-
case "deliver": {
|
|
377
|
-
const { tenderSnapshot, integration, method, policy } = fact.data;
|
|
378
|
-
return [
|
|
379
|
-
` tender ${tenderSnapshot}`,
|
|
380
|
-
` predecessor ${integration.predecessor}`,
|
|
381
|
-
` snapshot ${integration.snapshot}`,
|
|
382
|
-
` change ${integration.changeId}`,
|
|
383
|
-
` method ${method}`,
|
|
384
|
-
` require-branches-to-be-up-to-date ${String(policy.requireBranchesToBeUpToDate)}`,
|
|
385
|
-
];
|
|
386
|
-
}
|
|
387
|
-
case "reintegrated":
|
|
388
|
-
return [` predecessor ${fact.data.predecessor}`, ` snapshot ${fact.data.snapshot}`];
|
|
389
|
-
case "attestation": {
|
|
390
|
-
const lines = [` gate ${fact.data.gate}`, ` verdict ${fact.data.verdict}`, ` subject ${fact.data.subject}`];
|
|
391
|
-
if (fact.data.summary !== undefined)
|
|
392
|
-
receiptPayload(lines, "summary", fact.data.summary);
|
|
393
|
-
return lines;
|
|
394
|
-
}
|
|
395
|
-
case "claimed":
|
|
396
|
-
return [` delivery ${fact.data.delivery}`];
|
|
397
|
-
case "arc": {
|
|
398
|
-
const lines = [` sequence ${String(fact.data.seq)}`, ` title ${fact.data.title}`];
|
|
399
|
-
receiptPayload(lines, "objective", fact.data.objective);
|
|
400
|
-
receiptPayload(lines, "brief", fact.data.brief);
|
|
401
|
-
return lines;
|
|
402
|
-
}
|
|
403
|
-
case "abandoned": {
|
|
404
|
-
if (fact.data.note === undefined)
|
|
405
|
-
return [];
|
|
406
|
-
const lines = [];
|
|
407
|
-
receiptPayload(lines, "note", fact.data.note);
|
|
408
|
-
return lines;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
function contractHistoryEventLines(event) {
|
|
413
|
-
if (event.source === "dispatch") {
|
|
414
|
-
return [`${event.dispatch.dispatchedAt} dispatch · ${event.dispatch.akuId}`];
|
|
415
|
-
}
|
|
416
|
-
return [journalHead(event.fact), ...journalBody(event.fact)];
|
|
417
|
-
}
|
|
418
|
-
export function renderContractHistory(history) {
|
|
419
|
-
const journals = journalCount(history.events, "journal");
|
|
420
|
-
const dispatches = journalCount(history.events, "dispatch");
|
|
421
|
-
return [
|
|
422
|
-
`history ${history.id} · ${journals} journal · ${dispatches} dispatch`,
|
|
423
|
-
"",
|
|
424
|
-
...history.events.flatMap(contractHistoryEventLines),
|
|
425
|
-
].join("\n");
|
|
426
|
-
}
|
|
344
|
+
export { renderContractHistory } from "./contract-history.js";
|
|
@@ -4,7 +4,7 @@ import type { ContractId, ContractState, SnapshotId } from "../core/facts/types.
|
|
|
4
4
|
import type { GitDecodeChannel } from "./read-observation.js";
|
|
5
5
|
import { type TargetCheckoutEffect, type TargetCheckoutLag } from "./target-placement.js";
|
|
6
6
|
import { type WorktreeHookLag, type WorktreeHooks } from "./hooks.js";
|
|
7
|
-
import {
|
|
7
|
+
import type { UnsealedBytes } from "./terminal-seal.js";
|
|
8
8
|
export type Effect = Readonly<{
|
|
9
9
|
kind: "worktree";
|
|
10
10
|
path: string;
|
|
@@ -66,6 +66,13 @@ export type GitReconcileObservation = Readonly<{
|
|
|
66
66
|
state: ContractState | null;
|
|
67
67
|
result: ReconcileResult;
|
|
68
68
|
}>;
|
|
69
|
+
export type WorktreeTopology = Readonly<{
|
|
70
|
+
paths: Set<string>;
|
|
71
|
+
}>;
|
|
72
|
+
export type ReconcileAccumulation = Readonly<{
|
|
73
|
+
effects: Effect[];
|
|
74
|
+
lag: ReconcileLag[];
|
|
75
|
+
}>;
|
|
69
76
|
export declare function reconcile(input: ReconcileInput): Promise<GitReconcileObservation>;
|
|
70
77
|
export declare function reconcileObservationFailure(error: unknown): ReconcileResult;
|
|
71
78
|
export declare function reconcileEffectFailure(error: unknown, prior?: ReconcileResult): ReconcileResult;
|