@astrosheep/keiyaku 4.1.0 → 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/README.md +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +3 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -6
- 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 +37 -81
- package/build/src/akuma/akuma.js +39 -447
- package/build/src/akuma/allowed.d.ts +1 -0
- package/build/src/akuma/allowed.js +6 -0
- package/build/src/akuma/archetype.js +8 -5
- 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 +45 -4
- package/build/src/akuma/body.js +145 -35
- package/build/src/akuma/coordinate.js +17 -7
- package/build/src/akuma/heart/facts.js +1 -1
- package/build/src/akuma/heart/index.d.ts +1 -1
- package/build/src/akuma/heart/index.js +2 -4
- package/build/src/akuma/heart/request-authority.js +4 -4
- package/build/src/akuma/heart/request-rows.js +27 -16
- package/build/src/akuma/heart/rows.js +79 -41
- package/build/src/akuma/heart/soul.js +1 -1
- package/build/src/akuma/heart/storage.d.ts +1 -0
- package/build/src/akuma/heart/storage.js +76 -11
- package/build/src/akuma/heart/tells.js +35 -18
- package/build/src/akuma/heart/timeline.js +19 -11
- package/build/src/akuma/identity.d.ts +1 -0
- package/build/src/akuma/identity.js +1 -0
- package/build/src/akuma/index.d.ts +3 -3
- package/build/src/akuma/index.js +1 -1
- package/build/src/akuma/nuke.js +106 -14
- 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 -16
- package/build/src/akuma/projection.js +77 -154
- package/build/src/akuma/provider-recipe.js +11 -5
- package/build/src/akuma/provider.js +105 -62
- package/build/src/akuma/providers/acp/config.js +5 -6
- package/build/src/akuma/providers/acp/core.js +17 -10
- package/build/src/akuma/providers/acp/events.js +38 -29
- package/build/src/akuma/providers/acp/index.js +13 -9
- package/build/src/akuma/providers/claude/events.js +8 -12
- package/build/src/akuma/providers/claude/index.d.ts +1 -0
- package/build/src/akuma/providers/claude/index.js +55 -26
- package/build/src/akuma/providers/claude/input.js +6 -2
- package/build/src/akuma/providers/codex-app-server/events.js +61 -36
- package/build/src/akuma/providers/codex-app-server/index.js +25 -13
- package/build/src/akuma/providers/grok-build/index.js +22 -25
- package/build/src/akuma/providers/index.js +2 -18
- package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
- package/build/src/akuma/providers/opencode-sdk/index.js +26 -17
- package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
- package/build/src/akuma/providers/pi/events.js +26 -19
- package/build/src/akuma/providers/pi/index.js +58 -40
- package/build/src/akuma/publication.js +9 -9
- 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 +19 -122
- package/build/src/akuma/request-wire.d.ts +2 -2
- package/build/src/akuma/request-wire.js +75 -102
- package/build/src/akuma/requests.js +2 -2
- package/build/src/akuma/{body-turn.d.ts → turn-drive.d.ts} +2 -25
- package/build/src/akuma/{body-turn.js → turn-drive.js} +20 -103
- package/build/src/akuma-body.js +6 -5
- package/build/src/body/amend.d.ts +4 -1
- package/build/src/body/amend.js +14 -6
- package/build/src/body/decode.js +2 -4
- package/build/src/body/envelope.js +2 -4
- package/build/src/body/region.d.ts +1 -2
- package/build/src/body/region.js +2 -70
- package/build/src/body/render.js +17 -12
- package/build/src/body/shape.js +1 -7
- package/build/src/cli/accepted.d.ts +1 -1
- package/build/src/cli/accepted.js +8 -1
- package/build/src/cli/commands/akuma-invoke.js +18 -6
- package/build/src/cli/commands/akuma.d.ts +0 -6
- package/build/src/cli/commands/akuma.js +11 -24
- package/build/src/cli/commands/amend.d.ts +2 -2
- package/build/src/cli/commands/amend.js +2 -4
- package/build/src/cli/commands/bind.d.ts +4 -4
- package/build/src/cli/commands/bind.js +16 -6
- 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 +109 -10
- package/build/src/cli/commands/contract.js +339 -16
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +23 -15
- package/build/src/cli/commands/task-invoke.js +187 -67
- package/build/src/cli/commands/task-query.js +48 -24
- package/build/src/cli/commands/task.js +150 -38
- package/build/src/cli/coordinates.js +2 -4
- package/build/src/cli/invoke.js +92 -208
- package/build/src/cli/main.js +4 -2
- package/build/src/cli/parse.d.ts +3 -90
- package/build/src/cli/parse.js +27 -233
- 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-tool-command.js +6 -7
- package/build/src/cli/render/akuma-tool.js +10 -8
- package/build/src/cli/render/akuma.d.ts +1 -1
- package/build/src/cli/render/akuma.js +61 -353
- package/build/src/cli/render/audit.js +5 -15
- package/build/src/cli/render/board.d.ts +1 -0
- package/build/src/cli/render/board.js +17 -0
- package/build/src/cli/render/catalog.js +81 -8
- 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-observation.d.ts +10 -0
- package/build/src/cli/render/contract-observation.js +58 -0
- package/build/src/cli/render/contract.d.ts +1 -2
- package/build/src/cli/render/contract.js +41 -142
- package/build/src/cli/render/kanshi.js +239 -215
- package/build/src/cli/render/receipt.js +2 -9
- package/build/src/cli/render/refusal.js +10 -15
- package/build/src/cli/render/region.js +22 -6
- package/build/src/cli/render/settings.js +4 -4
- package/build/src/cli/render/task.js +34 -14
- package/build/src/cli/render/terminal.js +16 -5
- package/build/src/cli/result.d.ts +3 -3
- package/build/src/cli/runtime.d.ts +6 -1
- package/build/src/cli/runtime.js +84 -63
- package/build/src/cli/selectors.js +2 -4
- package/build/src/cli/usage.js +6 -5
- package/build/src/contract-worktree.d.ts +1 -23
- package/build/src/contract-worktree.js +79 -155
- package/build/src/coordination/durable-file.js +7 -3
- package/build/src/coordination/sqlite-transaction-lock.js +29 -12
- package/build/src/core/facts/codec.js +7 -3
- package/build/src/core/facts/types.d.ts +1 -1
- package/build/src/core/subject.js +16 -9
- package/build/src/core/verbs/abandon.d.ts +1 -1
- package/build/src/core/verbs/abandon.js +1 -1
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +7 -7
- package/build/src/core/verbs/attestation.js +4 -1
- package/build/src/core/verbs/bind.d.ts +1 -1
- package/build/src/core/verbs/bind.js +1 -1
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +10 -8
- package/build/src/dispatch/index.js +8 -6
- package/build/src/duration.js +5 -1
- package/build/src/git/admission.js +5 -3
- package/build/src/git/hooks.d.ts +8 -0
- package/build/src/git/hooks.js +63 -14
- package/build/src/git/identity.js +1 -4
- package/build/src/git/integration.d.ts +2 -3
- package/build/src/git/integration.js +32 -39
- package/build/src/git/nuke.d.ts +1 -1
- package/build/src/git/nuke.js +110 -57
- package/build/src/git/observe.d.ts +13 -1
- package/build/src/git/observe.js +51 -44
- package/build/src/git/process.js +4 -2
- package/build/src/git/read-observation.js +10 -8
- package/build/src/git/reconcile.d.ts +22 -2
- package/build/src/git/reconcile.js +38 -274
- package/build/src/git/repository.d.ts +2 -0
- package/build/src/git/repository.js +13 -22
- package/build/src/git/scratch.d.ts +8 -5
- package/build/src/git/scratch.js +29 -2
- package/build/src/git/target-placement.d.ts +9 -10
- package/build/src/git/target-placement.js +59 -62
- package/build/src/git/tender.js +13 -46
- package/build/src/git/terminal-reconcile.d.ts +21 -0
- package/build/src/git/terminal-reconcile.js +278 -0
- package/build/src/git/terminal-seal.js +15 -12
- package/build/src/git/tree.js +5 -2
- package/build/src/git/workspace.d.ts +24 -2
- package/build/src/git/workspace.js +120 -16
- package/build/src/identity/coordinates.js +3 -1
- package/build/src/identity/selector.js +6 -3
- package/build/src/kanshi/fleet.d.ts +6 -0
- package/build/src/kanshi/fleet.js +27 -0
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +60 -48
- package/build/src/kanshi/report.d.ts +11 -23
- package/build/src/kanshi/select.js +25 -24
- package/build/src/library/address.d.ts +2 -1
- package/build/src/library/address.js +7 -8
- package/build/src/library/akuma-creation.js +20 -12
- package/build/src/library/audit.d.ts +0 -1
- package/build/src/library/audit.js +1 -2
- package/build/src/library/bind.d.ts +53 -5
- package/build/src/library/bind.js +98 -22
- package/build/src/library/catalog.d.ts +1 -0
- package/build/src/library/catalog.js +6 -3
- package/build/src/library/configuration.js +3 -1
- package/build/src/library/continuation.d.ts +15 -4
- package/build/src/library/continuation.js +24 -16
- 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 +19 -154
- package/build/src/library/contract.js +46 -261
- package/build/src/library/fleet.d.ts +1 -1
- package/build/src/library/fleet.js +19 -11
- package/build/src/library/input.d.ts +2 -0
- package/build/src/library/input.js +14 -0
- package/build/src/library/keiyaku.d.ts +8 -7
- package/build/src/library/keiyaku.js +3 -3
- package/build/src/library/nuke.js +14 -5
- package/build/src/library/reconcile.d.ts +9 -4
- package/build/src/library/reconcile.js +30 -24
- package/build/src/library/refusal.d.ts +13 -5
- package/build/src/library/refusal.js +7 -0
- package/build/src/library/region.d.ts +8 -7
- package/build/src/library/region.js +31 -11
- package/build/src/library/repo.js +2 -2
- package/build/src/markdown/lex.js +9 -2
- package/build/src/markdown/parse.js +11 -7
- package/build/src/markdown/query.js +4 -2
- package/build/src/protocol/amend.js +3 -1
- package/build/src/protocol/attempt.d.ts +7 -3
- package/build/src/protocol/attempt.js +9 -5
- package/build/src/protocol/audit.d.ts +1 -1
- package/build/src/protocol/audit.js +4 -14
- package/build/src/protocol/bind.d.ts +19 -6
- package/build/src/protocol/bind.js +28 -13
- package/build/src/protocol/completion.d.ts +0 -1
- package/build/src/protocol/completion.js +1 -3
- package/build/src/protocol/deliver.d.ts +1 -3
- package/build/src/protocol/deliver.js +15 -39
- package/build/src/protocol/intent.d.ts +1 -0
- package/build/src/protocol/intent.js +9 -7
- package/build/src/protocol/operations.d.ts +3 -7
- package/build/src/protocol/operations.js +5 -3
- package/build/src/protocol/placement.d.ts +0 -1
- package/build/src/protocol/placement.js +6 -6
- package/build/src/protocol/read/observation.d.ts +11 -0
- package/build/src/protocol/read/observation.js +37 -0
- package/build/src/protocol/read/status.d.ts +23 -12
- package/build/src/protocol/read/status.js +90 -72
- package/build/src/protocol/reconcile.d.ts +1 -0
- package/build/src/protocol/reconcile.js +2 -3
- package/build/src/protocol/reintegrate.js +1 -1
- package/build/src/protocol/review.d.ts +0 -1
- package/build/src/protocol/review.js +15 -22
- package/build/src/protocol/run.d.ts +1 -0
- package/build/src/protocol/run.js +4 -5
- package/build/src/runtime/proc/launch.d.ts +33 -0
- package/build/src/runtime/proc/launch.js +98 -0
- package/build/src/runtime/proc/line-rpc.js +9 -3
- package/build/src/runtime/proc/run.d.ts +12 -6
- package/build/src/runtime/proc/run.js +78 -21
- package/build/src/runtime/proc/stdio.js +7 -10
- package/build/src/settings.js +6 -2
- package/build/src/settlement/holder.js +13 -10
- package/build/src/settlement/settle.js +39 -6
- package/build/src/task/board.js +12 -6
- package/build/src/task/compose.js +85 -22
- package/build/src/task/context.js +21 -8
- package/build/src/task/document.js +46 -10
- package/build/src/task/identity.js +5 -2
- package/build/src/task/index.d.ts +0 -1
- package/build/src/task/index.js +119 -34
- package/build/src/task/input.js +29 -7
- package/build/src/task/mutation.js +61 -19
- package/build/src/task/operations.d.ts +6 -1
- package/build/src/task/operations.js +83 -29
- package/build/src/task/query.js +55 -26
- package/build/src/task/store.d.ts +3 -1
- package/build/src/task/store.js +81 -17
- package/build/src/verification/execution.js +14 -11
- package/build/src/workspace-place.js +19 -7
- package/build/src/world.js +16 -6
- package/package.json +8 -3
|
@@ -1,301 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const OPENING_STROKE = "─────";
|
|
5
|
-
const TIME_WIDTH = 5;
|
|
6
|
-
const VERB_WIDTH = 6;
|
|
7
|
-
function identity(id, alias) {
|
|
8
|
-
return `${id}${alias === undefined ? "" : ` (${alias})`}`;
|
|
9
|
-
}
|
|
10
|
-
function associatedContractId(contract) {
|
|
11
|
-
return contract.kind === "associated" ? contract.contractId : undefined;
|
|
12
|
-
}
|
|
13
|
-
function associatedIdentity(id, alias, contract) {
|
|
14
|
-
const contractId = contract === undefined ? undefined : associatedContractId(contract);
|
|
15
|
-
return `${identity(id, alias)}${contractId === undefined ? "" : ` [${contractId}]`}`;
|
|
16
|
-
}
|
|
17
|
-
function ruler(columns) {
|
|
18
|
-
return "─".repeat(Math.max(OPENING_STROKE.length, columns));
|
|
19
|
-
}
|
|
20
|
-
function snapshotHeading(id, alias, contract, columns) {
|
|
21
|
-
const contractId = contract === undefined ? undefined : associatedContractId(contract);
|
|
22
|
-
return [
|
|
23
|
-
identity(id, alias),
|
|
24
|
-
ruler(columns),
|
|
25
|
-
...(contractId === undefined ? [] : [`└─ ${contractId}`]),
|
|
26
|
-
];
|
|
27
|
-
}
|
|
28
|
-
function answeredHeading(id, alias, columns) {
|
|
29
|
-
return [`✓ came back ${identity(id, alias)}`, ruler(columns)].join("\n");
|
|
30
|
-
}
|
|
31
|
-
function contractFacts(contract) {
|
|
32
|
-
return contract.kind === "failed" ? [`! contract failed ${safeText(contract.diagnostic)}`] : [];
|
|
33
|
-
}
|
|
34
|
-
function unobservedText(id, diagnostic) {
|
|
35
|
-
return `! ${id} unobserved: ${safeText(diagnostic)}`;
|
|
36
|
-
}
|
|
37
|
-
function lifeLabel(life) {
|
|
38
|
-
if (life === "running")
|
|
39
|
-
return "● STILL RUNNING";
|
|
40
|
-
if (life === "asleep")
|
|
41
|
-
return "✓ came back";
|
|
42
|
-
if (life === "killed")
|
|
43
|
-
return "× killed";
|
|
44
|
-
return `? ${life}`;
|
|
45
|
-
}
|
|
46
|
-
function clock(at) {
|
|
47
|
-
const date = new Date(at);
|
|
48
|
-
return Number.isFinite(date.getTime()) ? `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}` : "unknown";
|
|
49
|
-
}
|
|
50
|
-
function label(row) {
|
|
51
|
-
if (row.kind === "said")
|
|
52
|
-
return "say";
|
|
53
|
-
if (row.kind === "thought")
|
|
54
|
-
return "think";
|
|
55
|
-
if (row.kind === "note")
|
|
56
|
-
return "note";
|
|
57
|
-
if (row.kind === "call")
|
|
58
|
-
return "call";
|
|
59
|
-
if (row.kind === "tell")
|
|
60
|
-
return "tell";
|
|
61
|
-
if (row.kind === "outcome")
|
|
62
|
-
return row.outcome.kind === "answered" ? "say" : "error";
|
|
63
|
-
if (row.kind === "turn")
|
|
64
|
-
return "call";
|
|
65
|
-
return toolRepr(row).label;
|
|
66
|
-
}
|
|
67
|
-
function mark(row) {
|
|
68
|
-
if (row.kind === "outcome")
|
|
69
|
-
return row.outcome.kind === "answered" ? "✓" : "!";
|
|
70
|
-
if (row.kind === "tell" && row.state === "pending")
|
|
71
|
-
return "⧗";
|
|
72
|
-
if (row.kind === "tool") {
|
|
73
|
-
if (row.state === "active")
|
|
74
|
-
return "⧖";
|
|
75
|
-
if (row.state === "unsettled")
|
|
76
|
-
return "?";
|
|
77
|
-
return row.state.status === "ok" ? "✓" : "!";
|
|
78
|
-
}
|
|
79
|
-
return "│";
|
|
80
|
-
}
|
|
81
|
-
function rowText(row) {
|
|
82
|
-
if (row.kind === "said" || row.kind === "thought" || row.kind === "note" || row.kind === "call" || row.kind === "tell") {
|
|
83
|
-
return { text: row.text, lines: row.kind === "said" || row.kind === "thought" ? 2 : row.kind === "tell" || row.kind === "call" ? 1 : 2 };
|
|
84
|
-
}
|
|
85
|
-
if (row.kind === "outcome")
|
|
86
|
-
return row.outcome.kind === "answered"
|
|
87
|
-
? { text: row.outcome.answer, lines: 3 }
|
|
88
|
-
: { text: row.outcome.diagnostic, lines: 2 };
|
|
89
|
-
if (row.kind === "turn")
|
|
90
|
-
return { text: "", lines: 1 };
|
|
91
|
-
const repr = toolRepr(row);
|
|
92
|
-
return { text: repr.text, lines: 2, ...(repr.overflow === "middle-ellipsis" ? { middle: true } : {}), ...(repr.suffix === undefined ? {} : { suffix: repr.suffix }) };
|
|
93
|
-
}
|
|
94
|
-
function eventPrefix(glyph, verb, time) {
|
|
95
|
-
const gutter = time === undefined ? " ".repeat(TIME_WIDTH) : time.padEnd(TIME_WIDTH);
|
|
96
|
-
return `${gutter} ${glyph} ${verb.padEnd(VERB_WIDTH)} `;
|
|
97
|
-
}
|
|
98
|
-
function continuationPrefix() {
|
|
99
|
-
return eventPrefix("│", "");
|
|
100
|
-
}
|
|
101
|
-
function quotedBody(row) {
|
|
102
|
-
return row.kind === "said" || row.kind === "thought" || row.kind === "tell"
|
|
103
|
-
|| (row.kind === "outcome" && row.outcome.kind === "answered");
|
|
104
|
-
}
|
|
105
|
-
function quoteLines(lines, prefix) {
|
|
106
|
-
const prefixWidth = prefix.length;
|
|
107
|
-
return lines.map((line) => {
|
|
108
|
-
const body = line.slice(prefixWidth);
|
|
109
|
-
if (body.length === 0)
|
|
110
|
-
return line;
|
|
111
|
-
return `${line.slice(0, prefixWidth)}“${body}”`;
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
function renderMiddleEllipsis(first, text, suffix, columns) {
|
|
115
|
-
const prefixWidth = displayColumns(first);
|
|
116
|
-
const remaining = columns - prefixWidth;
|
|
117
|
-
const suffixWidth = displayColumns(suffix);
|
|
118
|
-
const withSuffix = remaining - suffixWidth;
|
|
119
|
-
// `$ ` + one head char + ellipsis + tail; cue and ellipsis alone are not a subject.
|
|
120
|
-
const showSuffix = suffix.length > 0 && withSuffix >= 6;
|
|
121
|
-
return `${first}${truncateMiddleDisplayText(text, Math.max(0, showSuffix ? withSuffix : remaining))}${showSuffix ? suffix : ""}`;
|
|
122
|
-
}
|
|
123
|
-
function renderRow(row, context, history, first) {
|
|
124
|
-
const value = rowText(row);
|
|
125
|
-
const quoted = quotedBody(row);
|
|
126
|
-
const quoteWidth = quoted ? 2 : 0;
|
|
127
|
-
if (value.middle === true) {
|
|
128
|
-
return [renderMiddleEllipsis(first, value.text, value.suffix ?? "", context.columns - quoteWidth)];
|
|
129
|
-
}
|
|
130
|
-
const lines = renderBoundedTextBlock(value.text, {
|
|
131
|
-
first,
|
|
132
|
-
continuation: continuationPrefix(),
|
|
133
|
-
columns: context.columns - quoteWidth,
|
|
134
|
-
lines: history ? Number.MAX_SAFE_INTEGER : value.lines,
|
|
135
|
-
...("truncated" in row && row.truncated === true ? { truncated: true } : {}),
|
|
136
|
-
});
|
|
137
|
-
return quoted ? quoteLines(lines, first) : lines;
|
|
138
|
-
}
|
|
139
|
-
function groupedEntries(entries, context, history = false) {
|
|
140
|
-
const lines = [];
|
|
141
|
-
let previousClock;
|
|
142
|
-
for (const entry of entries) {
|
|
143
|
-
if (entry.kind === "gap") {
|
|
144
|
-
lines.push(`${" ".repeat(TIME_WIDTH)} ⋮ ${entry.count} omitted`);
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
const row = entry.row;
|
|
148
|
-
const at = clock(row.at);
|
|
149
|
-
const changed = previousClock === undefined || at !== previousClock;
|
|
150
|
-
lines.push(...renderRow(row, context, history, eventPrefix(mark(row), label(row), changed ? at : undefined)));
|
|
151
|
-
previousClock = at;
|
|
152
|
-
}
|
|
153
|
-
return lines;
|
|
154
|
-
}
|
|
155
|
-
function groupedRows(rows, context, history = false) {
|
|
156
|
-
return groupedEntries(rows.filter((row) => row.kind !== "turn").map((row) => ({ kind: "row", row })), context, history);
|
|
157
|
-
}
|
|
158
|
-
function taskDispositionMark(disposition) {
|
|
159
|
-
if (disposition === "done")
|
|
160
|
-
return "✓";
|
|
161
|
-
if (disposition === "drop")
|
|
162
|
-
return "×";
|
|
163
|
-
if (disposition === "on_hold")
|
|
164
|
-
return "⧗";
|
|
165
|
-
if (disposition === "in_progress")
|
|
166
|
-
return "●";
|
|
167
|
-
return disposition === "blocked" ? "‖" : "○";
|
|
168
|
-
}
|
|
169
|
-
function changeStat(group) {
|
|
170
|
-
let added = 0;
|
|
171
|
-
let removed = 0;
|
|
172
|
-
for (const change of group) {
|
|
173
|
-
if (change.diffstat === undefined)
|
|
174
|
-
return "+? -?";
|
|
175
|
-
added += change.diffstat.added;
|
|
176
|
-
removed += change.diffstat.removed;
|
|
177
|
-
}
|
|
178
|
-
return `+${added} -${removed}`;
|
|
179
|
-
}
|
|
180
|
-
function groupedChangeRows(changes) {
|
|
181
|
-
const groups = [];
|
|
182
|
-
const seen = new Map();
|
|
183
|
-
for (const change of changes) {
|
|
184
|
-
const index = seen.get(change.path);
|
|
185
|
-
if (index === undefined) {
|
|
186
|
-
seen.set(change.path, groups.length);
|
|
187
|
-
groups.push([change]);
|
|
188
|
-
}
|
|
189
|
-
else
|
|
190
|
-
groups[index].push(change);
|
|
191
|
-
}
|
|
192
|
-
return groups.map((group) => ({ path: group[0].path, stat: changeStat(group) }));
|
|
193
|
-
}
|
|
194
|
-
function renderReportedChangeLines(snapshot) {
|
|
195
|
-
const rows = groupedChangeRows(snapshot.reportedChanges);
|
|
196
|
-
const width = rows.reduce((max, row) => Math.max(max, row.stat.length), 0);
|
|
197
|
-
return [
|
|
198
|
-
`changes ${snapshot.reportedChanges.length + snapshot.reportedChangesOmitted}`,
|
|
199
|
-
...rows.map((row) => ` ${row.stat.padEnd(width)} ${safeText(row.path)}`),
|
|
200
|
-
...(snapshot.reportedChangesOmitted > 0 ? [` ⋮ ${snapshot.reportedChangesOmitted} earlier changes`] : []),
|
|
201
|
-
];
|
|
202
|
-
}
|
|
203
|
-
function renderTaskRow(row, columns) {
|
|
204
|
-
const prefix = ` ${taskDispositionMark(row.disposition)} ${row.id} · `;
|
|
205
|
-
const body = `${safeText(row.title)} · ${row.disposition} · P${row.priority}`;
|
|
206
|
-
const inline = `${prefix}${body}`;
|
|
207
|
-
if (displayColumns(inline) <= columns)
|
|
208
|
-
return [inline];
|
|
209
|
-
return renderBoundedTextBlock(body, {
|
|
210
|
-
first: prefix,
|
|
211
|
-
continuation: " ",
|
|
212
|
-
columns,
|
|
213
|
-
lines: Number.MAX_SAFE_INTEGER,
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
function renderTaskContextLines(created, columns) {
|
|
217
|
-
if (created === undefined)
|
|
218
|
-
return [];
|
|
219
|
-
if (created.kind === "failed")
|
|
220
|
-
return [`! tasks failed ${safeText(created.diagnostic)}`];
|
|
221
|
-
return [`tasks ${created.rows.length}`, ...created.rows.flatMap((row) => renderTaskRow(row, columns))];
|
|
222
|
-
}
|
|
223
|
-
function answerContextLines(observation, columns) {
|
|
224
|
-
return [
|
|
225
|
-
...renderTaskContextLines(observation.createdTasks, columns),
|
|
226
|
-
...renderReportedChangeLines(observation.status.timeline),
|
|
227
|
-
];
|
|
228
|
-
}
|
|
229
|
-
function answeredBlock(observation, answer, alias, columns) {
|
|
230
|
-
const context = answerContextLines(observation, columns).join("\n");
|
|
231
|
-
if (context.length === 0)
|
|
232
|
-
return `${answeredHeading(observation.status.id, alias, columns)}\n${answer}`;
|
|
233
|
-
const separator = answer.endsWith("\n") ? "\n" : "\n\n";
|
|
234
|
-
return `${answeredHeading(observation.status.id, alias, columns)}\n${answer}${separator}${context}`;
|
|
235
|
-
}
|
|
236
|
-
function snapshotText(view, context, options = {}) {
|
|
237
|
-
const snapshot = view.status.timeline;
|
|
238
|
-
const activity = snapshot.kind === "idle" && snapshot.outcome !== undefined
|
|
239
|
-
? groupedRows([
|
|
240
|
-
...snapshot.entries.filter((entry) => entry.kind === "row").map((entry) => entry.row),
|
|
241
|
-
snapshot.outcome,
|
|
242
|
-
].sort((left, right) => left.sequence - right.sequence), context)
|
|
243
|
-
: groupedEntries(snapshot.entries, context);
|
|
244
|
-
const facts = [
|
|
245
|
-
...(view.status.readonly?.enforcement === "none" ? [`! ${safeText(view.status.readonly.diagnostic)}`] : []),
|
|
246
|
-
...contractFacts(view.contract),
|
|
247
|
-
...(options.facts ?? []),
|
|
248
|
-
];
|
|
249
|
-
const taskContext = renderTaskContextLines(view.createdTasks, context.columns);
|
|
250
|
-
const changes = renderReportedChangeLines(snapshot);
|
|
251
|
-
const footer = options.showLife === false ? [] : ["", lifeLabel(view.status.life)];
|
|
252
|
-
return [
|
|
253
|
-
...snapshotHeading(view.status.id, options.alias, view.contract, context.columns),
|
|
254
|
-
...facts,
|
|
255
|
-
...activity,
|
|
256
|
-
...(activity.length > 0 && taskContext.length > 0 ? [""] : []),
|
|
257
|
-
...taskContext,
|
|
258
|
-
...changes,
|
|
259
|
-
...footer,
|
|
260
|
-
].join("\n");
|
|
261
|
-
}
|
|
262
|
-
function observationStageText(id, observation, context, options = {}) {
|
|
263
|
-
if (observation.kind === "unobserved")
|
|
264
|
-
return unobservedText(id, observation.diagnostic);
|
|
265
|
-
return snapshotText(observation, context, options);
|
|
266
|
-
}
|
|
267
|
-
function waitText(result, context) {
|
|
268
|
-
const alias = result.alias;
|
|
269
|
-
const total = result.result.observations.length + result.result.unobserved.length;
|
|
270
|
-
const done = result.result.observations.filter((observation) => observation.status.life !== "running").length;
|
|
271
|
-
const blocks = [
|
|
272
|
-
...result.result.observations.map((observation) => {
|
|
273
|
-
const answer = statusAnswer(observation);
|
|
274
|
-
if (answer !== undefined)
|
|
275
|
-
return answeredBlock(observation, answer, alias, context.columns);
|
|
276
|
-
return snapshotText(observation, context, { ...(alias === undefined ? {} : { alias }) });
|
|
277
|
-
}),
|
|
278
|
-
...result.result.unobserved.map((member) => unobservedText(member.id, member.diagnostic)),
|
|
279
|
-
];
|
|
280
|
-
if (total <= 1)
|
|
281
|
-
return blocks.join("\n\n");
|
|
282
|
-
return [...blocks, `${done} of ${total} done`].join("\n\n");
|
|
283
|
-
}
|
|
284
|
-
function historyText(command, result, context) {
|
|
285
|
-
if (command.last)
|
|
286
|
-
return result.mode === "last" ? result.answer : "no answer retained";
|
|
287
|
-
if (result.mode !== "page")
|
|
288
|
-
throw new Error("history result lacks page");
|
|
289
|
-
return [...snapshotHeading(result.akuma, result.alias, result.historyResult.contract, context.columns), ...groupedRows(result.history.rows, context, true)].join("\n");
|
|
290
|
-
}
|
|
291
|
-
function tellText(result, context) {
|
|
292
|
-
const facts = typeof result.result.tell.wake === "string" ? [] : [`! error ${safeText(result.result.tell.wake.diagnostic)}`];
|
|
293
|
-
return observationStageText(result.result.akuma, result.result.observation, context, {
|
|
294
|
-
...(result.alias === undefined ? {} : { alias: result.alias }),
|
|
295
|
-
facts,
|
|
296
|
-
showLife: false,
|
|
297
|
-
});
|
|
298
|
-
}
|
|
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";
|
|
299
4
|
function dispatchLines(stage) {
|
|
300
5
|
if (stage.kind === "none" || stage.kind === "dispatched")
|
|
301
6
|
return [];
|
|
@@ -305,32 +10,6 @@ function dispatchLines(stage) {
|
|
|
305
10
|
return ["dispatch failed contention"];
|
|
306
11
|
return [`dispatch failed ${stage.failure.kind} ${safeText(stage.failure.diagnostic)}`];
|
|
307
12
|
}
|
|
308
|
-
function callFailed(result) {
|
|
309
|
-
return result.dispatch.kind === "failed"
|
|
310
|
-
|| result.alias.kind === "failed"
|
|
311
|
-
|| result.readonly?.enforcement === "none";
|
|
312
|
-
}
|
|
313
|
-
function statusAnswer(view) {
|
|
314
|
-
if (view.status.life !== "asleep")
|
|
315
|
-
return undefined;
|
|
316
|
-
if (view.status.readonly?.enforcement === "none")
|
|
317
|
-
return undefined;
|
|
318
|
-
const timeline = view.status.timeline;
|
|
319
|
-
if (timeline.kind !== "idle" || timeline.outcome?.outcome.kind !== "answered")
|
|
320
|
-
return undefined;
|
|
321
|
-
return timeline.outcome.outcome.answer;
|
|
322
|
-
}
|
|
323
|
-
export function akumaRawAnswer(result) {
|
|
324
|
-
if (result.action === "call") {
|
|
325
|
-
if (callFailed(result.result) || result.result.observation.kind !== "observed")
|
|
326
|
-
return undefined;
|
|
327
|
-
return statusAnswer({ status: result.result.observation.status });
|
|
328
|
-
}
|
|
329
|
-
if (result.action === "wait" && result.result.observations.length === 1) {
|
|
330
|
-
return statusAnswer(result.result.observations[0]);
|
|
331
|
-
}
|
|
332
|
-
return undefined;
|
|
333
|
-
}
|
|
334
13
|
function executionCwdLine(result) {
|
|
335
14
|
return result.execution.source === "contract-worktree" ? [`cwd ${result.execution.cwd}`] : [];
|
|
336
15
|
}
|
|
@@ -346,27 +25,33 @@ function callText(result, context) {
|
|
|
346
25
|
facts.push(`alias failed ${result.result.alias.failure.kind} ${safeText(result.result.alias.failure.diagnostic)}`);
|
|
347
26
|
const cwd = executionCwdLine(result.result);
|
|
348
27
|
if (result.result.observation.kind === "detached") {
|
|
349
|
-
const lines = [
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
28
|
+
const lines = [
|
|
29
|
+
...snapshotHeading(result.result.akuma, alias, contractId === undefined ? { kind: "none" } : { kind: "associated", contractId }),
|
|
30
|
+
...cwd,
|
|
31
|
+
...restraint,
|
|
32
|
+
...facts,
|
|
33
|
+
];
|
|
34
|
+
if (!(result.result.dispatch.kind === "failed" ||
|
|
35
|
+
result.result.alias.kind === "failed" ||
|
|
36
|
+
result.result.readonly?.enforcement === "none")) {
|
|
353
37
|
const selector = result.result.alias.kind === "aliased" ? result.result.alias.alias.alias : result.result.akuma;
|
|
354
38
|
lines.push(`$ keiyaku -C ${posixShellArgument(result.world)} wait ${selector} --timeout 5m`);
|
|
355
39
|
}
|
|
356
40
|
return lines.join("\n");
|
|
357
41
|
}
|
|
358
42
|
if (result.result.observation.kind === "failed") {
|
|
359
|
-
return [
|
|
360
|
-
|
|
361
|
-
|
|
43
|
+
return [
|
|
44
|
+
...snapshotHeading(result.result.akuma, alias, contractId === undefined ? { kind: "none" } : { kind: "associated", contractId }),
|
|
45
|
+
...cwd,
|
|
46
|
+
...restraint,
|
|
47
|
+
...facts,
|
|
48
|
+
`! error ${safeText(result.result.observation.failure.diagnostic)}`,
|
|
49
|
+
].join("\n");
|
|
362
50
|
}
|
|
363
51
|
return snapshotText({
|
|
364
52
|
status: result.result.observation.status,
|
|
365
53
|
contract: contractId === undefined ? { kind: "none" } : { kind: "associated", contractId },
|
|
366
|
-
}, context, {
|
|
367
|
-
...(alias === undefined ? {} : { alias }),
|
|
368
|
-
facts: [...cwd, ...facts],
|
|
369
|
-
});
|
|
54
|
+
}, context, { ...(alias === undefined ? {} : { alias }), facts: [...cwd, ...facts] });
|
|
370
55
|
}
|
|
371
56
|
export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
|
|
372
57
|
const answer = akumaRawAnswer(result);
|
|
@@ -377,14 +62,16 @@ export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
|
|
|
377
62
|
return cwd.length === 0 ? answer : `${cwd.join("\n")}\n${answer}`;
|
|
378
63
|
}
|
|
379
64
|
switch (result.action) {
|
|
380
|
-
case "call":
|
|
381
|
-
|
|
65
|
+
case "call":
|
|
66
|
+
return callText(result, context);
|
|
67
|
+
case "status":
|
|
68
|
+
return snapshotText(result.status, context, { ...(result.alias === undefined ? {} : { alias: result.alias }) });
|
|
382
69
|
case "wait":
|
|
383
70
|
return waitText(result, context);
|
|
384
71
|
case "tell":
|
|
385
72
|
return result.mode === "ordinary"
|
|
386
73
|
? tellText(result, context)
|
|
387
|
-
:
|
|
74
|
+
: mutationObservationStageText(result.result.id, result.result.observation, context, {
|
|
388
75
|
...(result.alias === undefined ? {} : { alias: result.alias }),
|
|
389
76
|
showLife: false,
|
|
390
77
|
});
|
|
@@ -392,17 +79,27 @@ export function renderAkumaText(command, result, context = DEFAULT_CONTEXT) {
|
|
|
392
79
|
return historyText(command, result, context);
|
|
393
80
|
case "fork": {
|
|
394
81
|
if (result.receipt.kind !== "forked")
|
|
395
|
-
return result.receipt.kind === "unknown-history"
|
|
82
|
+
return result.receipt.kind === "unknown-history"
|
|
83
|
+
? `${result.receipt.at} has no matching retained answered turn`
|
|
84
|
+
: result.receipt.kind === "provider-cannot-fork"
|
|
85
|
+
? `${result.receipt.provider} cannot fork`
|
|
86
|
+
: result.receipt.diagnostic;
|
|
396
87
|
const contractId = result.receipt.dispatch.kind === "dispatched" ? result.receipt.dispatch.dispatch.contractId : undefined;
|
|
397
|
-
return associatedIdentity(result.receipt.child, undefined, contractId === undefined
|
|
398
|
-
? { kind: "none" }
|
|
399
|
-
: { kind: "associated", contractId });
|
|
88
|
+
return associatedIdentity(result.receipt.child, undefined, contractId === undefined ? { kind: "none" } : { kind: "associated", contractId });
|
|
400
89
|
}
|
|
401
|
-
case "kill":
|
|
90
|
+
case "kill":
|
|
91
|
+
return result.result.results
|
|
92
|
+
.map((member) => mutationObservationStageText(member.id, member.observation, context, {
|
|
93
|
+
facts: [`kill ${member.evidence}`],
|
|
94
|
+
...(result.alias === undefined ? {} : { alias: result.alias }),
|
|
95
|
+
}))
|
|
96
|
+
.join("\n\n");
|
|
402
97
|
}
|
|
403
98
|
}
|
|
404
99
|
function callExitCode(result) {
|
|
405
|
-
if (result.result.dispatch.kind === "failed" ||
|
|
100
|
+
if (result.result.dispatch.kind === "failed" ||
|
|
101
|
+
result.result.alias.kind === "failed" ||
|
|
102
|
+
result.result.observation.kind === "failed")
|
|
406
103
|
return 2;
|
|
407
104
|
if (result.result.observation.kind !== "observed")
|
|
408
105
|
return 0;
|
|
@@ -410,23 +107,34 @@ function callExitCode(result) {
|
|
|
410
107
|
return timeline.kind === "idle" && timeline.outcome?.outcome.kind === "failed" ? 2 : 0;
|
|
411
108
|
}
|
|
412
109
|
function killExitCode(result) {
|
|
413
|
-
return result.result.results.some((member) => member.evidence === "unavailable" || member.evidence === "hung" || member.evidence === "untidy")
|
|
110
|
+
return result.result.results.some((member) => member.evidence === "unavailable" || member.evidence === "hung" || member.evidence === "untidy")
|
|
111
|
+
? 1
|
|
112
|
+
: 0;
|
|
414
113
|
}
|
|
415
114
|
function tellExitCode(result) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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;
|
|
419
122
|
}
|
|
420
123
|
function forkExitCode(result) {
|
|
421
124
|
return result.receipt.kind === "forked" ? 0 : result.receipt.kind === "upstream-forked" ? 2 : 1;
|
|
422
125
|
}
|
|
423
126
|
export function akumaExitCode(result) {
|
|
424
127
|
switch (result.action) {
|
|
425
|
-
case "call":
|
|
426
|
-
|
|
427
|
-
case "
|
|
428
|
-
|
|
429
|
-
|
|
128
|
+
case "call":
|
|
129
|
+
return callExitCode(result);
|
|
130
|
+
case "kill":
|
|
131
|
+
return killExitCode(result);
|
|
132
|
+
case "tell":
|
|
133
|
+
return tellExitCode(result);
|
|
134
|
+
case "fork":
|
|
135
|
+
return forkExitCode(result);
|
|
136
|
+
default:
|
|
137
|
+
return 0;
|
|
430
138
|
}
|
|
431
139
|
}
|
|
432
140
|
export function akumaJsonValue(result) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { cleanupLines, leakLines, receiptPayload, receiptRow, stopLines, titleLines
|
|
1
|
+
import { cleanupLines, leakLines, receiptPayload, receiptRow, stopLines, titleLines } from "./receipt.js";
|
|
2
2
|
import { renderRefusalFacts } from "./refusal.js";
|
|
3
|
-
import { gitShortStat, renderOpaqueBlock
|
|
3
|
+
import { gitShortStat, renderOpaqueBlock } from "./terminal.js";
|
|
4
4
|
const CHILD = " ";
|
|
5
5
|
function workspaceEvidence(workspace, columns) {
|
|
6
6
|
return renderOpaqueBlock(`workspace ${workspace.kind} ${workspace.path}`, CHILD, columns);
|
|
@@ -41,10 +41,7 @@ function verificationLines(verification, columns, addressed) {
|
|
|
41
41
|
if (verification.kind === "stopped") {
|
|
42
42
|
return stopLines("verification", verification.stop, columns, addressed);
|
|
43
43
|
}
|
|
44
|
-
receiptRow(lines, verification.kind === "satisfied" ? "✓" : "!", "verification", [
|
|
45
|
-
{ text: verification.kind },
|
|
46
|
-
{ text: `${verification.passed} of ${verification.total}` },
|
|
47
|
-
], columns);
|
|
44
|
+
receiptRow(lines, verification.kind === "satisfied" ? "✓" : "!", "verification", [{ text: verification.kind }, { text: `${verification.passed} of ${verification.total}` }], columns);
|
|
48
45
|
if (verification.summary !== undefined) {
|
|
49
46
|
receiptPayload(lines, "summary", verification.summary);
|
|
50
47
|
}
|
|
@@ -57,11 +54,7 @@ function targetLines(target, columns, addressed) {
|
|
|
57
54
|
return lines;
|
|
58
55
|
}
|
|
59
56
|
if (target.kind === "placeable") {
|
|
60
|
-
receiptRow(lines, "✓", "target", [
|
|
61
|
-
{ text: "placeable" },
|
|
62
|
-
{ text: target.ref, opaque: true },
|
|
63
|
-
{ text: target.head, opaque: true },
|
|
64
|
-
], columns);
|
|
57
|
+
receiptRow(lines, "✓", "target", [{ text: "placeable" }, { text: target.ref, opaque: true }, { text: target.head, opaque: true }], columns);
|
|
65
58
|
return lines;
|
|
66
59
|
}
|
|
67
60
|
if (target.kind === "moved") {
|
|
@@ -92,10 +85,7 @@ function recordLines(result, columns) {
|
|
|
92
85
|
return [];
|
|
93
86
|
const rows = [];
|
|
94
87
|
for (const fact of result.facts) {
|
|
95
|
-
receiptRow(rows, " ", "journal", [
|
|
96
|
-
{ text: fact.entry, opaque: true },
|
|
97
|
-
{ text: `· ${fact.kind}` },
|
|
98
|
-
], columns);
|
|
88
|
+
receiptRow(rows, " ", "journal", [{ text: fact.entry, opaque: true }, { text: `· ${fact.kind}` }], columns);
|
|
99
89
|
}
|
|
100
90
|
receiptRow(rows, " ", "head", [{ text: result.head, opaque: true }], columns);
|
|
101
91
|
return [" record", ...rows.map((line) => ` ${line}`)];
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
+
export function worldObservationFailureText(result) {
|
|
2
|
+
if (result.command !== "reconcile")
|
|
3
|
+
return undefined;
|
|
4
|
+
const report = result.report;
|
|
5
|
+
if (typeof report !== "object" ||
|
|
6
|
+
report === null ||
|
|
7
|
+
!("kind" in report) ||
|
|
8
|
+
report.kind !== "world-observation-failed" ||
|
|
9
|
+
!("diagnostic" in report) ||
|
|
10
|
+
typeof report.diagnostic !== "string") {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
return `reconcile: world observation failed · ${report.diagnostic}`;
|
|
14
|
+
}
|
|
1
15
|
export function renderObservation(result) {
|
|
16
|
+
const failed = worldObservationFailureText(result);
|
|
17
|
+
if (failed !== undefined)
|
|
18
|
+
return failed;
|
|
2
19
|
const { kind: _kind, command, ...observation } = result;
|
|
3
20
|
return [`observation ${command}`, JSON.stringify(observation, null, 2)].join("\n");
|
|
4
21
|
}
|
|
@@ -1,20 +1,93 @@
|
|
|
1
|
+
import { abbreviateGitIds, afterWording, candidateFact, dependentWording, displayGitId, gateFact, gitIdsInRow, } from "./contract-observation.js";
|
|
1
2
|
import { safeText } from "./terminal.js";
|
|
3
|
+
function targetLine(row) {
|
|
4
|
+
if (row.target === null)
|
|
5
|
+
return "no target";
|
|
6
|
+
const target = row.target.startsWith("refs/heads/") ? row.target.slice("refs/heads/".length) : row.target;
|
|
7
|
+
const lag = row.targetLag.kind === "counted"
|
|
8
|
+
? `${row.targetLag.behind} commits behind ${target}`
|
|
9
|
+
: row.targetLag.kind === "unknown"
|
|
10
|
+
? `commits behind ${target} unknown`
|
|
11
|
+
: undefined;
|
|
12
|
+
return [
|
|
13
|
+
`target ${target}`,
|
|
14
|
+
...(lag === undefined ? [] : [lag]),
|
|
15
|
+
...(row.targetObservation?.drift === true ? ["target moved"] : []),
|
|
16
|
+
].join(" · ");
|
|
17
|
+
}
|
|
18
|
+
function catalogMark(row) {
|
|
19
|
+
if (row.phase === "claimed")
|
|
20
|
+
return "✓";
|
|
21
|
+
if (row.phase === "abandoned")
|
|
22
|
+
return "×";
|
|
23
|
+
if (row.title === null)
|
|
24
|
+
return "?";
|
|
25
|
+
if (row.gates.reports.some((gate) => gate.current.kind === "attested" && gate.current.verdict === "unsatisfied"))
|
|
26
|
+
return "!";
|
|
27
|
+
if (row.targetLag.kind === "unknown")
|
|
28
|
+
return "?";
|
|
29
|
+
if (row.phase === "waiting")
|
|
30
|
+
return "○";
|
|
31
|
+
return "●";
|
|
32
|
+
}
|
|
33
|
+
function formatAge(source, observedAt) {
|
|
34
|
+
const seconds = Math.floor((Date.parse(observedAt) - Date.parse(source)) / 1_000);
|
|
35
|
+
if (seconds < 0)
|
|
36
|
+
return "future";
|
|
37
|
+
if (seconds < 60)
|
|
38
|
+
return `${seconds}s`;
|
|
39
|
+
const minutes = Math.floor(seconds / 60);
|
|
40
|
+
if (minutes < 60)
|
|
41
|
+
return `${minutes}m`;
|
|
42
|
+
const hours = Math.floor(minutes / 60);
|
|
43
|
+
return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
|
|
44
|
+
}
|
|
45
|
+
function renderContractCatalog(catalog) {
|
|
46
|
+
const abbreviations = abbreviateGitIds([
|
|
47
|
+
...(catalog.state === null ? [] : [catalog.state]),
|
|
48
|
+
...catalog.rows.flatMap(gitIdsInRow),
|
|
49
|
+
]);
|
|
50
|
+
const rows = catalog.rows.filter((row) => row.disposition === "active");
|
|
51
|
+
const candidates = rows.filter((row) => row.delivery !== null).length;
|
|
52
|
+
const header = [
|
|
53
|
+
`${rows.length} active · ${candidates} candidate${candidates === 1 ? "" : "s"}`,
|
|
54
|
+
catalog.state === null
|
|
55
|
+
? `observedAt ${catalog.observedAt}`
|
|
56
|
+
: `contract state ${displayGitId(catalog.state, abbreviations)} · observedAt ${catalog.observedAt}`,
|
|
57
|
+
];
|
|
58
|
+
const blocks = rows.map((row) => {
|
|
59
|
+
const lines = [
|
|
60
|
+
`${catalogMark(row)} ${safeText(row.id)} · ${row.phase} · ${formatAge(row.phaseAt, catalog.observedAt)} · ${safeText(row.title ?? "title unavailable")}`,
|
|
61
|
+
` ${candidateFact(row.delivery)} · ${targetLine(row)}`,
|
|
62
|
+
...row.after.map((edge) => ` ${afterWording(edge)}`),
|
|
63
|
+
...(row.dependents.length === 0 ? [] : [` dependents ${row.dependents.map(dependentWording).join(" · ")}`]),
|
|
64
|
+
...(row.gates.reports.length === 0 ? [] : [` ${row.gates.reports.map(gateFact).join(" ")}`]),
|
|
65
|
+
];
|
|
66
|
+
return lines.join("\n");
|
|
67
|
+
});
|
|
68
|
+
return [...header, ...(blocks.length === 0 ? [] : ["", ...blocks])].join("\n");
|
|
69
|
+
}
|
|
2
70
|
export function renderCatalogText(catalog) {
|
|
3
71
|
if (catalog.kind === "tasks") {
|
|
4
|
-
return catalog.rows
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return catalog.rows.map((row) => `${safeText(row.id)} - ${row.phase}`).join("\n");
|
|
72
|
+
return catalog.rows
|
|
73
|
+
.map((row) => `${safeText(row.id)} - P${row.priority} - ${row.disposition} - ${safeText(row.title)}`)
|
|
74
|
+
.join("\n");
|
|
8
75
|
}
|
|
76
|
+
if (catalog.kind === "contracts")
|
|
77
|
+
return renderContractCatalog(catalog);
|
|
9
78
|
if (catalog.kind === "archetypes") {
|
|
10
|
-
return catalog.rows
|
|
79
|
+
return catalog.rows
|
|
80
|
+
.flatMap((row) => [
|
|
11
81
|
`${safeText(row.name)}${row.model === undefined ? "" : ` - ${safeText(row.model)}`}`,
|
|
12
82
|
...(row.description === undefined ? [] : [` ${safeText(row.description)}`]),
|
|
13
|
-
])
|
|
83
|
+
])
|
|
84
|
+
.join("\n");
|
|
14
85
|
}
|
|
15
|
-
return catalog.rows
|
|
86
|
+
return catalog.rows
|
|
87
|
+
.map((row) => {
|
|
16
88
|
if (!("lifeAt" in row))
|
|
17
89
|
return `${safeText(row.id)} - ${row.life}`;
|
|
18
90
|
return `${safeText(row.id)} - ${row.life} - runtime ${row.lifeAt ?? "-"} - last activity ${row.lastActivityAt ?? "-"}`;
|
|
19
|
-
})
|
|
91
|
+
})
|
|
92
|
+
.join("\n");
|
|
20
93
|
}
|