@astrosheep/keiyaku 4.5.7 → 4.5.9
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 +10 -0
- 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/opencode.js +3 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +12 -11
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +33 -12
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +35 -96
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +28 -49
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +21 -15
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +148 -89
- package/build/src/akuma/abort.d.ts +2 -1
- package/build/src/akuma/abort.js +6 -23
- package/build/src/akuma/akuma-handle.js +4 -2
- package/build/src/akuma/akuma-observe.d.ts +2 -0
- package/build/src/akuma/akuma-observe.js +1 -0
- package/build/src/akuma/akuma-product.js +9 -7
- package/build/src/akuma/akuma.d.ts +392 -9
- package/build/src/akuma/akuma.js +31 -1
- package/build/src/akuma/allowed.d.ts +1 -1
- package/build/src/akuma/allowed.js +1 -0
- package/build/src/akuma/archetype.js +1 -1
- package/build/src/akuma/body.d.ts +8 -5
- package/build/src/akuma/body.js +12 -5
- package/build/src/akuma/call-request.d.ts +80 -0
- package/build/src/akuma/call-request.js +211 -0
- package/build/src/akuma/heart/facts.d.ts +16 -78
- package/build/src/akuma/heart/facts.js +11 -0
- package/build/src/akuma/heart/index.d.ts +3 -2
- package/build/src/akuma/heart/index.js +4 -1
- package/build/src/akuma/heart/request-authority.d.ts +5 -4
- package/build/src/akuma/heart/request-authority.js +20 -34
- package/build/src/akuma/heart/request-rows.js +12 -23
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +5 -13
- package/build/src/akuma/index.d.ts +1 -1
- package/build/src/akuma/index.js +1 -1
- package/build/src/akuma/projection-read.d.ts +1 -0
- package/build/src/akuma/projection-read.js +8 -1
- package/build/src/akuma/projection.d.ts +907 -137
- package/build/src/akuma/projection.js +193 -9
- package/build/src/akuma/provider.d.ts +30 -3
- package/build/src/akuma/provider.js +111 -0
- package/build/src/akuma/providers/acp/core.d.ts +2 -2
- package/build/src/akuma/providers/acp/core.js +13 -6
- package/build/src/akuma/providers/acp/index.js +5 -4
- package/build/src/akuma/providers/claude/events.d.ts +2 -2
- package/build/src/akuma/providers/claude/events.js +16 -3
- package/build/src/akuma/providers/claude/index.d.ts +3 -3
- package/build/src/akuma/providers/claude/index.js +16 -5
- package/build/src/akuma/providers/codex-app-server/events.d.ts +2 -2
- package/build/src/akuma/providers/codex-app-server/events.js +25 -4
- package/build/src/akuma/providers/codex-app-server/index.js +18 -6
- package/build/src/akuma/providers/grok-build/index.js +5 -4
- package/build/src/akuma/providers/opencode-sdk/index.js +66 -25
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +3 -2
- package/build/src/akuma/providers/opencode-sdk/session.js +28 -11
- package/build/src/akuma/providers/pi/index.js +72 -58
- package/build/src/akuma/request-lifecycle.d.ts +4 -10
- package/build/src/akuma/request-lifecycle.js +7 -5
- package/build/src/akuma/request-rendezvous.d.ts +26 -0
- package/build/src/akuma/request-rendezvous.js +100 -0
- package/build/src/akuma/request-serve.d.ts +6 -66
- package/build/src/akuma/request-serve.js +83 -210
- package/build/src/akuma/request-wire.d.ts +109 -115
- package/build/src/akuma/request-wire.js +63 -318
- package/build/src/akuma/requests.d.ts +19 -47
- package/build/src/akuma/requests.js +51 -107
- package/build/src/akuma/turn-drive.d.ts +5 -3
- package/build/src/akuma/turn-drive.js +39 -11
- package/build/src/akuma-body.d.ts +7 -2
- package/build/src/akuma-body.js +68 -46
- package/build/src/body/amend.js +18 -19
- package/build/src/cli/accepted.d.ts +1 -1
- package/build/src/cli/accepted.js +2 -2
- package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
- package/build/src/cli/commands/akuma-invoke.js +17 -9
- package/build/src/cli/commands/akuma.js +8 -8
- package/build/src/cli/commands/contract-invoke.d.ts +3 -2
- package/build/src/cli/commands/contract-invoke.js +42 -30
- package/build/src/cli/commands/contract.d.ts +16 -20
- package/build/src/cli/commands/contract.js +58 -25
- package/build/src/cli/commands/install.d.ts +2 -1
- package/build/src/cli/commands/install.js +3 -2
- package/build/src/cli/commands/task-invoke.d.ts +3 -0
- package/build/src/cli/commands/task-invoke.js +23 -140
- package/build/src/cli/commands/task.js +54 -20
- package/build/src/cli/invoke.js +39 -25
- package/build/src/cli/main.js +2 -1
- package/build/src/cli/parse.d.ts +2 -2
- package/build/src/cli/parse.js +56 -27
- package/build/src/cli/render/akuma-activity.d.ts +3 -0
- package/build/src/cli/render/akuma-activity.js +45 -29
- package/build/src/cli/render/akuma-tool.d.ts +5 -1
- package/build/src/cli/render/akuma.js +4 -8
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/catalog.js +80 -21
- package/build/src/cli/render/contract-observation.d.ts +2 -0
- package/build/src/cli/render/contract-observation.js +11 -0
- package/build/src/cli/render/contract.js +35 -62
- package/build/src/cli/render/kanshi-akuma.d.ts +8 -0
- package/build/src/cli/render/kanshi-akuma.js +132 -0
- package/build/src/cli/render/kanshi.js +131 -213
- package/build/src/cli/render/receipt.d.ts +1 -2
- package/build/src/cli/render/receipt.js +76 -26
- package/build/src/cli/render/refusal.js +2 -10
- package/build/src/cli/render/region.js +5 -2
- package/build/src/cli/render/settings.d.ts +1 -1
- package/build/src/cli/render/settings.js +27 -8
- package/build/src/cli/render/task.js +22 -5
- package/build/src/cli/render/terminal.d.ts +32 -1
- package/build/src/cli/render/terminal.js +77 -1
- package/build/src/cli/result.d.ts +3 -3
- package/build/src/cli/runtime.js +4 -2
- package/build/src/cli/selectors.d.ts +2 -1
- package/build/src/cli/selectors.js +4 -3
- package/build/src/cli/square-edge.js +120 -36
- package/build/src/cli/usage.js +2 -1
- package/build/src/contract-guidance.d.ts +5 -0
- package/build/src/contract-guidance.js +121 -0
- package/build/src/contract-worktree.d.ts +0 -1
- package/build/src/contract-worktree.js +32 -83
- package/build/src/coordination/sqlite-transaction-lock.d.ts +1 -0
- package/build/src/coordination/sqlite-transaction-lock.js +5 -0
- package/build/src/core/facts/codec.d.ts +2 -0
- package/build/src/core/facts/codec.js +4 -0
- package/build/src/core/verbs/placement.d.ts +6 -1
- package/build/src/core/verbs/placement.js +5 -3
- package/build/src/dispatch/index.d.ts +0 -2
- package/build/src/dispatch/index.js +54 -55
- package/build/src/git/admission.js +2 -2
- package/build/src/git/hooks.d.ts +9 -15
- package/build/src/git/hooks.js +23 -317
- package/build/src/git/nuke.d.ts +2 -1
- package/build/src/git/nuke.js +39 -21
- package/build/src/git/private-state-seat.d.ts +12 -0
- package/build/src/git/private-state-seat.js +39 -0
- package/build/src/git/process.d.ts +6 -0
- package/build/src/git/process.js +26 -11
- package/build/src/git/read-observation.js +29 -20
- package/build/src/git/reconcile.d.ts +13 -1
- package/build/src/git/reconcile.js +70 -11
- package/build/src/git/ref-migration.d.ts +22 -0
- package/build/src/git/ref-migration.js +55 -0
- package/build/src/git/repository.d.ts +10 -6
- package/build/src/git/repository.js +16 -8
- package/build/src/git/target-placement.d.ts +1 -0
- package/build/src/git/target-placement.js +5 -0
- package/build/src/git/tender.d.ts +1 -0
- package/build/src/git/terminal-reconcile.d.ts +1 -1
- package/build/src/git/terminal-reconcile.js +22 -20
- package/build/src/git/workspace.d.ts +14 -0
- package/build/src/git/workspace.js +44 -0
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +16 -16
- package/build/src/kanshi/report.d.ts +2 -2
- package/build/src/library/address.d.ts +9 -3
- package/build/src/library/address.js +3 -2
- package/build/src/library/akuma-creation.d.ts +4 -3
- package/build/src/library/akuma-creation.js +19 -13
- package/build/src/library/audit.d.ts +14 -6
- package/build/src/library/audit.js +13 -23
- package/build/src/library/catalog.d.ts +3 -1
- package/build/src/library/catalog.js +20 -6
- package/build/src/library/composition.d.ts +385 -0
- package/build/src/library/composition.js +28 -0
- package/build/src/library/configuration.js +8 -2
- package/build/src/library/continuation.js +66 -30
- package/build/src/library/contract-bind.js +10 -2
- package/build/src/library/contract-forwarding-reconciliation-result.d.ts +102 -0
- package/build/src/library/contract-forwarding-reconciliation-result.js +92 -0
- package/build/src/library/contract-forwarding-result.d.ts +4464 -0
- package/build/src/library/contract-forwarding-result.js +521 -0
- package/build/src/library/contract-forwarding.d.ts +71 -0
- package/build/src/library/contract-forwarding.js +114 -0
- package/build/src/library/contract-handle.d.ts +38 -0
- package/build/src/library/contract-handle.js +314 -0
- package/build/src/library/contract-operations.d.ts +214 -69
- package/build/src/library/contract-operations.js +189 -118
- package/build/src/library/contract-types.d.ts +7 -3
- package/build/src/library/contract.d.ts +21 -34
- package/build/src/library/contract.js +29 -287
- package/build/src/library/fleet-result.d.ts +1580 -0
- package/build/src/library/fleet-result.js +98 -0
- package/build/src/library/fleet.d.ts +112 -54
- package/build/src/library/fleet.js +211 -71
- package/build/src/library/input.d.ts +3 -1
- package/build/src/library/input.js +11 -1
- package/build/src/library/keiyaku.d.ts +388 -20
- package/build/src/library/keiyaku.js +13 -21
- package/build/src/library/mutation.d.ts +3 -3
- package/build/src/library/mutation.js +5 -9
- package/build/src/library/nuke.d.ts +1 -1
- package/build/src/library/nuke.js +4 -3
- package/build/src/library/reconcile.d.ts +4 -0
- package/build/src/library/reconcile.js +2 -0
- package/build/src/library/refusal.d.ts +0 -9
- package/build/src/library/refusal.js +0 -7
- package/build/src/protocol/amend.js +56 -50
- package/build/src/protocol/attempt.d.ts +2 -0
- package/build/src/protocol/attempt.js +8 -1
- package/build/src/protocol/completion.js +7 -0
- package/build/src/protocol/deliver.js +6 -2
- package/build/src/protocol/operations.d.ts +4 -1
- package/build/src/protocol/operations.js +5 -2
- package/build/src/protocol/placement.d.ts +1 -0
- package/build/src/protocol/placement.js +52 -38
- package/build/src/protocol/read/observation.d.ts +1 -4
- package/build/src/protocol/read/observation.js +2 -15
- package/build/src/protocol/reintegrate.js +62 -58
- package/build/src/protocol/review.js +5 -0
- package/build/src/protocol/run.js +17 -13
- package/build/src/runtime/proc/run.d.ts +9 -0
- package/build/src/runtime/proc/run.js +51 -4
- package/build/src/runtime/proc/termination.js +26 -22
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settlement/holder.d.ts +2 -1
- package/build/src/settlement/holder.js +15 -4
- package/build/src/settlement/settle.js +99 -33
- package/build/src/task/board.d.ts +68 -27
- package/build/src/task/board.js +31 -1
- package/build/src/task/catalog.d.ts +4 -0
- package/build/src/task/catalog.js +23 -0
- package/build/src/task/compose-language.js +33 -7
- package/build/src/task/compose-parser.d.ts +1 -1
- package/build/src/task/compose-parser.js +1 -1
- package/build/src/task/compose.js +2 -0
- package/build/src/task/index.d.ts +12 -4
- package/build/src/task/index.js +97 -16
- package/build/src/task/mutation-result.d.ts +923 -0
- package/build/src/task/mutation-result.js +140 -0
- package/build/src/task/mutation.d.ts +552 -28
- package/build/src/task/mutation.js +304 -97
- package/build/src/task/operations.d.ts +1 -4
- package/build/src/task/operations.js +0 -6
- package/build/src/task/public.d.ts +2 -0
- package/build/src/task/public.js +1 -0
- package/build/src/workspace-place.d.ts +7 -2
- package/build/src/workspace-place.js +34 -24
- package/build/src/world.d.ts +1 -0
- package/build/src/world.js +11 -0
- package/package.json +8 -6
- package/build/src/akuma/request-execution.d.ts +0 -8
- package/build/src/akuma/request-execution.js +0 -98
|
@@ -1,8 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { abbreviateGitIds, afterWording, candidateFact, dependentWording, displayGitId, gateFact, gitIdsInRow, mergeSummary, targetMovementFacts, } from "./contract-observation.js";
|
|
2
|
+
import { entityLines, elapsedMilliseconds, identityLine, plumbFacts, RECENT_TONE_MS, renderTextBlock, renderSectionBlock, safeText, tone, } from "./terminal.js";
|
|
3
|
+
import { akumaMark, endpointFact, formatAge, NARROW_COLUMNS, renderAkuma } from "./kanshi-akuma.js";
|
|
4
4
|
const PLUMB = " │ ";
|
|
5
5
|
const MAX_VISIBLE_ROWS = 10;
|
|
6
|
+
const REVIEW_ATTENTION_MS = 15 * 60 * 1_000;
|
|
7
|
+
const PENDING_ATTENTION_MS = 60 * 60 * 1_000;
|
|
8
|
+
function contractHasError(row) {
|
|
9
|
+
return (row.title === null ||
|
|
10
|
+
row.gates.reports.some((report) => report.current.kind === "attested" && report.current.verdict === "unsatisfied") ||
|
|
11
|
+
row.targetLag.kind === "unknown" ||
|
|
12
|
+
row.workspaceObservation.kind === "failed" ||
|
|
13
|
+
row.workspaceObservation.kind === "unavailable" ||
|
|
14
|
+
row.issue !== undefined);
|
|
15
|
+
}
|
|
16
|
+
function contractStatusTone(row, observedAt) {
|
|
17
|
+
if (contractHasError(row))
|
|
18
|
+
return "alert";
|
|
19
|
+
const phaseAge = elapsedMilliseconds(row.phaseAt, observedAt);
|
|
20
|
+
if (row.phase === "tendered" && phaseAge !== null && phaseAge >= REVIEW_ATTENTION_MS)
|
|
21
|
+
return "attention";
|
|
22
|
+
if ((row.phase === "waiting" || row.phase === "bound") && phaseAge !== null && phaseAge >= PENDING_ATTENTION_MS)
|
|
23
|
+
return "attention";
|
|
24
|
+
const journalAge = elapsedMilliseconds(row.lastJournalAt, observedAt);
|
|
25
|
+
return journalAge !== null && journalAge <= RECENT_TONE_MS ? "recent" : null;
|
|
26
|
+
}
|
|
6
27
|
function contractMark(row) {
|
|
7
28
|
if (row.phase === "claimed")
|
|
8
29
|
return "✓";
|
|
@@ -10,9 +31,8 @@ function contractMark(row) {
|
|
|
10
31
|
return "×";
|
|
11
32
|
if (row.title === null)
|
|
12
33
|
return "?";
|
|
13
|
-
if (row.gates.reports.some((report) => report.current.kind === "attested" && report.current.verdict === "unsatisfied"))
|
|
34
|
+
if (row.gates.reports.some((report) => report.current.kind === "attested" && report.current.verdict === "unsatisfied"))
|
|
14
35
|
return "!";
|
|
15
|
-
}
|
|
16
36
|
if (row.targetLag.kind === "unknown")
|
|
17
37
|
return "?";
|
|
18
38
|
if (row.phase === "waiting")
|
|
@@ -26,20 +46,7 @@ function taskMark(row) {
|
|
|
26
46
|
return "×";
|
|
27
47
|
if (row.disposition === "on_hold")
|
|
28
48
|
return "⧗";
|
|
29
|
-
|
|
30
|
-
return "●";
|
|
31
|
-
return row.disposition === "blocked" ? "‖" : "○";
|
|
32
|
-
}
|
|
33
|
-
function akumaMark(life) {
|
|
34
|
-
if (life === "running")
|
|
35
|
-
return "●";
|
|
36
|
-
if (life === "stillborn")
|
|
37
|
-
return "!";
|
|
38
|
-
if (life === "asleep")
|
|
39
|
-
return "○";
|
|
40
|
-
if (life === "killed")
|
|
41
|
-
return "×";
|
|
42
|
-
return "?";
|
|
49
|
+
return row.disposition === "in_progress" ? "●" : row.disposition === "blocked" ? "‖" : "○";
|
|
43
50
|
}
|
|
44
51
|
function gitAbbreviations(report) {
|
|
45
52
|
const ids = [];
|
|
@@ -47,32 +54,13 @@ function gitAbbreviations(report) {
|
|
|
47
54
|
return abbreviateGitIds(ids);
|
|
48
55
|
if (report.contracts.value.state !== null)
|
|
49
56
|
ids.push(report.contracts.value.state);
|
|
50
|
-
|
|
51
|
-
ids.push(...gitIdsInRow(row));
|
|
57
|
+
report.contracts.value.rows.forEach((row) => ids.push(...gitIdsInRow(row)));
|
|
52
58
|
return abbreviateGitIds(ids);
|
|
53
59
|
}
|
|
54
|
-
function formatAge(source, observedAt) {
|
|
55
|
-
if (source === null || source === undefined)
|
|
56
|
-
return "—";
|
|
57
|
-
const sourceMs = Date.parse(source);
|
|
58
|
-
const observedMs = Date.parse(observedAt);
|
|
59
|
-
if (sourceMs > observedMs)
|
|
60
|
-
return "future";
|
|
61
|
-
const seconds = Math.floor((observedMs - sourceMs) / 1_000);
|
|
62
|
-
if (seconds < 60)
|
|
63
|
-
return `${seconds}s`;
|
|
64
|
-
const minutes = Math.floor(seconds / 60);
|
|
65
|
-
if (minutes < 60)
|
|
66
|
-
return `${minutes}m`;
|
|
67
|
-
const hours = Math.floor(minutes / 60);
|
|
68
|
-
return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
|
|
69
|
-
}
|
|
70
60
|
function branchName(target) {
|
|
71
|
-
|
|
72
|
-
return null;
|
|
73
|
-
return target.startsWith("refs/heads/") ? target.slice("refs/heads/".length) : target;
|
|
61
|
+
return target === null ? null : target.startsWith("refs/heads/") ? target.slice("refs/heads/".length) : target;
|
|
74
62
|
}
|
|
75
|
-
function targetFacts(row) {
|
|
63
|
+
function targetFacts(row, abbreviations) {
|
|
76
64
|
const name = branchName(row.target);
|
|
77
65
|
if (name === null)
|
|
78
66
|
return ["no target"];
|
|
@@ -81,16 +69,13 @@ function targetFacts(row) {
|
|
|
81
69
|
facts.push(`commits behind ${name} unknown`);
|
|
82
70
|
if (row.targetLag.kind === "counted")
|
|
83
71
|
facts.push(`${row.targetLag.behind} commits behind ${name}`);
|
|
84
|
-
|
|
85
|
-
facts.push("target moved");
|
|
86
|
-
return facts;
|
|
72
|
+
return [...facts, ...targetMovementFacts(row, abbreviations)];
|
|
87
73
|
}
|
|
88
74
|
function selectedTargetFacts(row, abbreviations) {
|
|
75
|
+
const head = row.targetObservation?.head;
|
|
89
76
|
return [
|
|
90
|
-
...targetFacts(row),
|
|
91
|
-
...(row.target !== null &&
|
|
92
|
-
? [`target head ${displayGitId(row.targetObservation.head, abbreviations)}`]
|
|
93
|
-
: []),
|
|
77
|
+
...targetFacts(row, abbreviations),
|
|
78
|
+
...(row.target !== null && head ? [`target head ${displayGitId(head, abbreviations)}`] : []),
|
|
94
79
|
];
|
|
95
80
|
}
|
|
96
81
|
function workspaceState(row) {
|
|
@@ -103,12 +88,9 @@ function workspaceState(row) {
|
|
|
103
88
|
return "worktree unavailable";
|
|
104
89
|
if (observation.kind === "clean")
|
|
105
90
|
return "worktree clean";
|
|
106
|
-
const counts =
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
...(observation.counts.untracked > 0 ? [`untracked ${observation.counts.untracked}`] : []),
|
|
110
|
-
...(observation.counts.submodules > 0 ? [`submodules ${observation.counts.submodules}`] : []),
|
|
111
|
-
];
|
|
91
|
+
const counts = Object.entries(observation.counts)
|
|
92
|
+
.filter(([, count]) => count > 0)
|
|
93
|
+
.map(([name, count]) => `${name} ${count}`);
|
|
112
94
|
return counts.length === 0 ? "worktree dirty" : `worktree dirty · ${counts.join(" · ")}`;
|
|
113
95
|
}
|
|
114
96
|
function mergeFacts(row, selected, abbreviations) {
|
|
@@ -116,9 +98,8 @@ function mergeFacts(row, selected, abbreviations) {
|
|
|
116
98
|
const summary = mergeSummary(observation);
|
|
117
99
|
if (summary === undefined ||
|
|
118
100
|
(observation.kind !== "clean" && observation.kind !== "dirty") ||
|
|
119
|
-
observation.merge === null)
|
|
101
|
+
observation.merge === null)
|
|
120
102
|
return [];
|
|
121
|
-
}
|
|
122
103
|
if (!selected)
|
|
123
104
|
return [summary];
|
|
124
105
|
const paths = observation.merge.unmergedPaths;
|
|
@@ -128,80 +109,6 @@ function mergeFacts(row, selected, abbreviations) {
|
|
|
128
109
|
...(paths.length === 0 ? ["0 paths"] : paths),
|
|
129
110
|
];
|
|
130
111
|
}
|
|
131
|
-
function worldAfterFacts(row) {
|
|
132
|
-
return row.after.map(afterWording);
|
|
133
|
-
}
|
|
134
|
-
function activitySnapshotLine(row) {
|
|
135
|
-
const snapshot = row.snapshot;
|
|
136
|
-
if (snapshot === undefined)
|
|
137
|
-
return undefined;
|
|
138
|
-
const entries = snapshot.entries.flatMap((entry) => (entry.kind === "row" ? [entry.row] : []));
|
|
139
|
-
const latest = entries.at(-1);
|
|
140
|
-
if (latest === undefined) {
|
|
141
|
-
if (snapshot.kind === "idle" && snapshot.outcome !== undefined) {
|
|
142
|
-
return snapshot.outcome.outcome.kind === "answered"
|
|
143
|
-
? snapshot.outcome.outcome.answer
|
|
144
|
-
: snapshot.outcome.outcome.diagnostic;
|
|
145
|
-
}
|
|
146
|
-
return undefined;
|
|
147
|
-
}
|
|
148
|
-
if (latest.kind === "said" ||
|
|
149
|
-
latest.kind === "thought" ||
|
|
150
|
-
latest.kind === "note" ||
|
|
151
|
-
latest.kind === "call" ||
|
|
152
|
-
latest.kind === "tell") {
|
|
153
|
-
return latest.text;
|
|
154
|
-
}
|
|
155
|
-
if (latest.kind === "tool")
|
|
156
|
-
return latest.name;
|
|
157
|
-
return "activity";
|
|
158
|
-
}
|
|
159
|
-
function boundedActivity(value, columns, prefix) {
|
|
160
|
-
const budget = Math.max(1, columns - displayColumns(prefix));
|
|
161
|
-
return `activity "${truncateDisplayText(value, Math.max(1, budget - displayColumns('activity ""')))}"`;
|
|
162
|
-
}
|
|
163
|
-
function renderColdFleetLine(row, prefix, snapshot, columns) {
|
|
164
|
-
const mark = akumaMark(row.life);
|
|
165
|
-
const identity = identityLine(mark, row.id, prefix);
|
|
166
|
-
if (snapshot === undefined)
|
|
167
|
-
return [identity];
|
|
168
|
-
const activity = boundedActivity(snapshot, columns, PLUMB);
|
|
169
|
-
return [identity, ...plumbFacts([activity], columns)];
|
|
170
|
-
}
|
|
171
|
-
function plumbFacts(facts, columns) {
|
|
172
|
-
const clean = facts.map(safeText).filter((fact) => fact.length > 0);
|
|
173
|
-
if (clean.length === 0)
|
|
174
|
-
return [];
|
|
175
|
-
const lines = [];
|
|
176
|
-
let current = PLUMB;
|
|
177
|
-
for (const fact of clean) {
|
|
178
|
-
const candidate = current === PLUMB ? `${PLUMB}${fact}` : `${current} · ${fact}`;
|
|
179
|
-
if (current !== PLUMB && displayColumns(candidate) > columns) {
|
|
180
|
-
lines.push(current);
|
|
181
|
-
current = `${PLUMB}${fact}`;
|
|
182
|
-
}
|
|
183
|
-
else
|
|
184
|
-
current = candidate;
|
|
185
|
-
}
|
|
186
|
-
lines.push(current);
|
|
187
|
-
return lines;
|
|
188
|
-
}
|
|
189
|
-
function identityLine(mark, identity, extra = "") {
|
|
190
|
-
return extra.length === 0 ? `${mark} ${safeText(identity)}` : `${mark} ${safeText(identity)} ${safeText(extra)}`;
|
|
191
|
-
}
|
|
192
|
-
function failure(name, section, context) {
|
|
193
|
-
return [`[ ${name} ]`, "", `${tone(`! ${safeText(section.failure.message)}`, "alert", context.color)}`];
|
|
194
|
-
}
|
|
195
|
-
function sectionAbsent(name, _columns) {
|
|
196
|
-
return [`[ ${name} ]`, "", `${PLUMB}${name.toLowerCase()} absent`];
|
|
197
|
-
}
|
|
198
|
-
function endpointFact(id, observed) {
|
|
199
|
-
if (observed === "missing")
|
|
200
|
-
return `-> ${id} (missing)`;
|
|
201
|
-
if (observed === "unavailable")
|
|
202
|
-
return `-> ${id} (unavailable)`;
|
|
203
|
-
return `-> ${id}`;
|
|
204
|
-
}
|
|
205
112
|
function linkedTask(report, taskId) {
|
|
206
113
|
if (report.tasks.kind !== "present")
|
|
207
114
|
return `! ${taskId} · unavailable`;
|
|
@@ -219,11 +126,11 @@ function isTerminalAkuma(life) {
|
|
|
219
126
|
return life === "killed" || life === "stillborn";
|
|
220
127
|
}
|
|
221
128
|
function attachmentTimestamp(akuma) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
129
|
+
return "lifeAt" in akuma && akuma.lifeAt !== null
|
|
130
|
+
? akuma.lifeAt
|
|
131
|
+
: "lastActivityAt" in akuma
|
|
132
|
+
? akuma.lastActivityAt
|
|
133
|
+
: null;
|
|
227
134
|
}
|
|
228
135
|
function worldAttachments(row, report) {
|
|
229
136
|
if (report.akuma.kind !== "present")
|
|
@@ -265,16 +172,37 @@ function linkedFacts(row, report, mode) {
|
|
|
265
172
|
linked.push(linkedAkuma(report, attached.id, attached.aliases));
|
|
266
173
|
return linked;
|
|
267
174
|
}
|
|
175
|
+
function linkedAkumaSummary(row, report) {
|
|
176
|
+
if (row.fleet.length === 0)
|
|
177
|
+
return undefined;
|
|
178
|
+
if (report.akuma.kind !== "present")
|
|
179
|
+
return "akuma unavailable";
|
|
180
|
+
const byId = new Map(report.akuma.value.rows.map((akuma) => [akuma.id, akuma]));
|
|
181
|
+
const known = row.fleet
|
|
182
|
+
.map((attached) => byId.get(attached.id))
|
|
183
|
+
.filter((akuma) => akuma !== undefined);
|
|
184
|
+
if (known.length === 0)
|
|
185
|
+
return `akuma ${row.fleet.length} missing`;
|
|
186
|
+
const live = known.filter((akuma) => !isTerminalAkuma(akuma.life)).length;
|
|
187
|
+
const terminal = known.length - live;
|
|
188
|
+
const facts = [`akuma ${row.fleet.length}`];
|
|
189
|
+
if (live > 0)
|
|
190
|
+
facts.push(`${live} live`);
|
|
191
|
+
if (terminal > 0)
|
|
192
|
+
facts.push(`${terminal} terminal`);
|
|
193
|
+
return facts.join(" · ");
|
|
194
|
+
}
|
|
268
195
|
function semanticBlock(name, facts, context) {
|
|
196
|
+
if (facts.length === 0)
|
|
197
|
+
return [];
|
|
269
198
|
const lines = [` ${name}`];
|
|
270
|
-
const
|
|
271
|
-
for (const fact of values)
|
|
199
|
+
for (const fact of facts)
|
|
272
200
|
lines.push(...renderTextBlock(safeText(fact), " ", context.columns));
|
|
273
201
|
return lines;
|
|
274
202
|
}
|
|
275
203
|
function namespaceTaskFacts(row) {
|
|
276
204
|
if (row.namespaceTasks.kind === "absent")
|
|
277
|
-
return [
|
|
205
|
+
return [];
|
|
278
206
|
if (row.namespaceTasks.kind === "failed") {
|
|
279
207
|
return [`failed ${row.namespaceTasks.failure.message}`];
|
|
280
208
|
}
|
|
@@ -282,10 +210,18 @@ function namespaceTaskFacts(row) {
|
|
|
282
210
|
}
|
|
283
211
|
function renderSelectedContractRow(row, report, context, abbreviations) {
|
|
284
212
|
const title = row.title ?? "title unavailable";
|
|
213
|
+
const statusTone = contractStatusTone(row, report.observedAt);
|
|
285
214
|
const lines = [
|
|
286
|
-
|
|
215
|
+
...entityLines({
|
|
216
|
+
mark: statusTone === null ? contractMark(row) : tone(contractMark(row), statusTone, context.color),
|
|
217
|
+
identity: row.id,
|
|
218
|
+
state: `${row.phase} · ${formatAge(row.phaseAt, report.observedAt)}`,
|
|
219
|
+
title,
|
|
220
|
+
facts: [],
|
|
221
|
+
context,
|
|
222
|
+
}),
|
|
287
223
|
];
|
|
288
|
-
lines.push(...semanticBlock("after",
|
|
224
|
+
lines.push(...semanticBlock("after", row.after.map(afterWording), context));
|
|
289
225
|
lines.push(...semanticBlock("dependents", row.dependents.map(dependentWording), context));
|
|
290
226
|
const gateFacts = row.gates.reports.flatMap((gate) => [
|
|
291
227
|
`${gateFact(gate)} ${formatAge(gate.current.kind === "attested" ? gate.current.at : null, report.observedAt)}`,
|
|
@@ -304,10 +240,8 @@ function renderSelectedContractRow(row, report, context, abbreviations) {
|
|
|
304
240
|
}
|
|
305
241
|
lines.push(...semanticBlock("workspace/merge", [...workspaceFacts, ...mergeFacts(row, true, abbreviations)], context));
|
|
306
242
|
const attachments = [...linkedFacts(row, report, "selected")];
|
|
307
|
-
if (row.issue !== undefined)
|
|
308
|
-
|
|
309
|
-
attachments.push(`lag (observed now): ${detail}`);
|
|
310
|
-
}
|
|
243
|
+
if (row.issue !== undefined)
|
|
244
|
+
attachments.push(`lag (observed now): target-checkout-retained ${row.issue.target}`);
|
|
311
245
|
lines.push(...semanticBlock("attachments", attachments, context));
|
|
312
246
|
lines.push(...semanticBlock("namespace tasks", namespaceTaskFacts(row), context));
|
|
313
247
|
return lines;
|
|
@@ -331,19 +265,27 @@ function isTerminalTask(row) {
|
|
|
331
265
|
}
|
|
332
266
|
function renderWorldContractRow(row, report, context) {
|
|
333
267
|
const title = row.title ?? "title unavailable";
|
|
334
|
-
const
|
|
268
|
+
const contractFacts = [
|
|
335
269
|
candidateFact(row.delivery),
|
|
336
|
-
...targetFacts(row),
|
|
337
|
-
...
|
|
270
|
+
...targetFacts(row, gitAbbreviations(report)),
|
|
271
|
+
...row.after.map(afterWording),
|
|
338
272
|
...(row.dependents.length === 0 ? [] : [`dependents ${row.dependents.map(dependentWording).join(" · ")}`]),
|
|
339
273
|
...row.gates.reports.map(gateFact),
|
|
340
|
-
...linkedFacts(row, report, "world"),
|
|
341
274
|
];
|
|
342
|
-
const
|
|
343
|
-
|
|
275
|
+
const linkedFacts = [
|
|
276
|
+
...(row.holder.kind === "held" ? [linkedTask(report, row.holder.taskId)] : []),
|
|
277
|
+
...(row.holder.kind === "unavailable" ? ["! task · unavailable"] : []),
|
|
278
|
+
...(linkedAkumaSummary(row, report) === undefined ? [] : [linkedAkumaSummary(row, report)]),
|
|
344
279
|
];
|
|
345
|
-
|
|
346
|
-
return
|
|
280
|
+
const statusTone = contractStatusTone(row, report.observedAt);
|
|
281
|
+
return entityLines({
|
|
282
|
+
mark: statusTone === null ? contractMark(row) : tone(contractMark(row), statusTone, context.color),
|
|
283
|
+
identity: row.id,
|
|
284
|
+
state: `${row.phase} · ${formatAge(row.lastJournalAt, report.observedAt)}`,
|
|
285
|
+
title,
|
|
286
|
+
facts: contractFacts,
|
|
287
|
+
context,
|
|
288
|
+
}).concat(plumbFacts(linkedFacts, context.columns));
|
|
347
289
|
}
|
|
348
290
|
function selectRecentRows(rows, timestamp) {
|
|
349
291
|
return [...rows]
|
|
@@ -356,35 +298,24 @@ function selectRecentRows(rows, timestamp) {
|
|
|
356
298
|
})
|
|
357
299
|
.slice(0, MAX_VISIBLE_ROWS);
|
|
358
300
|
}
|
|
359
|
-
function sectionFooter({ visible, total, unit, selector, neutral, }) {
|
|
360
|
-
if (visible === total)
|
|
361
|
-
return [` (all ${total}${neutral ? "" : " live"} ${unit} shown)`];
|
|
362
|
-
return [` + ${total - visible} more${neutral ? "" : " live"} ${unit} not shown`, ` keiyaku ls ${selector}/`];
|
|
363
|
-
}
|
|
364
|
-
function sectionBlock({ name, unit, selector, rows, total, neutral = false, }) {
|
|
365
|
-
const lines = [`[ ${name} ] ${total}${neutral ? ` ${unit}` : " live"}`, "", ...rows.flat()];
|
|
366
|
-
lines.push("", ...sectionFooter({ visible: rows.length, total, unit, selector, neutral }));
|
|
367
|
-
return lines;
|
|
368
|
-
}
|
|
369
301
|
function renderContracts(report, context) {
|
|
370
302
|
const section = report.contracts;
|
|
371
303
|
if (section.kind === "absent")
|
|
372
|
-
return
|
|
304
|
+
return ["CONTRACTS // absent", "", `${PLUMB}contracts absent`];
|
|
373
305
|
if (section.kind === "failed")
|
|
374
|
-
return
|
|
306
|
+
return ["CONTRACTS // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
375
307
|
const live = section.value.rows.filter((row) => !isTerminalContract(row));
|
|
376
308
|
const rows = selectRecentRows(live, (row) => row.lastJournalAt);
|
|
377
|
-
const abbreviations = gitAbbreviations(report);
|
|
378
309
|
const candidates = live.filter((row) => row.delivery !== null).length;
|
|
379
|
-
const rendered =
|
|
380
|
-
name: "
|
|
310
|
+
const rendered = renderSectionBlock({
|
|
311
|
+
name: "CONTRACTS",
|
|
381
312
|
unit: "keiyaku",
|
|
382
313
|
selector: "kei",
|
|
383
314
|
rows: rows.map((row) => renderWorldContractRow(row, report, context)),
|
|
384
315
|
total: live.length,
|
|
385
316
|
});
|
|
386
|
-
const header = `
|
|
387
|
-
return [header,
|
|
317
|
+
const header = `CONTRACTS // ${live.length} live · ${candidates} candidates`;
|
|
318
|
+
return [header, ...rendered.slice(1)];
|
|
388
319
|
}
|
|
389
320
|
function renderSelectedContract(report, context) {
|
|
390
321
|
const section = report.contracts;
|
|
@@ -400,65 +331,52 @@ function renderSelectedContract(report, context) {
|
|
|
400
331
|
function renderTasks(report, context) {
|
|
401
332
|
const section = report.tasks;
|
|
402
333
|
if (section.kind === "absent")
|
|
403
|
-
return
|
|
334
|
+
return ["TASKS // absent", "", `${PLUMB}tasks absent`];
|
|
404
335
|
if (section.kind === "failed")
|
|
405
|
-
return
|
|
336
|
+
return ["TASKS // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
406
337
|
const live = section.value.rows.filter((row) => !isTerminalTask(row));
|
|
407
338
|
const rows = selectRecentRows(live, (row) => row.updatedAt);
|
|
408
339
|
const rowLines = rows.map((row) => {
|
|
409
340
|
const relation = row.contract === undefined ? ["unbound"] : [endpointFact(row.contract.id, row.contract.observed)];
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (section.kind === "failed")
|
|
427
|
-
return failure("FLEET", section, context);
|
|
428
|
-
const rows = visibleFleetRows(section.value.rows);
|
|
429
|
-
const rowLines = rows.map((row) => {
|
|
430
|
-
const lifeAt = "lifeAt" in row ? row.lifeAt : null;
|
|
431
|
-
const life = `${row.life} · ${formatAge(lifeAt, report.observedAt)}`;
|
|
432
|
-
const activity = "lastActivityAt" in row && row.lastActivityAt !== null
|
|
433
|
-
? [`activity ${formatAge(row.lastActivityAt, report.observedAt)}`]
|
|
434
|
-
: [];
|
|
435
|
-
const key = row.life === "stranded" && "strandedReason" in row && row.strandedReason === "resume-unsupported"
|
|
436
|
-
? [life, ...activity, "resume unsupported"]
|
|
437
|
-
: [life, ...activity];
|
|
438
|
-
const relation = row.contract === undefined ? ["unbound"] : [endpointFact(row.contract.id, row.contract.observed)];
|
|
439
|
-
const snapshot = activitySnapshotLine(row);
|
|
440
|
-
const prefix = `${akumaLabel(row)} · ${[...key, ...relation].join(" · ")}`.trim();
|
|
441
|
-
return renderColdFleetLine(row, prefix, snapshot, context.columns);
|
|
442
|
-
});
|
|
443
|
-
return sectionBlock({
|
|
444
|
-
name: "FLEET",
|
|
445
|
-
unit: "akuma",
|
|
446
|
-
selector: "aku",
|
|
447
|
-
rows: rowLines,
|
|
448
|
-
total: section.value.rows.length,
|
|
449
|
-
neutral: true,
|
|
341
|
+
const childFacts = row.children === undefined ? [] : [`children ${row.children.live} live · ${row.children.total} total`];
|
|
342
|
+
const blockerFacts = (row.blockers ?? []).map((blocker) => `blocked ${blocker.id}`);
|
|
343
|
+
if (context.columns > NARROW_COLUMNS) {
|
|
344
|
+
return [
|
|
345
|
+
identityLine(taskMark(row), row.id, `· ${row.disposition} · P${row.priority} · ${row.title} · ${relation.join(" · ")}`),
|
|
346
|
+
...plumbFacts([...childFacts, ...blockerFacts], context.columns),
|
|
347
|
+
];
|
|
348
|
+
}
|
|
349
|
+
return entityLines({
|
|
350
|
+
mark: taskMark(row),
|
|
351
|
+
identity: row.id,
|
|
352
|
+
state: `${row.disposition} · P${row.priority}`,
|
|
353
|
+
title: row.title,
|
|
354
|
+
facts: [...relation, ...childFacts, ...blockerFacts],
|
|
355
|
+
context,
|
|
356
|
+
});
|
|
450
357
|
});
|
|
358
|
+
return [
|
|
359
|
+
`TASKS // ${live.length} live`,
|
|
360
|
+
...renderSectionBlock({
|
|
361
|
+
name: "TASKS",
|
|
362
|
+
unit: "task",
|
|
363
|
+
selector: "task",
|
|
364
|
+
continuation: "keiyaku task ls --world",
|
|
365
|
+
rows: rowLines,
|
|
366
|
+
total: live.length,
|
|
367
|
+
}).slice(1),
|
|
368
|
+
];
|
|
451
369
|
}
|
|
452
370
|
export function renderKanshiText(report, context = { columns: 80, color: false }, selection = "world") {
|
|
453
371
|
if (selection === "contract")
|
|
454
372
|
return renderSelectedContract(report, context).join("\n");
|
|
455
373
|
return [
|
|
456
|
-
|
|
374
|
+
`${tone("契", "alert", context.color)} KEIYAKU // WORLD`,
|
|
457
375
|
"",
|
|
376
|
+
...renderContracts(report, context),
|
|
458
377
|
"",
|
|
459
378
|
...renderAkuma(report, context),
|
|
460
379
|
"",
|
|
461
|
-
"",
|
|
462
380
|
...renderTasks(report, context),
|
|
463
381
|
].join("\n");
|
|
464
382
|
}
|
|
@@ -14,8 +14,7 @@ export declare function titleLines(mark: string, title: string, contract: string
|
|
|
14
14
|
export declare function hookFailureSummary(failure: HookFailure): string;
|
|
15
15
|
export declare function appendHookPayload(lines: string[], failure: HookFailure): void;
|
|
16
16
|
export declare function reuseLines(reuse: VerificationReuse | undefined, columns: number): readonly string[];
|
|
17
|
-
export declare function stopLines(
|
|
18
|
-
export declare function stopSummary(stop: VerificationStop | PlacementStop, addressed: string): readonly ReceiptSegment[];
|
|
17
|
+
export declare function stopLines(stop: VerificationStop | PlacementStop, columns: number, addressed: string, dependent?: string): readonly string[];
|
|
19
18
|
export declare function cleanupLines(cleanup: NonNullable<AcceptedDeliverResult["cleanup"]>, columns: number): readonly string[];
|
|
20
19
|
export declare function leakLines(leak: NonNullable<AcceptedDeliverResult["leak"]>, columns: number): readonly string[];
|
|
21
20
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { renderRefusalFacts } from "./refusal.js";
|
|
1
2
|
import { displayColumns, renderOpaqueBlock, safeText } from "./terminal.js";
|
|
2
3
|
export function receiptRow(lines, mark, label, segments, columns) {
|
|
3
4
|
let current = `${mark} ${label}`;
|
|
@@ -68,25 +69,96 @@ function prerequisiteRows(stop, columns) {
|
|
|
68
69
|
}
|
|
69
70
|
return lines;
|
|
70
71
|
}
|
|
72
|
+
function gateRows(stop, columns) {
|
|
73
|
+
if (!("refusal" in stop) || stop.refusal?.kind !== "gates-unsatisfied")
|
|
74
|
+
return [];
|
|
75
|
+
const lines = [];
|
|
76
|
+
for (const report of stop.refusal.unmet) {
|
|
77
|
+
const { gate, current } = report;
|
|
78
|
+
if (current.kind === "attested") {
|
|
79
|
+
receiptRow(lines, " ", "gate", [{ text: gate, opaque: true }, { text: "·" }, { text: current.verdict }, { text: `· at=${current.at}` }], columns);
|
|
80
|
+
if (current.summary !== undefined)
|
|
81
|
+
receiptPayload(lines, ` summary ${gate}`, current.summary);
|
|
82
|
+
}
|
|
83
|
+
else if (current.kind === "stale") {
|
|
84
|
+
receiptRow(lines, " ", "gate", [{ text: gate, opaque: true }, { text: "· stale" }, { text: `· prior=${current.priorVerdict}` }], columns);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
receiptRow(lines, " ", "gate", [{ text: gate, opaque: true }, { text: "· missing" }], columns);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return lines;
|
|
91
|
+
}
|
|
71
92
|
function targetMovedDetail(stop) {
|
|
72
93
|
if ("integratedAt" in stop) {
|
|
73
94
|
return [
|
|
74
95
|
{ text: stop.target, opaque: true },
|
|
75
96
|
{ text: `${stop.integratedAt} -> ${stop.observed}`, opaque: true },
|
|
76
97
|
{ text: `attempts=${stop.attempts}` },
|
|
98
|
+
...(stop.observedTreeEqualsCandidate ? [{ text: "content=identical" }] : []),
|
|
77
99
|
];
|
|
78
100
|
}
|
|
79
101
|
return [
|
|
80
102
|
{ text: stop.target, opaque: true },
|
|
81
103
|
{ text: `${stop.expected} -> ${stop.observed}`, opaque: true },
|
|
104
|
+
...(stop.observedTreeEqualsCandidate ? [{ text: "content=identical" }] : []),
|
|
82
105
|
];
|
|
83
106
|
}
|
|
84
|
-
|
|
85
|
-
|
|
107
|
+
function directStopName(stop) {
|
|
108
|
+
if ("refusal" in stop && stop.refusal !== undefined)
|
|
109
|
+
return stop.refusal.kind.replaceAll("-", " ");
|
|
110
|
+
if ("retry" in stop && stop.retry !== undefined)
|
|
111
|
+
return stop.retry.kind.replaceAll("-", " ");
|
|
112
|
+
return stop.failure.replaceAll("-", " ");
|
|
113
|
+
}
|
|
114
|
+
function refusalEvidence(stop, columns) {
|
|
86
115
|
const lines = [];
|
|
87
|
-
const state = label === "verification" ? "failed" : "blocked";
|
|
88
|
-
receiptRow(lines, "!", label, [{ text: state }, { text: "·" }, ...detail], columns);
|
|
89
116
|
lines.push(...prerequisiteRows(stop, columns));
|
|
117
|
+
lines.push(...gateRows(stop, columns));
|
|
118
|
+
if (!("refusal" in stop) || stop.refusal === undefined)
|
|
119
|
+
return lines;
|
|
120
|
+
const refusal = stop.refusal;
|
|
121
|
+
if (refusal.kind === "integration-failed") {
|
|
122
|
+
receiptRow(lines, " ", "reason", [{ text: refusal.reason }], columns);
|
|
123
|
+
receiptRow(lines, " ", "target", [{ text: refusal.targetHead, opaque: true }], columns);
|
|
124
|
+
if ("conflictPaths" in refusal) {
|
|
125
|
+
for (const path of refusal.conflictPaths)
|
|
126
|
+
receiptRow(lines, " ", "conflict", [{ text: path, opaque: true }], columns);
|
|
127
|
+
}
|
|
128
|
+
const recovery = "recovery" in refusal ? refusal.recovery : undefined;
|
|
129
|
+
if (typeof recovery === "object" &&
|
|
130
|
+
recovery !== null &&
|
|
131
|
+
"materialize" in recovery &&
|
|
132
|
+
typeof recovery.materialize === "string" &&
|
|
133
|
+
"continue" in recovery &&
|
|
134
|
+
typeof recovery.continue === "string") {
|
|
135
|
+
receiptRow(lines, " ", "recovery materialize conflicts", [{ text: recovery.materialize }], columns);
|
|
136
|
+
receiptRow(lines, " ", "recovery continue after resolve", [{ text: recovery.continue }], columns);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else if (refusal.kind === "integration-unsupported") {
|
|
140
|
+
receiptRow(lines, " ", "required Git", [{ text: refusal.requiredGit }], columns);
|
|
141
|
+
}
|
|
142
|
+
return lines;
|
|
143
|
+
}
|
|
144
|
+
export function stopLines(stop, columns, addressed, dependent) {
|
|
145
|
+
if ("refusal" in stop && stop.refusal?.kind === "checkout-not-followable") {
|
|
146
|
+
const checkout = renderRefusalFacts(stop.refusal, "", columns, addressed);
|
|
147
|
+
if (dependent === undefined)
|
|
148
|
+
return checkout;
|
|
149
|
+
const lines = [];
|
|
150
|
+
receiptRow(lines, "!", "continuation", [{ text: dependent, opaque: true }], columns);
|
|
151
|
+
return [...lines, ...checkout];
|
|
152
|
+
}
|
|
153
|
+
const lines = [];
|
|
154
|
+
const segments = dependent === undefined ? [] : [{ text: "·" }, { text: directStopName(stop) }];
|
|
155
|
+
if ("failure" in stop && stop.failure === "target-moved")
|
|
156
|
+
segments.push(...targetMovedDetail(stop));
|
|
157
|
+
if ("failure" in stop && stop.failure === "environment-failure" && "command" in stop) {
|
|
158
|
+
segments.push({ text: `command=${stop.command}` }, { text: hookFailureSummary(stop.detail), opaque: true });
|
|
159
|
+
}
|
|
160
|
+
receiptRow(lines, "!", dependent === undefined ? directStopName(stop) : dependent, segments, columns);
|
|
161
|
+
lines.push(...refusalEvidence(stop, columns));
|
|
90
162
|
if ("failure" in stop && stop.failure === "environment-failure" && "command" in stop) {
|
|
91
163
|
appendHookPayload(lines, stop.detail);
|
|
92
164
|
}
|
|
@@ -98,28 +170,6 @@ export function stopLines(label, stop, columns, addressed) {
|
|
|
98
170
|
}
|
|
99
171
|
return lines;
|
|
100
172
|
}
|
|
101
|
-
export function stopSummary(stop, addressed) {
|
|
102
|
-
const detail = [];
|
|
103
|
-
if ("refusal" in stop && stop.refusal !== undefined) {
|
|
104
|
-
detail.push({ text: stop.refusal.kind });
|
|
105
|
-
if ("contractId" in stop.refusal && stop.refusal.contractId !== addressed) {
|
|
106
|
-
detail.push({ text: `contract=${stop.refusal.contractId}`, opaque: true });
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
else if ("retry" in stop && stop.retry !== undefined) {
|
|
110
|
-
detail.push({ text: stop.retry.kind });
|
|
111
|
-
}
|
|
112
|
-
else if ("failure" in stop) {
|
|
113
|
-
detail.push({ text: stop.failure });
|
|
114
|
-
if (stop.failure === "environment-failure" && "command" in stop) {
|
|
115
|
-
detail.push({ text: `command=${stop.command}` }, { text: hookFailureSummary(stop.detail), opaque: true });
|
|
116
|
-
}
|
|
117
|
-
else if (stop.failure === "target-moved") {
|
|
118
|
-
detail.push(...targetMovedDetail(stop));
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return detail;
|
|
122
|
-
}
|
|
123
173
|
export function cleanupLines(cleanup, columns) {
|
|
124
174
|
const lines = [];
|
|
125
175
|
receiptRow(lines, "!", "cleanup", [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { displayColumns, gitShortStat, renderOpaqueBlock, safeText } from "./terminal.js";
|
|
1
|
+
import { checkoutNotFollowableLines, displayColumns, gitShortStat, renderOpaqueBlock, safeText, } from "./terminal.js";
|
|
2
2
|
function isRecord(value) {
|
|
3
3
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
4
|
}
|
|
@@ -78,15 +78,7 @@ export function renderRefusalFacts(refusal, indent, columns, addressed) {
|
|
|
78
78
|
return renderOpaqueBlock(refusalHead(refusal.kind, identity, [`requiredGit=${refusal.requiredGit}`]), indent, columns);
|
|
79
79
|
}
|
|
80
80
|
if (refusal.kind === "checkout-not-followable") {
|
|
81
|
-
|
|
82
|
-
...renderOpaqueBlock(refusalHead(refusal.kind, identity, [
|
|
83
|
-
`target=${refusal.target}`,
|
|
84
|
-
`path=${refusal.path}`,
|
|
85
|
-
`reason=${refusal.reason}`,
|
|
86
|
-
]), indent, columns),
|
|
87
|
-
];
|
|
88
|
-
lines.push(...collectionLines("paths", refusal.paths, indent, columns));
|
|
89
|
-
return lines;
|
|
81
|
+
return checkoutNotFollowableLines(refusal);
|
|
90
82
|
}
|
|
91
83
|
return renderOpaqueBlock(refusalHead(refusal.kind, identity, []), indent, columns);
|
|
92
84
|
}
|