@astrosheep/keiyaku 4.6.8 → 4.6.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 +40 -14
- package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/opencode/index.js +1 -1
- package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/skills/keiyaku/SKILL.md +5 -6
- package/build/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/src/akuma/akuma-instance.d.ts +2 -0
- package/build/src/akuma/akuma-instance.js +10 -0
- package/build/src/akuma/akuma-observe.d.ts +33 -8
- package/build/src/akuma/akuma-observe.js +88 -64
- package/build/src/akuma/akuma-owner.d.ts +11 -2
- package/build/src/akuma/akuma-owner.js +45 -35
- package/build/src/akuma/akuma-selection-execution.js +9 -1
- package/build/src/akuma/akuma-stream.d.ts +22 -0
- package/build/src/akuma/akuma-stream.js +116 -0
- package/build/src/akuma/akuma-wait.d.ts +1 -40
- package/build/src/akuma/akuma-wait.js +23 -84
- package/build/src/akuma/akuma.d.ts +17 -11
- package/build/src/akuma/akuma.js +2 -0
- package/build/src/akuma/allowed.d.ts +7 -12
- package/build/src/akuma/allowed.js +13 -4
- package/build/src/akuma/body-supervisor.d.ts +5 -5
- package/build/src/akuma/body-supervisor.js +22 -20
- package/build/src/akuma/body.js +28 -1
- package/build/src/akuma/call-request.d.ts +12 -22
- package/build/src/akuma/heart/activity-schema.d.ts +12 -0
- package/build/src/akuma/heart/activity-schema.js +6 -0
- package/build/src/akuma/heart/index.d.ts +59 -2
- package/build/src/akuma/heart/index.js +87 -8
- package/build/src/akuma/heart/rows.js +5 -3
- package/build/src/akuma/heart/soul.d.ts +9 -0
- package/build/src/akuma/heart/soul.js +29 -0
- package/build/src/akuma/heart/storage.d.ts +15 -0
- package/build/src/akuma/heart/storage.js +55 -0
- package/build/src/akuma/heart/timeline.d.ts +7 -0
- package/build/src/akuma/heart/timeline.js +10 -0
- package/build/src/akuma/index.d.ts +1 -0
- package/build/src/akuma/projection.d.ts +25 -0
- package/build/src/akuma/projection.js +24 -7
- package/build/src/akuma/provider-recipe.d.ts +11 -0
- package/build/src/akuma/provider-recipe.js +23 -0
- package/build/src/akuma/provider.d.ts +25 -0
- package/build/src/akuma/provider.js +99 -7
- package/build/src/akuma/providers/acp/events.js +25 -2
- package/build/src/akuma/providers/claude/events.js +76 -10
- package/build/src/akuma/providers/claude/index.js +2 -5
- package/build/src/akuma/providers/codex-app-server/events.js +17 -2
- package/build/src/akuma/providers/codex-app-server/index.js +15 -9
- package/build/src/akuma/providers/decode.d.ts +8 -0
- package/build/src/akuma/providers/decode.js +21 -0
- package/build/src/akuma/providers/grok-build/index.js +10 -26
- package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
- package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
- package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
- package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
- package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
- package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
- package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
- package/build/src/akuma/providers/paseo/events.d.ts +8 -0
- package/build/src/akuma/providers/paseo/events.js +58 -11
- package/build/src/akuma/providers/paseo/index.js +11 -7
- package/build/src/akuma/providers/pi/events.d.ts +2 -0
- package/build/src/akuma/providers/pi/events.js +32 -24
- package/build/src/akuma/providers/pi/index.js +21 -35
- package/build/src/akuma/request-lifecycle.d.ts +1 -2
- package/build/src/akuma/request-lifecycle.js +2 -8
- package/build/src/akuma/request-rendezvous.js +38 -55
- package/build/src/akuma/request-serve.d.ts +1 -1
- package/build/src/akuma/request-serve.js +77 -113
- package/build/src/akuma/selection-observation.d.ts +57 -51
- package/build/src/akuma/selection-observation.js +3 -3
- package/build/src/akuma/turn-drive.d.ts +3 -0
- package/build/src/akuma/turn-drive.js +26 -5
- package/build/src/akuma-body.js +12 -22
- package/build/src/cli/akuma-caller.js +10 -0
- package/build/src/cli/commands/akuma-grammar.js +3 -4
- package/build/src/cli/commands/akuma.js +13 -51
- package/build/src/cli/commands/contract-grammar.d.ts +7 -6
- package/build/src/cli/commands/contract-grammar.js +27 -32
- package/build/src/cli/commands/contract-help.d.ts +16 -7
- package/build/src/cli/commands/contract-help.js +20 -11
- package/build/src/cli/commands/contract.js +11 -11
- package/build/src/cli/commands/debt-grammar.d.ts +19 -0
- package/build/src/cli/commands/debt-grammar.js +323 -0
- package/build/src/cli/commands/debt-query.d.ts +5 -0
- package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
- package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
- package/build/src/cli/commands/{task.js → debt.js} +83 -143
- package/build/src/cli/coordinates.d.ts +1 -1
- package/build/src/cli/coordinates.js +1 -1
- package/build/src/cli/parse.d.ts +4 -4
- package/build/src/cli/parse.js +17 -16
- package/build/src/cli/render/akuma-activity.d.ts +11 -83
- package/build/src/cli/render/akuma-activity.js +20 -382
- package/build/src/cli/render/catalog.d.ts +2 -2
- package/build/src/cli/render/catalog.js +5 -5
- package/build/src/cli/render/contract.js +2 -2
- package/build/src/cli/render/debt.d.ts +28 -0
- package/build/src/cli/render/{task.js → debt.js} +51 -112
- package/build/src/cli/render/kanshi.js +28 -28
- package/build/src/cli/render/marks.d.ts +5 -5
- package/build/src/cli/render/marks.js +4 -10
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/runtime.js +3 -3
- package/build/src/cli/scan.d.ts +1 -1
- package/build/src/cli/usage.d.ts +1 -1
- package/build/src/cli/usage.js +4 -4
- package/build/src/contract-worktree.js +3 -3
- package/build/src/debt/board.d.ts +160 -0
- package/build/src/{task → debt}/board.js +89 -89
- package/build/src/debt/catalog.d.ts +11 -0
- package/build/src/debt/catalog.js +59 -0
- package/build/src/{task → debt}/context.d.ts +1 -1
- package/build/src/{task → debt}/context.js +1 -1
- package/build/src/{task → debt}/created-observation.d.ts +6 -10
- package/build/src/{task → debt}/created-observation.js +7 -7
- package/build/src/debt/document.d.ts +37 -0
- package/build/src/{task → debt}/document.js +37 -37
- package/build/src/debt/identity.d.ts +21 -0
- package/build/src/{task → debt}/identity.js +35 -35
- package/build/src/debt/index.d.ts +111 -0
- package/build/src/debt/index.js +203 -0
- package/build/src/{task → debt}/input.d.ts +8 -8
- package/build/src/{task → debt}/input.js +21 -21
- package/build/src/debt/lifecycle-operations.d.ts +6 -0
- package/build/src/{task → debt}/lifecycle-operations.js +27 -31
- package/build/src/debt/mutation-result.d.ts +981 -0
- package/build/src/debt/mutation-result.js +109 -0
- package/build/src/debt/mutation.d.ts +424 -0
- package/build/src/debt/mutation.js +223 -0
- package/build/src/debt/operation-types.d.ts +71 -0
- package/build/src/debt/operations.d.ts +28 -0
- package/build/src/{task → debt}/operations.js +59 -60
- package/build/src/debt/query.d.ts +76 -0
- package/build/src/{task → debt}/query.js +55 -55
- package/build/src/{task → debt}/store.d.ts +13 -13
- package/build/src/{task → debt}/store.js +58 -49
- package/build/src/debt/view.d.ts +4 -0
- package/build/src/debt/view.js +7 -0
- package/build/src/identity/coordinates.d.ts +1 -1
- package/build/src/index.d.ts +13 -13
- package/build/src/index.js +9 -9
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +33 -33
- package/build/src/kanshi/report.d.ts +7 -7
- package/build/src/kanshi/select.js +4 -4
- package/build/src/library/akumas.d.ts +2 -3
- package/build/src/library/bind.d.ts +3 -3
- package/build/src/library/bind.js +5 -5
- package/build/src/library/contract-creation.js +5 -5
- package/build/src/library/contract-execution.js +4 -4
- package/build/src/library/contract-types.d.ts +2 -2
- package/build/src/library/input.d.ts +2 -2
- package/build/src/library/input.js +5 -5
- package/build/src/library/invocation.js +2 -2
- package/build/src/library/nuke.js +3 -3
- package/build/src/library/outcome.d.ts +126 -126
- package/build/src/library/outcome.js +3 -3
- package/build/src/library/selection.d.ts +1 -4
- package/build/src/library/selection.js +11 -62
- package/build/src/plugin/public.d.ts +5 -0
- package/build/src/plugin/runtime.js +3 -1
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settlement/fence.d.ts +3 -3
- package/build/src/settlement/fence.js +4 -4
- package/build/src/settlement/holder.d.ts +16 -16
- package/build/src/settlement/holder.js +69 -63
- package/build/src/settlement/settle.d.ts +5 -5
- package/build/src/settlement/settle.js +53 -53
- package/package.json +12 -6
- package/plugins/paseo/plugin/index.server.ts +17 -0
- package/plugins/paseo/plugin/paseo-plugin.json +4 -0
- package/plugins/paseo/plugin/server/attach.ts +52 -0
- package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
- package/plugins/paseo/plugin/server/message.ts +60 -0
- package/plugins/paseo/plugin/server/mirror.ts +193 -0
- package/plugins/paseo/plugin/server/model.ts +14 -0
- package/plugins/paseo/plugin/server/provider.ts +276 -0
- package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
- package/plugins/paseo/plugin/server/sdk.ts +289 -0
- package/plugins/paseo/plugin/server/stop.ts +26 -0
- package/plugins/paseo/plugin/server/transport.ts +35 -0
- package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
- package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
- package/plugins/paseo/plugin/tsconfig.json +6 -0
- package/skills/keiyaku/SKILL.md +5 -6
- package/skills/keiyaku-akuma/SKILL.md +1 -1
- package/skills/keiyaku-akuma/references/automation.md +8 -8
- package/skills/keiyaku-babysit/SKILL.md +1 -1
- package/skills/keiyaku-bind/SKILL.md +9 -9
- package/skills/keiyaku-debt/SKILL.md +91 -0
- package/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
- package/build/skills/keiyaku-task/SKILL.md +0 -104
- package/build/src/cli/commands/task-grammar.d.ts +0 -19
- package/build/src/cli/commands/task-grammar.js +0 -384
- package/build/src/cli/commands/task-query.d.ts +0 -5
- package/build/src/cli/render/task.d.ts +0 -39
- package/build/src/task/board.d.ts +0 -168
- package/build/src/task/catalog.d.ts +0 -11
- package/build/src/task/catalog.js +0 -59
- package/build/src/task/compose-language.d.ts +0 -57
- package/build/src/task/compose-language.js +0 -364
- package/build/src/task/compose-parser.d.ts +0 -32
- package/build/src/task/compose-parser.js +0 -180
- package/build/src/task/compose.d.ts +0 -16
- package/build/src/task/compose.js +0 -189
- package/build/src/task/document.d.ts +0 -39
- package/build/src/task/identity.d.ts +0 -21
- package/build/src/task/index.d.ts +0 -138
- package/build/src/task/index.js +0 -269
- package/build/src/task/lifecycle-operations.d.ts +0 -6
- package/build/src/task/mutation-result.d.ts +0 -1726
- package/build/src/task/mutation-result.js +0 -198
- package/build/src/task/mutation.d.ts +0 -590
- package/build/src/task/mutation.js +0 -262
- package/build/src/task/operation-types.d.ts +0 -71
- package/build/src/task/operations.d.ts +0 -28
- package/build/src/task/query.d.ts +0 -76
- package/build/src/task/view.d.ts +0 -4
- package/build/src/task/view.js +0 -7
- package/skills/keiyaku-task/SKILL.md +0 -104
- /package/build/src/{task → debt}/operation-types.js +0 -0
|
@@ -2,9 +2,8 @@ import type { AkumaStatus } from "../../akuma/akuma.js";
|
|
|
2
2
|
import type { KillEvidence } from "../../akuma/heart/index.js";
|
|
3
3
|
import type { ActivityRow } from "../../akuma/projection.js";
|
|
4
4
|
import type { AkumaAskObservation, AkumaAskResult, AkumaTellResult, AkumaWaitResult } from "../../akuma/selection-observation.js";
|
|
5
|
-
import type { AkumaObservation,
|
|
5
|
+
import type { AkumaObservation, CreatedDebtObservation, DispatchAssociation } from "../../index.js";
|
|
6
6
|
import type { CallObservation, CallResult } from "../../library/akuma-creation.js";
|
|
7
|
-
import type { WaitObservedAkuma } from "../../library/akumas.js";
|
|
8
7
|
import type { AkumaHistoryResult } from "../../library/selection.js";
|
|
9
8
|
import { type TextRenderContext } from "./terminal.js";
|
|
10
9
|
export declare const DEFAULT_CONTEXT: TextRenderContext;
|
|
@@ -14,10 +13,6 @@ export declare const DEFAULT_CONTEXT: TextRenderContext;
|
|
|
14
13
|
*/
|
|
15
14
|
export declare function frameRule(headLines: readonly string[]): string;
|
|
16
15
|
type StatusTimeline = AkumaObservation["status"]["timeline"];
|
|
17
|
-
type StatusTimelineEntry = StatusTimeline["entries"][number];
|
|
18
|
-
type RenderRow = ActivityRow | Extract<StatusTimelineEntry, {
|
|
19
|
-
kind: "row";
|
|
20
|
-
}>["row"];
|
|
21
16
|
type RenderedSnapshot = StatusTimeline;
|
|
22
17
|
type RenderedActivity = Readonly<{
|
|
23
18
|
snapshot: RenderedSnapshot;
|
|
@@ -26,9 +21,7 @@ type RenderedActivity = Readonly<{
|
|
|
26
21
|
export declare function associatedIdentity(id: string, alias?: string, contract?: DispatchAssociation): string;
|
|
27
22
|
export declare function snapshotHeading(id: string, alias: string | undefined, contract: DispatchAssociation | undefined): readonly string[];
|
|
28
23
|
/**
|
|
29
|
-
* The one place row prefixes live: time,
|
|
30
|
-
* A plain layout is the single-target grammar; a source layout adds the frozen
|
|
31
|
-
* source column a plural wait aligns across its selected set.
|
|
24
|
+
* The one place row prefixes live: time, mark, verb, content.
|
|
32
25
|
*/
|
|
33
26
|
type RowLayout = Readonly<{
|
|
34
27
|
head: (time: string | undefined, glyph: string, verb: string, columns: number) => string;
|
|
@@ -36,14 +29,10 @@ type RowLayout = Readonly<{
|
|
|
36
29
|
marker: (count: number) => string;
|
|
37
30
|
history?: true;
|
|
38
31
|
compactRun?: true;
|
|
39
|
-
/**
|
|
32
|
+
/** A one-row receipt keeps that row on one line; speech can use its two-line budget. */
|
|
40
33
|
singleLine?: true;
|
|
41
34
|
/** World-board answer previews keep the conclusion at the tail. */
|
|
42
35
|
tailAnswer?: true;
|
|
43
|
-
/** A plural wait shares one minute clock across all of its attributed rows. */
|
|
44
|
-
clock?: {
|
|
45
|
-
previous?: string;
|
|
46
|
-
};
|
|
47
36
|
}>;
|
|
48
37
|
/**
|
|
49
38
|
* Shared snapshot activity rendering. Full snapshots render the selected
|
|
@@ -56,29 +45,12 @@ export declare function snapshotActivityLines(snapshot: RenderedSnapshot, contex
|
|
|
56
45
|
}>): readonly string[];
|
|
57
46
|
/** One command's append-only activity view, with a baseline and a final tail flush. */
|
|
58
47
|
export type ActivityStream = ((activity: RenderedActivity) => readonly string[]) & Readonly<{
|
|
59
|
-
/** Establish a
|
|
48
|
+
/** Establish a live baseline without spending the command's live tool budget. */
|
|
60
49
|
seed: (activity: RenderedActivity, alreadyRenderedSequence?: number) => readonly string[];
|
|
61
50
|
/** Current live rows for the redrawable frame; never part of append-only output. */
|
|
62
51
|
frame: () => readonly string[];
|
|
63
52
|
/** Emit the pending omission count and unsettled rows once before the command's conclusion. */
|
|
64
53
|
flush: () => readonly string[];
|
|
65
|
-
/** The same decisions undrawn, so concurrent streams can merge before rendering. */
|
|
66
|
-
emissions: Readonly<{
|
|
67
|
-
observe: (activity: RenderedActivity) => readonly StreamEmission[];
|
|
68
|
-
seed: (activity: RenderedActivity, alreadyRenderedSequence?: number) => readonly StreamEmission[];
|
|
69
|
-
flush: () => readonly StreamEmission[];
|
|
70
|
-
}>;
|
|
71
|
-
render: (emissions: readonly StreamEmission[]) => readonly string[];
|
|
72
|
-
}>;
|
|
73
|
-
/** One decided piece of append-only output: a settled row, or an untimed omission count. */
|
|
74
|
-
export type StreamEmission = Readonly<{
|
|
75
|
-
kind: "gap";
|
|
76
|
-
count: number;
|
|
77
|
-
}> | Readonly<{
|
|
78
|
-
kind: "row";
|
|
79
|
-
row: RenderRow;
|
|
80
|
-
inFlightSay?: boolean;
|
|
81
|
-
unsettled?: boolean;
|
|
82
54
|
}>;
|
|
83
55
|
/**
|
|
84
56
|
* Append-only live view over one command's successive settled snapshots.
|
|
@@ -87,54 +59,12 @@ export type StreamEmission = Readonly<{
|
|
|
87
59
|
* always print.
|
|
88
60
|
*/
|
|
89
61
|
export declare function activityStream(context: TextRenderContext, layout?: RowLayout): ActivityStream;
|
|
90
|
-
/** What a wait conclusion renders over: its observed and unobserved members. */
|
|
91
|
-
export type WaitConclusionResult = Readonly<{
|
|
92
|
-
reason: "completed" | "deadline";
|
|
93
|
-
observations: readonly AkumaObservation[];
|
|
94
|
-
unobserved: readonly Readonly<{
|
|
95
|
-
id: string;
|
|
96
|
-
diagnostic: string;
|
|
97
|
-
}>[];
|
|
98
|
-
}>;
|
|
99
|
-
/** One selected Akuma's frozen identity, resolved before the first observation round. */
|
|
100
|
-
export type WaitSelectedIdentity = Readonly<{
|
|
101
|
-
id: string;
|
|
102
|
-
alias?: string;
|
|
103
|
-
contract?: DispatchAssociation;
|
|
104
|
-
}>;
|
|
105
|
-
export type WaitObservationStream = Readonly<{
|
|
106
|
-
/** Freeze the selected set's identities so the source column is stable before the first row. */
|
|
107
|
-
select: (selected: readonly WaitSelectedIdentity[]) => void;
|
|
108
|
-
/** One observation round; returns the head frames and newly settled rows to print. */
|
|
109
|
-
observe: (observed: readonly WaitObservedAkuma[]) => readonly string[];
|
|
110
|
-
/** Current live rows from all selected streams; never part of append-only output. */
|
|
111
|
-
frame: () => readonly string[];
|
|
112
|
-
/** In-flight rows with their unresolved marks, emitted by a close that never concluded. */
|
|
113
|
-
flush: () => readonly string[];
|
|
114
|
-
/** The wait's closing scoreboard, or the empty string when there is nothing to print. */
|
|
115
|
-
conclude: (result: WaitConclusionResult) => string;
|
|
116
|
-
streamed: () => boolean;
|
|
117
|
-
}>;
|
|
118
62
|
export declare function inputWaitConclusion(observation: AkumaAskObservation, input: Readonly<{
|
|
119
63
|
startedAt: number;
|
|
120
64
|
completedAt?: string | null;
|
|
121
65
|
now?: number;
|
|
122
66
|
status?: AkumaStatus;
|
|
123
67
|
}>): readonly string[];
|
|
124
|
-
/**
|
|
125
|
-
* Live view over a wait's successive observation rounds, one append-only
|
|
126
|
-
* stream per selected Akuma. A plural wait opens one aggregate frame naming
|
|
127
|
-
* its selected set before any activity row and never opens a per-target frame
|
|
128
|
-
* during observation; a single-target wait opens that Akuma's own identity
|
|
129
|
-
* frame — the identity and Contract association the observed facts carry —
|
|
130
|
-
* and an already settled Akuma prints that frame while replaying no backlog
|
|
131
|
-
* rows. `conclude` renders the closing rows once the wait ends: one row per
|
|
132
|
-
* observed Akuma in `<clock> <mark> <verb> — <duration>` grammar, with a target
|
|
133
|
-
* named for a multi-target scoreboard and no activity replay.
|
|
134
|
-
*/
|
|
135
|
-
export declare function waitObservationStream(context: TextRenderContext, options?: Readonly<{
|
|
136
|
-
now?: () => number;
|
|
137
|
-
}>): WaitObservationStream;
|
|
138
68
|
/** The identity a streamed observing call's head frame renders from its resolved birth. */
|
|
139
69
|
export type ObservedCallHead = Readonly<{
|
|
140
70
|
id: string;
|
|
@@ -190,7 +120,7 @@ export declare function callObservationStream(context: TextRenderContext, head:
|
|
|
190
120
|
type SnapshotView = Readonly<{
|
|
191
121
|
status: AkumaObservation["status"];
|
|
192
122
|
contract: DispatchAssociation;
|
|
193
|
-
|
|
123
|
+
createdDebts?: CreatedDebtObservation;
|
|
194
124
|
}>;
|
|
195
125
|
type SnapshotCoreOptions = Readonly<{
|
|
196
126
|
alias?: string;
|
|
@@ -199,21 +129,19 @@ type SnapshotCoreOptions = Readonly<{
|
|
|
199
129
|
}>;
|
|
200
130
|
export declare function snapshotText(view: SnapshotView, context: TextRenderContext, options?: SnapshotCoreOptions): string;
|
|
201
131
|
export declare function killResultText(id: string, evidence: KillEvidence, alias?: string): string;
|
|
202
|
-
export declare function statusAnswer(view: Readonly<{
|
|
203
|
-
status: AkumaObservation["status"];
|
|
204
|
-
}>): string | undefined;
|
|
205
132
|
/** Presentation-only state for one akuma invocation; it never reaches JSON. */
|
|
206
133
|
type AkumaPresentation = Readonly<{
|
|
207
134
|
alias?: string;
|
|
208
|
-
streamed?: boolean;
|
|
209
|
-
structured?: boolean;
|
|
210
|
-
startedAt?: number;
|
|
211
|
-
selection?: readonly WaitSelectedIdentity[];
|
|
212
135
|
}>;
|
|
213
136
|
export declare function askRawAnswer(result: AkumaAskResult, structured: boolean | undefined): string | undefined;
|
|
214
137
|
export declare function callRawAnswer(result: CallResult, streamed: boolean): string | undefined;
|
|
215
|
-
export declare function waitRawAnswer(result: AkumaWaitResult, streamed: boolean): string | undefined;
|
|
216
138
|
export declare function historyRawAnswer(result: AkumaHistoryResult, historyId: string | undefined): string | undefined;
|
|
139
|
+
/**
|
|
140
|
+
* One wait's final text: each observed Akuma's own status snapshot, then one
|
|
141
|
+
* failure fact per member the wait could not read. A wait observes to its
|
|
142
|
+
* completion judgment and streams nothing, so an answer is visible only as the
|
|
143
|
+
* snapshot's own outcome row.
|
|
144
|
+
*/
|
|
217
145
|
export declare function waitText(result: AkumaWaitResult, presentation: AkumaPresentation, context: TextRenderContext): string;
|
|
218
146
|
export declare function historyText(result: AkumaHistoryResult, presentation: AkumaPresentation & Readonly<{
|
|
219
147
|
id?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defaultWaitComplete } from "../../akuma/akuma-observe.js";
|
|
2
2
|
import { renderDiffstat, toolContent, toolRepr } from "./akuma-tool.js";
|
|
3
|
-
import {
|
|
3
|
+
import { debtDispositionMark } from "./marks.js";
|
|
4
4
|
import { DEFAULT_CLI_COLUMNS, displayColumns, padToDisplay, renderBoundedPayload, renderBoundedTextBlock, safeText, takeDisplayColumns, takeDisplayColumnsFromEnd, truncateDisplayText, truncateMiddleDisplayText, } from "./terminal.js";
|
|
5
5
|
export const DEFAULT_CONTEXT = { columns: DEFAULT_CLI_COLUMNS, color: false };
|
|
6
6
|
const TIME_WIDTH = 5;
|
|
@@ -30,10 +30,6 @@ export function snapshotHeading(id, alias, contract) {
|
|
|
30
30
|
const head = [identity(id, alias), ...(contractId === undefined ? [] : [`└─ ${contractId}`])];
|
|
31
31
|
return [...head, frameRule(head)];
|
|
32
32
|
}
|
|
33
|
-
function answeredHeading(id, alias) {
|
|
34
|
-
const heading = `✓ answered ${identity(id, alias)}`;
|
|
35
|
-
return [heading, frameRule([heading])];
|
|
36
|
-
}
|
|
37
33
|
function contractFacts(contract) {
|
|
38
34
|
return contract.kind === "failed" ? [`! contract failed ${safeText(contract.diagnostic)}`] : [];
|
|
39
35
|
}
|
|
@@ -145,16 +141,6 @@ function compactLayout() {
|
|
|
145
141
|
function historyLayout() {
|
|
146
142
|
return { ...compactLayout(), history: true };
|
|
147
143
|
}
|
|
148
|
-
function sourceLayout(source, width, clock) {
|
|
149
|
-
const gutter = () => `${" ".repeat(TIME_WIDTH)} ${padToDisplay(source, width())} `;
|
|
150
|
-
return {
|
|
151
|
-
head: (time, glyph, verb, columns) => actionCell(`${time === undefined ? " ".repeat(TIME_WIDTH) : time.padEnd(TIME_WIDTH)} ${padToDisplay(source, width())} ${glyph}`, verb, columns),
|
|
152
|
-
continuation: () => `${" ".repeat(TIME_WIDTH)} ${" ".repeat(width())} │ ${" ".repeat(VERB_WIDTH)} `,
|
|
153
|
-
marker: (count) => `${gutter()}⋮ ${count} omitted`,
|
|
154
|
-
clock,
|
|
155
|
-
singleLine: true,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
144
|
function quotedBody(row) {
|
|
159
145
|
return (row.kind === "said" ||
|
|
160
146
|
row.kind === "thought" ||
|
|
@@ -408,16 +394,12 @@ function baselineOmissionCount(activity, after, before) {
|
|
|
408
394
|
function renderStreamRow(state, row, lines, options) {
|
|
409
395
|
const { context, layout, inFlightSay = false, unsettled = false } = options;
|
|
410
396
|
const at = clock(row.at);
|
|
411
|
-
const
|
|
412
|
-
const changed = previousClock === undefined || at !== previousClock;
|
|
397
|
+
const changed = state.previousClock === undefined || at !== state.previousClock;
|
|
413
398
|
lines.push(...renderTimelineRow(row, context, layout, changed ? at : undefined, {
|
|
414
399
|
inFlightSay,
|
|
415
400
|
unsettled,
|
|
416
401
|
}));
|
|
417
|
-
|
|
418
|
-
layout.clock.previous = at;
|
|
419
|
-
else
|
|
420
|
-
state.previousClock = at;
|
|
402
|
+
state.previousClock = at;
|
|
421
403
|
}
|
|
422
404
|
/**
|
|
423
405
|
* A say is in-flight only while it is the newest row of the open turn: it may still be streaming, so it
|
|
@@ -598,12 +580,6 @@ export function activityStream(context, layout = plainLayout()) {
|
|
|
598
580
|
seed: (activity, alreadyRenderedSequence) => render(seed(activity, alreadyRenderedSequence)),
|
|
599
581
|
frame,
|
|
600
582
|
flush: () => render(flush()),
|
|
601
|
-
emissions: {
|
|
602
|
-
observe: (activity) => observeActivitySnapshot(state, activity),
|
|
603
|
-
seed,
|
|
604
|
-
flush,
|
|
605
|
-
},
|
|
606
|
-
render,
|
|
607
583
|
});
|
|
608
584
|
}
|
|
609
585
|
function conclusionMarkVerb(status, outcome) {
|
|
@@ -630,18 +606,6 @@ function conclusionMarkVerb(status, outcome) {
|
|
|
630
606
|
return { mark: "!", verb: "untidy" };
|
|
631
607
|
return { mark: "!", verb: "stranded" };
|
|
632
608
|
}
|
|
633
|
-
/**
|
|
634
|
-
* The durable moment an Akuma settled, read from the outcome row its own timeline
|
|
635
|
-
* retained. Absent for an ending that leaves no outcome row, so the caller falls
|
|
636
|
-
* back to the observation that noticed it.
|
|
637
|
-
*/
|
|
638
|
-
function settleMoment(status) {
|
|
639
|
-
const outcome = status.timeline.kind === "idle" ? status.timeline.outcome : undefined;
|
|
640
|
-
if (outcome === undefined)
|
|
641
|
-
return undefined;
|
|
642
|
-
const at = new Date(outcome.at).getTime();
|
|
643
|
-
return Number.isFinite(at) ? at : undefined;
|
|
644
|
-
}
|
|
645
609
|
function clockFromMs(at) {
|
|
646
610
|
return clock(new Date(at).toISOString());
|
|
647
611
|
}
|
|
@@ -651,156 +615,6 @@ function durationText(durationMs) {
|
|
|
651
615
|
return `${seconds}s`;
|
|
652
616
|
return `${Math.floor(seconds / 60)}m${String(seconds % 60)}s`;
|
|
653
617
|
}
|
|
654
|
-
function createWaitObservationState() {
|
|
655
|
-
return {
|
|
656
|
-
streams: new Map(),
|
|
657
|
-
sources: new Map(),
|
|
658
|
-
tags: new Map(),
|
|
659
|
-
contracts: new Map(),
|
|
660
|
-
settledAt: new Map(),
|
|
661
|
-
sourceWidth: 0,
|
|
662
|
-
clock: {},
|
|
663
|
-
plural: undefined,
|
|
664
|
-
headerEmitted: false,
|
|
665
|
-
observed: false,
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
function shortestUniquePrefix(value, values) {
|
|
669
|
-
for (let length = 4; length <= value.length; length += 1) {
|
|
670
|
-
const tag = value.slice(0, length);
|
|
671
|
-
if (values.filter((candidate) => candidate.slice(0, length) === tag).length === 1)
|
|
672
|
-
return tag;
|
|
673
|
-
}
|
|
674
|
-
return undefined;
|
|
675
|
-
}
|
|
676
|
-
function shortestUniqueSegmentSuffix(id, ids) {
|
|
677
|
-
const segments = id.split("/");
|
|
678
|
-
for (let start = segments.length - 2; start >= 0; start -= 1) {
|
|
679
|
-
const tag = segments.slice(start).join("/");
|
|
680
|
-
if (ids.filter((candidate) => candidate.endsWith(`/${tag}`) || candidate === tag).length === 1)
|
|
681
|
-
return tag;
|
|
682
|
-
}
|
|
683
|
-
return undefined;
|
|
684
|
-
}
|
|
685
|
-
function waitIdentityTag(id, ids) {
|
|
686
|
-
const finals = ids.map((candidate) => candidate.slice(candidate.lastIndexOf("/") + 1));
|
|
687
|
-
const index = ids.indexOf(id);
|
|
688
|
-
const own = finals[index];
|
|
689
|
-
if (own === undefined)
|
|
690
|
-
return id;
|
|
691
|
-
return (shortestUniquePrefix(own, finals) ?? shortestUniqueSegmentSuffix(id, ids) ?? shortestUniquePrefix(id, ids) ?? id);
|
|
692
|
-
}
|
|
693
|
-
/** The selected set fixes identity tags before its first attributed row. */
|
|
694
|
-
function freezeWaitTags(state) {
|
|
695
|
-
const ids = [...state.sources.keys()];
|
|
696
|
-
state.tags = new Map(ids.map((id) => [id, waitIdentityTag(id, ids)]));
|
|
697
|
-
state.sourceWidth = Math.max(0, ...Array.from(state.tags.values(), displayColumns));
|
|
698
|
-
}
|
|
699
|
-
function sourceTag(state, id) {
|
|
700
|
-
return state.tags.get(id) ?? waitIdentityTag(id, [...state.sources.keys()]);
|
|
701
|
-
}
|
|
702
|
-
/** Register one selected or newly observed source; the set freezes the column before the first row. */
|
|
703
|
-
function registerWaitSource(state, id, alias, contract) {
|
|
704
|
-
if (state.sources.has(id))
|
|
705
|
-
return;
|
|
706
|
-
const label = alias ?? id;
|
|
707
|
-
state.sources.set(id, label);
|
|
708
|
-
if (contract !== undefined)
|
|
709
|
-
state.contracts.set(id, contract);
|
|
710
|
-
}
|
|
711
|
-
/**
|
|
712
|
-
* The one aggregate head a plural wait prints before any activity row: the
|
|
713
|
-
* selected set read as a list, each target on its own line named by the alias
|
|
714
|
-
* addressing it, otherwise its complete identity, with its `· kei/<contract>`
|
|
715
|
-
* association inline when one exists, all closed by the frame's single rule.
|
|
716
|
-
*/
|
|
717
|
-
function aggregateHeading(state) {
|
|
718
|
-
const head = [...state.sources].map(([id, label]) => {
|
|
719
|
-
const contractId = associatedContractId(state.contracts.get(id) ?? { kind: "none" });
|
|
720
|
-
const named = `${sourceTag(state, id)} ${label}`;
|
|
721
|
-
return contractId === undefined ? named : `${named} · ${contractId}`;
|
|
722
|
-
});
|
|
723
|
-
return [...head, frameRule(head)];
|
|
724
|
-
}
|
|
725
|
-
function observeWaitRound(state, round, context, now) {
|
|
726
|
-
state.observed = true;
|
|
727
|
-
// Establish the whole round's sources before any row so widths stay aligned within it.
|
|
728
|
-
for (const member of round)
|
|
729
|
-
registerWaitSource(state, member.status.id, member.alias, member.contract);
|
|
730
|
-
if (!state.headerEmitted)
|
|
731
|
-
freezeWaitTags(state);
|
|
732
|
-
const lines = [];
|
|
733
|
-
// The observation subject opens once: an aggregate head for a plural set, the observed
|
|
734
|
-
// identity frame for a single target. Every later round only appends attributed rows.
|
|
735
|
-
if (!state.headerEmitted && round.length > 0) {
|
|
736
|
-
state.headerEmitted = true;
|
|
737
|
-
state.plural ??= state.sources.size > 1;
|
|
738
|
-
if (state.plural) {
|
|
739
|
-
lines.push(...aggregateHeading(state));
|
|
740
|
-
}
|
|
741
|
-
else {
|
|
742
|
-
const sole = round[0];
|
|
743
|
-
lines.push(...snapshotHeading(sole.status.id, sole.alias, sole.contract));
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
const parts = [];
|
|
747
|
-
for (const { status, rows } of round) {
|
|
748
|
-
const known = state.streams.get(status.id);
|
|
749
|
-
if (known !== undefined) {
|
|
750
|
-
parts.push({ stream: known, emissions: known.emissions.observe({ snapshot: status.timeline, rows }) });
|
|
751
|
-
}
|
|
752
|
-
else {
|
|
753
|
-
// Only a plural wait attributes its rows; a single-target stream keeps the plain row grammar.
|
|
754
|
-
const stream = activityStream(context, state.plural === true
|
|
755
|
-
? sourceLayout(sourceTag(state, status.id), () => state.sourceWidth, state.clock)
|
|
756
|
-
: plainLayout());
|
|
757
|
-
state.streams.set(status.id, stream);
|
|
758
|
-
// Seed marks skipped retained evidence without spending this command's live tool budget.
|
|
759
|
-
parts.push({ stream, emissions: stream.emissions.seed({ snapshot: status.timeline, rows }) });
|
|
760
|
-
}
|
|
761
|
-
if (!state.settledAt.has(status.id) && defaultWaitComplete(status))
|
|
762
|
-
state.settledAt.set(status.id, settleMoment(status) ?? now());
|
|
763
|
-
}
|
|
764
|
-
lines.push(...mergeStreamEmissions(parts));
|
|
765
|
-
return lines;
|
|
766
|
-
}
|
|
767
|
-
/**
|
|
768
|
-
* Merge one observation's decided output across sources by row time. Each
|
|
769
|
-
* source keeps its own order; an omission count travels with the row after it,
|
|
770
|
-
* or with the row before it when it trails. Ties keep selection order.
|
|
771
|
-
*/
|
|
772
|
-
function mergeStreamEmissions(parts) {
|
|
773
|
-
const queues = parts.map(({ stream, emissions }) => {
|
|
774
|
-
const units = [];
|
|
775
|
-
let pending = [];
|
|
776
|
-
for (const emission of emissions) {
|
|
777
|
-
pending.push(emission);
|
|
778
|
-
if (emission.kind !== "row")
|
|
779
|
-
continue;
|
|
780
|
-
const at = Date.parse(emission.row.at);
|
|
781
|
-
units.push({ at: Number.isFinite(at) ? at : (units.at(-1)?.at ?? Number.NEGATIVE_INFINITY), emissions: pending });
|
|
782
|
-
pending = [];
|
|
783
|
-
}
|
|
784
|
-
if (pending.length > 0) {
|
|
785
|
-
const last = units.at(-1);
|
|
786
|
-
if (last === undefined)
|
|
787
|
-
units.push({ at: Number.NEGATIVE_INFINITY, emissions: pending });
|
|
788
|
-
else
|
|
789
|
-
last.emissions.push(...pending);
|
|
790
|
-
}
|
|
791
|
-
return { stream, units };
|
|
792
|
-
});
|
|
793
|
-
const lines = [];
|
|
794
|
-
for (;;) {
|
|
795
|
-
let next;
|
|
796
|
-
for (const queue of queues)
|
|
797
|
-
if (queue.units.length > 0 && (next === undefined || queue.units[0].at < next.units[0].at))
|
|
798
|
-
next = queue;
|
|
799
|
-
if (next === undefined)
|
|
800
|
-
return lines;
|
|
801
|
-
lines.push(...next.stream.render(next.units.shift().emissions));
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
618
|
/**
|
|
805
619
|
* A conclusion clause asserts real waiting: a target that settled at or after
|
|
806
620
|
* this wait began keeps its duration, a target already settled names no
|
|
@@ -842,91 +656,6 @@ export function inputWaitConclusion(observation, input) {
|
|
|
842
656
|
: []),
|
|
843
657
|
];
|
|
844
658
|
}
|
|
845
|
-
/** Present ids in frozen selection order, then any result member the selection never named. */
|
|
846
|
-
function orderedWaitIds(state, result) {
|
|
847
|
-
const ids = [...state.sources.keys()];
|
|
848
|
-
const known = new Set(ids);
|
|
849
|
-
for (const observation of result.observations) {
|
|
850
|
-
if (!known.has(observation.status.id)) {
|
|
851
|
-
known.add(observation.status.id);
|
|
852
|
-
ids.push(observation.status.id);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
for (const member of result.unobserved) {
|
|
856
|
-
if (!known.has(member.id)) {
|
|
857
|
-
known.add(member.id);
|
|
858
|
-
ids.push(member.id);
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
return ids;
|
|
862
|
-
}
|
|
863
|
-
function flushWaitStreams(state) {
|
|
864
|
-
return mergeStreamEmissions([...state.streams.values()].map((stream) => ({ stream, emissions: stream.emissions.flush() })));
|
|
865
|
-
}
|
|
866
|
-
function concludeWaitStream(state, result, startedAt, now) {
|
|
867
|
-
const tail = flushWaitStreams(state);
|
|
868
|
-
const end = now();
|
|
869
|
-
for (const observation of result.observations)
|
|
870
|
-
registerWaitSource(state, observation.status.id, undefined, observation.contract);
|
|
871
|
-
for (const member of result.unobserved)
|
|
872
|
-
registerWaitSource(state, member.id, undefined);
|
|
873
|
-
if (!state.headerEmitted)
|
|
874
|
-
freezeWaitTags(state);
|
|
875
|
-
const order = orderedWaitIds(state, result);
|
|
876
|
-
const multi = order.length > 1;
|
|
877
|
-
const observationById = new Map(result.observations.map((observation) => [observation.status.id, observation]));
|
|
878
|
-
const unobservedById = new Map(result.unobserved.map((member) => [member.id, member]));
|
|
879
|
-
// A failure fact keeps the complete identity even where the scoreboard attributes a target by its identity tag.
|
|
880
|
-
const unobservedLines = order
|
|
881
|
-
.filter((id) => unobservedById.has(id))
|
|
882
|
-
.map((id) => unobservedText(id, unobservedById.get(id).diagnostic));
|
|
883
|
-
const conclusions = order.flatMap((id) => {
|
|
884
|
-
const observation = observationById.get(id);
|
|
885
|
-
if (observation === undefined)
|
|
886
|
-
return [];
|
|
887
|
-
const status = observation.status;
|
|
888
|
-
const complete = defaultWaitComplete(status);
|
|
889
|
-
const at = complete ? (state.settledAt.get(id) ?? end) : end;
|
|
890
|
-
const { mark, verb } = conclusionMarkVerb(status, statusAnswer(observation) !== undefined ? "answered" : "life");
|
|
891
|
-
const target = multi ? ` ${padToDisplay(sourceTag(state, id), state.sourceWidth)}` : "";
|
|
892
|
-
return [waitConclusionRow({ at, startedAt, complete, end, mark, verb, target })];
|
|
893
|
-
});
|
|
894
|
-
const answeredSingle = !multi && result.observations.length === 1 && statusAnswer(result.observations[0]) !== undefined;
|
|
895
|
-
const blocks = [
|
|
896
|
-
...(conclusions.length > 0 ? [conclusions.join("\n")] : []),
|
|
897
|
-
...(unobservedLines.length > 0 ? [unobservedLines.join("\n")] : []),
|
|
898
|
-
];
|
|
899
|
-
const body = [...tail, ...blocks].join("\n");
|
|
900
|
-
// One blank line keeps the bare stdout answer visually separate from the stream.
|
|
901
|
-
return answeredSingle ? `${body}\n\n` : body;
|
|
902
|
-
}
|
|
903
|
-
/**
|
|
904
|
-
* Live view over a wait's successive observation rounds, one append-only
|
|
905
|
-
* stream per selected Akuma. A plural wait opens one aggregate frame naming
|
|
906
|
-
* its selected set before any activity row and never opens a per-target frame
|
|
907
|
-
* during observation; a single-target wait opens that Akuma's own identity
|
|
908
|
-
* frame — the identity and Contract association the observed facts carry —
|
|
909
|
-
* and an already settled Akuma prints that frame while replaying no backlog
|
|
910
|
-
* rows. `conclude` renders the closing rows once the wait ends: one row per
|
|
911
|
-
* observed Akuma in `<clock> <mark> <verb> — <duration>` grammar, with a target
|
|
912
|
-
* named for a multi-target scoreboard and no activity replay.
|
|
913
|
-
*/
|
|
914
|
-
export function waitObservationStream(context, options = {}) {
|
|
915
|
-
const now = options.now ?? (() => Date.now());
|
|
916
|
-
const startedAt = now();
|
|
917
|
-
const state = createWaitObservationState();
|
|
918
|
-
const select = (selected) => {
|
|
919
|
-
for (const member of selected)
|
|
920
|
-
registerWaitSource(state, member.id, member.alias, member.contract);
|
|
921
|
-
state.plural ??= selected.length > 1;
|
|
922
|
-
freezeWaitTags(state);
|
|
923
|
-
};
|
|
924
|
-
const observe = (round) => observeWaitRound(state, round, context, now);
|
|
925
|
-
const frame = () => [...state.streams.values()].flatMap((stream) => stream.frame());
|
|
926
|
-
const flush = () => flushWaitStreams(state);
|
|
927
|
-
const conclude = (result) => concludeWaitStream(state, result, startedAt, now);
|
|
928
|
-
return { select, observe, frame, flush, conclude, streamed: () => state.observed };
|
|
929
|
-
}
|
|
930
659
|
function failedOutcomeDiagnostic(status) {
|
|
931
660
|
const outcome = status.timeline.kind === "idle" ? status.timeline.outcome : undefined;
|
|
932
661
|
return outcome !== undefined && outcome.outcome.kind === "failed" ? outcome.outcome.diagnostic : undefined;
|
|
@@ -1032,8 +761,8 @@ function renderReportedChangeLines(snapshot) {
|
|
|
1032
761
|
...(snapshot.reportedChangesOmitted > 0 ? [` ⋮ ${snapshot.reportedChangesOmitted} more files`] : []),
|
|
1033
762
|
];
|
|
1034
763
|
}
|
|
1035
|
-
function
|
|
1036
|
-
const prefix = ` ${
|
|
764
|
+
function renderDebtRow(row, columns) {
|
|
765
|
+
const prefix = ` ${debtDispositionMark(row.disposition)} ${row.id} · `;
|
|
1037
766
|
const body = `${safeText(row.title)} · ${row.disposition} · P${row.priority}`;
|
|
1038
767
|
const inline = `${prefix}${body}`;
|
|
1039
768
|
if (displayColumns(inline) <= columns)
|
|
@@ -1045,28 +774,14 @@ function renderTaskRow(row, columns) {
|
|
|
1045
774
|
lines: Number.MAX_SAFE_INTEGER,
|
|
1046
775
|
});
|
|
1047
776
|
}
|
|
1048
|
-
function
|
|
777
|
+
function renderDebtContextLines(created, columns) {
|
|
1049
778
|
if (created === undefined)
|
|
1050
779
|
return [];
|
|
1051
780
|
if (created.kind === "failed")
|
|
1052
|
-
return [`!
|
|
781
|
+
return [`! debts failed ${safeText(created.diagnostic)}`];
|
|
1053
782
|
if (created.rows.length === 0)
|
|
1054
783
|
return [];
|
|
1055
|
-
return [`
|
|
1056
|
-
}
|
|
1057
|
-
function answerContextLines(observation, columns) {
|
|
1058
|
-
return [
|
|
1059
|
-
...renderTaskContextLines(observation.createdTasks, columns),
|
|
1060
|
-
...renderReportedChangeLines(observation.status.timeline),
|
|
1061
|
-
];
|
|
1062
|
-
}
|
|
1063
|
-
function answeredBlock(observation, answer, alias, columns) {
|
|
1064
|
-
const frame = answeredHeading(observation.status.id, alias).join("\n");
|
|
1065
|
-
const context = answerContextLines(observation, columns).join("\n");
|
|
1066
|
-
if (context.length === 0)
|
|
1067
|
-
return `${frame}\n${answer}`;
|
|
1068
|
-
const separator = answer.endsWith("\n") ? "\n" : "\n\n";
|
|
1069
|
-
return `${frame}\n${answer}${separator}${context}`;
|
|
784
|
+
return [`debts ${created.rows.length}`, ...created.rows.flatMap((row) => renderDebtRow(row, columns))];
|
|
1070
785
|
}
|
|
1071
786
|
function snapshotCore(view, context, options) {
|
|
1072
787
|
const activity = snapshotActivityLines(view.status.timeline, context);
|
|
@@ -1094,12 +809,12 @@ function snapshotConclusion(status) {
|
|
|
1094
809
|
}
|
|
1095
810
|
export function snapshotText(view, context, options = {}) {
|
|
1096
811
|
const core = snapshotCore(view, context, options);
|
|
1097
|
-
const
|
|
812
|
+
const debtContext = renderDebtContextLines(view.createdDebts, context.columns);
|
|
1098
813
|
const conclusion = snapshotConclusion(view.status);
|
|
1099
814
|
return [
|
|
1100
815
|
...core.lines,
|
|
1101
816
|
...(conclusion.length === 0 ? [] : [conclusion]),
|
|
1102
|
-
...(
|
|
817
|
+
...(debtContext.length > 0 ? ["", ...debtContext] : []),
|
|
1103
818
|
...(view.status.timeline.reportedChanges.length > 0 || view.status.timeline.reportedChangesOmitted > 0 ? [""] : []),
|
|
1104
819
|
...renderReportedChangeLines(view.status.timeline),
|
|
1105
820
|
...(core.facts.length > 0 ? ["", ...core.facts] : []),
|
|
@@ -1117,16 +832,6 @@ function killResultLabel(evidence) {
|
|
|
1117
832
|
export function killResultText(id, evidence, alias) {
|
|
1118
833
|
return [...snapshotHeading(id, alias, undefined), "", killResultLabel(evidence)].join("\n");
|
|
1119
834
|
}
|
|
1120
|
-
export function statusAnswer(view) {
|
|
1121
|
-
if (!defaultWaitComplete(view.status))
|
|
1122
|
-
return undefined;
|
|
1123
|
-
if (view.status.life !== "asleep")
|
|
1124
|
-
return undefined;
|
|
1125
|
-
const timeline = view.status.timeline;
|
|
1126
|
-
if (timeline.kind !== "idle" || timeline.outcome?.outcome.kind !== "answered")
|
|
1127
|
-
return undefined;
|
|
1128
|
-
return timeline.outcome.outcome.answer;
|
|
1129
|
-
}
|
|
1130
835
|
function answerBytes(answer, structured) {
|
|
1131
836
|
return !structured && typeof answer === "string" ? answer : JSON.stringify(answer);
|
|
1132
837
|
}
|
|
@@ -1141,90 +846,23 @@ export function callRawAnswer(result, streamed) {
|
|
|
1141
846
|
return streamed ? "" : undefined;
|
|
1142
847
|
return answerBytes(observation.observation.answer, result.structured === true);
|
|
1143
848
|
}
|
|
1144
|
-
export function waitRawAnswer(result, streamed) {
|
|
1145
|
-
const total = result.observations.length + result.unobserved.length;
|
|
1146
|
-
if (streamed) {
|
|
1147
|
-
// Plural waits leave stdout empty so one answer can never be mistaken for the whole result.
|
|
1148
|
-
if (total !== 1)
|
|
1149
|
-
return "";
|
|
1150
|
-
const single = result.observations[0];
|
|
1151
|
-
return single === undefined ? "" : (statusAnswer(single) ?? "");
|
|
1152
|
-
}
|
|
1153
|
-
if (total !== 1)
|
|
1154
|
-
return undefined;
|
|
1155
|
-
return statusAnswer(result.observations[0]);
|
|
1156
|
-
}
|
|
1157
849
|
export function historyRawAnswer(result, historyId) {
|
|
1158
850
|
if (historyId === undefined || result.kind !== "exact")
|
|
1159
851
|
return undefined;
|
|
1160
852
|
const outcome = result.outcome.outcome;
|
|
1161
853
|
return outcome.kind === "answered" ? outcome.answer : outcome.diagnostic;
|
|
1162
854
|
}
|
|
855
|
+
/**
|
|
856
|
+
* One wait's final text: each observed Akuma's own status snapshot, then one
|
|
857
|
+
* failure fact per member the wait could not read. A wait observes to its
|
|
858
|
+
* completion judgment and streams nothing, so an answer is visible only as the
|
|
859
|
+
* snapshot's own outcome row.
|
|
860
|
+
*/
|
|
1163
861
|
export function waitText(result, presentation, context) {
|
|
1164
|
-
const alias = presentation.alias;
|
|
1165
|
-
const
|
|
1166
|
-
const unobserved = result.unobserved;
|
|
1167
|
-
|
|
1168
|
-
if (total <= 1) {
|
|
1169
|
-
const single = [
|
|
1170
|
-
...observations.map((observation) => {
|
|
1171
|
-
const answer = statusAnswer(observation);
|
|
1172
|
-
if (answer !== undefined)
|
|
1173
|
-
return answeredBlock(observation, answer, alias, context.columns);
|
|
1174
|
-
return snapshotText(observation, context, { ...(alias === undefined ? {} : { alias }) });
|
|
1175
|
-
}),
|
|
1176
|
-
...unobserved.map((member) => unobservedText(member.id, member.diagnostic)),
|
|
1177
|
-
];
|
|
1178
|
-
return single.join("\n\n");
|
|
1179
|
-
}
|
|
1180
|
-
const end = Date.now();
|
|
1181
|
-
const startedAt = presentation.startedAt ?? end;
|
|
1182
|
-
const order = [];
|
|
1183
|
-
const remember = (id) => {
|
|
1184
|
-
if (!order.includes(id))
|
|
1185
|
-
order.push(id);
|
|
1186
|
-
};
|
|
1187
|
-
for (const member of presentation.selection ?? [])
|
|
1188
|
-
remember(member.id);
|
|
1189
|
-
for (const observation of observations)
|
|
1190
|
-
remember(observation.status.id);
|
|
1191
|
-
for (const member of unobserved)
|
|
1192
|
-
remember(member.id);
|
|
1193
|
-
const observationById = new Map(observations.map((observation) => [observation.status.id, observation]));
|
|
1194
|
-
const unobservedById = new Map(unobserved.map((member) => [member.id, member]));
|
|
1195
|
-
const sourceWidth = Math.max(0, ...order.map((id) => displayColumns(waitIdentityTag(id, order))));
|
|
1196
|
-
const blocks = [
|
|
1197
|
-
...order.flatMap((id) => {
|
|
1198
|
-
const observation = observationById.get(id);
|
|
1199
|
-
if (observation === undefined)
|
|
1200
|
-
return [];
|
|
1201
|
-
const answer = statusAnswer(observation);
|
|
1202
|
-
if (answer !== undefined)
|
|
1203
|
-
return [answeredBlock(observation, answer, undefined, context.columns)];
|
|
1204
|
-
return [snapshotText(observation, context)];
|
|
1205
|
-
}),
|
|
1206
|
-
...(unobserved.length > 0
|
|
1207
|
-
? [
|
|
1208
|
-
order
|
|
1209
|
-
.filter((id) => unobservedById.has(id))
|
|
1210
|
-
.map((id) => unobservedText(id, unobservedById.get(id).diagnostic))
|
|
1211
|
-
.join("\n"),
|
|
1212
|
-
]
|
|
1213
|
-
: []),
|
|
1214
|
-
];
|
|
1215
|
-
const rows = order.flatMap((id) => {
|
|
1216
|
-
const observation = observationById.get(id);
|
|
1217
|
-
if (observation === undefined)
|
|
1218
|
-
return [];
|
|
1219
|
-
const status = observation.status;
|
|
1220
|
-
const complete = defaultWaitComplete(status);
|
|
1221
|
-
const at = complete ? (settleMoment(status) ?? end) : end;
|
|
1222
|
-
const { mark, verb } = conclusionMarkVerb(status, statusAnswer(observation) !== undefined ? "answered" : "life");
|
|
1223
|
-
return [
|
|
1224
|
-
`${clockFromMs(at)} ${padToDisplay(waitIdentityTag(id, order), sourceWidth)} ${mark} ${verb}${conclusionClause(at, startedAt, complete, end)}`,
|
|
1225
|
-
];
|
|
1226
|
-
});
|
|
1227
|
-
return rows.length > 0 ? [...blocks, rows.join("\n")].join("\n\n") : blocks.join("\n\n");
|
|
862
|
+
const alias = result.observations.length === 1 && result.unobserved.length === 0 ? presentation.alias : undefined;
|
|
863
|
+
const blocks = result.observations.map((observation) => snapshotText(observation, context, { ...(alias === undefined ? {} : { alias }) }));
|
|
864
|
+
const unobserved = result.unobserved.map((member) => unobservedText(member.id, member.diagnostic));
|
|
865
|
+
return [...blocks, ...(unobserved.length === 0 ? [] : [unobserved.join("\n")])].join("\n\n");
|
|
1228
866
|
}
|
|
1229
867
|
export function historyText(result, presentation, context) {
|
|
1230
868
|
if (presentation.id !== undefined) {
|