@kenkaiiii/ggcoder 4.3.205 → 4.3.207

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.
Files changed (193) hide show
  1. package/dist/cli.js +38 -26
  2. package/dist/cli.js.map +1 -1
  3. package/dist/config.js +2 -2
  4. package/dist/core/compaction/compactor.d.ts.map +1 -1
  5. package/dist/core/compaction/compactor.js +6 -0
  6. package/dist/core/compaction/compactor.js.map +1 -1
  7. package/dist/core/compaction/compactor.test.js +16 -0
  8. package/dist/core/compaction/compactor.test.js.map +1 -1
  9. package/dist/core/goal-controller.d.ts +57 -0
  10. package/dist/core/goal-controller.d.ts.map +1 -0
  11. package/dist/core/goal-controller.js +285 -0
  12. package/dist/core/goal-controller.js.map +1 -0
  13. package/dist/core/goal-controller.test.d.ts +2 -0
  14. package/dist/core/goal-controller.test.d.ts.map +1 -0
  15. package/dist/core/goal-controller.test.js +419 -0
  16. package/dist/core/goal-controller.test.js.map +1 -0
  17. package/dist/core/goal-lifecycle-smoke.test.d.ts +2 -0
  18. package/dist/core/goal-lifecycle-smoke.test.d.ts.map +1 -0
  19. package/dist/core/goal-lifecycle-smoke.test.js +207 -0
  20. package/dist/core/goal-lifecycle-smoke.test.js.map +1 -0
  21. package/dist/core/goal-store.d.ts +164 -0
  22. package/dist/core/goal-store.d.ts.map +1 -0
  23. package/dist/core/goal-store.js +721 -0
  24. package/dist/core/goal-store.js.map +1 -0
  25. package/dist/core/goal-store.test.d.ts +2 -0
  26. package/dist/core/goal-store.test.d.ts.map +1 -0
  27. package/dist/core/goal-store.test.js +341 -0
  28. package/dist/core/goal-store.test.js.map +1 -0
  29. package/dist/core/goal-verifier.d.ts +17 -0
  30. package/dist/core/goal-verifier.d.ts.map +1 -0
  31. package/dist/core/goal-verifier.js +84 -0
  32. package/dist/core/goal-verifier.js.map +1 -0
  33. package/dist/core/goal-verifier.test.d.ts +2 -0
  34. package/dist/core/goal-verifier.test.d.ts.map +1 -0
  35. package/dist/core/goal-verifier.test.js +88 -0
  36. package/dist/core/goal-verifier.test.js.map +1 -0
  37. package/dist/core/goal-worker-dev-server-lifecycle.test.d.ts +2 -0
  38. package/dist/core/goal-worker-dev-server-lifecycle.test.d.ts.map +1 -0
  39. package/dist/core/goal-worker-dev-server-lifecycle.test.js +68 -0
  40. package/dist/core/goal-worker-dev-server-lifecycle.test.js.map +1 -0
  41. package/dist/core/goal-worker.d.ts +51 -0
  42. package/dist/core/goal-worker.d.ts.map +1 -0
  43. package/dist/core/goal-worker.js +339 -0
  44. package/dist/core/goal-worker.js.map +1 -0
  45. package/dist/core/goal-worker.test.d.ts +2 -0
  46. package/dist/core/goal-worker.test.d.ts.map +1 -0
  47. package/dist/core/goal-worker.test.js +224 -0
  48. package/dist/core/goal-worker.test.js.map +1 -0
  49. package/dist/core/model-registry.test.js +51 -1
  50. package/dist/core/model-registry.test.js.map +1 -1
  51. package/dist/core/oauth/gemini.d.ts.map +1 -1
  52. package/dist/core/oauth/gemini.js +138 -30
  53. package/dist/core/oauth/gemini.js.map +1 -1
  54. package/dist/core/oauth/gemini.test.d.ts +2 -0
  55. package/dist/core/oauth/gemini.test.d.ts.map +1 -0
  56. package/dist/core/oauth/gemini.test.js +154 -0
  57. package/dist/core/oauth/gemini.test.js.map +1 -0
  58. package/dist/core/process-manager-dev-server-repro.test.d.ts +2 -0
  59. package/dist/core/process-manager-dev-server-repro.test.d.ts.map +1 -0
  60. package/dist/core/process-manager-dev-server-repro.test.js +100 -0
  61. package/dist/core/process-manager-dev-server-repro.test.js.map +1 -0
  62. package/dist/core/process-manager.js +2 -2
  63. package/dist/core/process-manager.js.map +1 -1
  64. package/dist/core/prompt-commands.d.ts.map +1 -1
  65. package/dist/core/prompt-commands.js +125 -0
  66. package/dist/core/prompt-commands.js.map +1 -1
  67. package/dist/core/prompt-commands.test.js +38 -0
  68. package/dist/core/prompt-commands.test.js.map +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +1 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/interactive.d.ts.map +1 -1
  74. package/dist/interactive.js +20 -11
  75. package/dist/interactive.js.map +1 -1
  76. package/dist/system-prompt.d.ts.map +1 -1
  77. package/dist/system-prompt.js +19 -50
  78. package/dist/system-prompt.js.map +1 -1
  79. package/dist/system-prompt.test.js +124 -1
  80. package/dist/system-prompt.test.js.map +1 -1
  81. package/dist/tools/edit-diff.d.ts.map +1 -1
  82. package/dist/tools/edit-diff.js +71 -32
  83. package/dist/tools/edit-diff.js.map +1 -1
  84. package/dist/tools/edit-diff.test.js +14 -0
  85. package/dist/tools/edit-diff.test.js.map +1 -1
  86. package/dist/tools/edit.d.ts.map +1 -1
  87. package/dist/tools/edit.js +38 -18
  88. package/dist/tools/edit.js.map +1 -1
  89. package/dist/tools/edit.test.js +56 -6
  90. package/dist/tools/edit.test.js.map +1 -1
  91. package/dist/tools/enter-plan.d.ts.map +1 -1
  92. package/dist/tools/enter-plan.js +1 -0
  93. package/dist/tools/enter-plan.js.map +1 -1
  94. package/dist/tools/goals.d.ts +110 -0
  95. package/dist/tools/goals.d.ts.map +1 -0
  96. package/dist/tools/goals.js +500 -0
  97. package/dist/tools/goals.js.map +1 -0
  98. package/dist/tools/goals.test.d.ts +2 -0
  99. package/dist/tools/goals.test.d.ts.map +1 -0
  100. package/dist/tools/goals.test.js +431 -0
  101. package/dist/tools/goals.test.js.map +1 -0
  102. package/dist/tools/index.d.ts +2 -0
  103. package/dist/tools/index.d.ts.map +1 -1
  104. package/dist/tools/index.js +6 -0
  105. package/dist/tools/index.js.map +1 -1
  106. package/dist/tools/prompt-hints.d.ts.map +1 -1
  107. package/dist/tools/prompt-hints.js +2 -0
  108. package/dist/tools/prompt-hints.js.map +1 -1
  109. package/dist/tools/source-path.d.ts +9 -0
  110. package/dist/tools/source-path.d.ts.map +1 -0
  111. package/dist/tools/source-path.js +119 -0
  112. package/dist/tools/source-path.js.map +1 -0
  113. package/dist/tools/source-path.test.d.ts +2 -0
  114. package/dist/tools/source-path.test.d.ts.map +1 -0
  115. package/dist/tools/source-path.test.js +80 -0
  116. package/dist/tools/source-path.test.js.map +1 -0
  117. package/dist/tools/subagent.js +16 -0
  118. package/dist/tools/subagent.js.map +1 -1
  119. package/dist/ui/App.d.ts +73 -4
  120. package/dist/ui/App.d.ts.map +1 -1
  121. package/dist/ui/App.js +1068 -140
  122. package/dist/ui/App.js.map +1 -1
  123. package/dist/ui/activity-phrases.d.ts.map +1 -1
  124. package/dist/ui/activity-phrases.js +7 -3
  125. package/dist/ui/activity-phrases.js.map +1 -1
  126. package/dist/ui/app-state-persistence.test.d.ts +2 -0
  127. package/dist/ui/app-state-persistence.test.d.ts.map +1 -0
  128. package/dist/ui/app-state-persistence.test.js +130 -0
  129. package/dist/ui/app-state-persistence.test.js.map +1 -0
  130. package/dist/ui/components/BackgroundTasksBar.d.ts +16 -1
  131. package/dist/ui/components/BackgroundTasksBar.d.ts.map +1 -1
  132. package/dist/ui/components/BackgroundTasksBar.js +15 -2
  133. package/dist/ui/components/BackgroundTasksBar.js.map +1 -1
  134. package/dist/ui/components/Banner.d.ts +2 -1
  135. package/dist/ui/components/Banner.d.ts.map +1 -1
  136. package/dist/ui/components/Banner.js +3 -3
  137. package/dist/ui/components/Banner.js.map +1 -1
  138. package/dist/ui/components/GoalOverlay.d.ts +74 -0
  139. package/dist/ui/components/GoalOverlay.d.ts.map +1 -0
  140. package/dist/ui/components/GoalOverlay.js +675 -0
  141. package/dist/ui/components/GoalOverlay.js.map +1 -0
  142. package/dist/ui/components/GoalStatusBar.d.ts +24 -0
  143. package/dist/ui/components/GoalStatusBar.d.ts.map +1 -0
  144. package/dist/ui/components/GoalStatusBar.js +113 -0
  145. package/dist/ui/components/GoalStatusBar.js.map +1 -0
  146. package/dist/ui/components/InputArea.d.ts +2 -1
  147. package/dist/ui/components/InputArea.d.ts.map +1 -1
  148. package/dist/ui/components/InputArea.js +44 -2
  149. package/dist/ui/components/InputArea.js.map +1 -1
  150. package/dist/ui/components/InputArea.test.d.ts +2 -0
  151. package/dist/ui/components/InputArea.test.d.ts.map +1 -0
  152. package/dist/ui/components/InputArea.test.js +79 -0
  153. package/dist/ui/components/InputArea.test.js.map +1 -0
  154. package/dist/ui/components/ToolExecution.d.ts.map +1 -1
  155. package/dist/ui/components/ToolExecution.js +96 -3
  156. package/dist/ui/components/ToolExecution.js.map +1 -1
  157. package/dist/ui/footer-status-layout.test.d.ts +2 -0
  158. package/dist/ui/footer-status-layout.test.d.ts.map +1 -0
  159. package/dist/ui/footer-status-layout.test.js +56 -0
  160. package/dist/ui/footer-status-layout.test.js.map +1 -0
  161. package/dist/ui/goal-events.d.ts +107 -0
  162. package/dist/ui/goal-events.d.ts.map +1 -0
  163. package/dist/ui/goal-events.js +323 -0
  164. package/dist/ui/goal-events.js.map +1 -0
  165. package/dist/ui/goal-events.test.d.ts +2 -0
  166. package/dist/ui/goal-events.test.d.ts.map +1 -0
  167. package/dist/ui/goal-events.test.js +293 -0
  168. package/dist/ui/goal-events.test.js.map +1 -0
  169. package/dist/ui/goal-overlay.test.d.ts +2 -0
  170. package/dist/ui/goal-overlay.test.d.ts.map +1 -0
  171. package/dist/ui/goal-overlay.test.js +276 -0
  172. package/dist/ui/goal-overlay.test.js.map +1 -0
  173. package/dist/ui/goal-status-bar.test.d.ts +2 -0
  174. package/dist/ui/goal-status-bar.test.d.ts.map +1 -0
  175. package/dist/ui/goal-status-bar.test.js +143 -0
  176. package/dist/ui/goal-status-bar.test.js.map +1 -0
  177. package/dist/ui/live-item-flush.test.js +48 -0
  178. package/dist/ui/live-item-flush.test.js.map +1 -1
  179. package/dist/ui/render.d.ts +11 -4
  180. package/dist/ui/render.d.ts.map +1 -1
  181. package/dist/ui/render.js +12 -3
  182. package/dist/ui/render.js.map +1 -1
  183. package/dist/ui/scroll-stabilization.test.d.ts +2 -0
  184. package/dist/ui/scroll-stabilization.test.d.ts.map +1 -0
  185. package/dist/ui/scroll-stabilization.test.js +70 -0
  186. package/dist/ui/scroll-stabilization.test.js.map +1 -0
  187. package/dist/ui/slash-command-images.test.d.ts +2 -0
  188. package/dist/ui/slash-command-images.test.d.ts.map +1 -0
  189. package/dist/ui/slash-command-images.test.js +47 -0
  190. package/dist/ui/slash-command-images.test.js.map +1 -0
  191. package/dist/utils/format.js +44 -0
  192. package/dist/utils/format.js.map +1 -1
  193. package/package.json +6 -5
@@ -0,0 +1,675 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React, { useCallback, useEffect, useRef, useState } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ import { basename } from "node:path";
5
+ import { formatGoalPrerequisiteInstruction, goalHasBlockingPrerequisites, isBlockingGoalPrerequisite, loadGoalRuns, saveGoalRuns, summarizeGoalCountsFromRuns, } from "../../core/goal-store.js";
6
+ import { useTerminalSize } from "../hooks/useTerminalSize.js";
7
+ import { useTheme } from "../theme/theme.js";
8
+ const GOAL_LOGO = [" ▄▀▀▀ ▄▀▀▀", " █ ▀█ █ ▀█", " ▀▄▄▀ ▀▄▄▀"];
9
+ const GRADIENT = [
10
+ "#4ade80",
11
+ "#5ad89a",
12
+ "#6fd2b4",
13
+ "#85ccce",
14
+ "#60a5fa",
15
+ "#85ccce",
16
+ "#6fd2b4",
17
+ "#5ad89a",
18
+ ];
19
+ const GOAL_SUCCESS = "#4ade80";
20
+ const GOAL_ACTIVE = "#fbbf24";
21
+ const GAP = " ";
22
+ const LOGO_WIDTH = 9;
23
+ const SIDE_BY_SIDE_MIN = LOGO_WIDTH + GAP.length + 20;
24
+ export function clampGoalSelectedIndex(index, length) {
25
+ if (length <= 0)
26
+ return 0;
27
+ return Math.min(Math.max(0, index), length - 1);
28
+ }
29
+ export function formatGoalPrerequisiteSummary(run) {
30
+ if (run.prerequisites.length === 0)
31
+ return "no prereqs";
32
+ const met = run.prerequisites.filter((item) => item.status === "met").length;
33
+ const missing = run.prerequisites.filter((item) => item.status === "missing").length;
34
+ const unknown = run.prerequisites.filter((item) => item.status === "unknown").length;
35
+ const suffix = [missing > 0 ? `${missing} missing` : "", unknown > 0 ? `${unknown} unknown` : ""]
36
+ .filter(Boolean)
37
+ .join(", ");
38
+ return `${met}/${run.prerequisites.length} prereqs met${suffix ? ` (${suffix})` : ""}`;
39
+ }
40
+ export function formatGoalTaskSummary(run) {
41
+ if (run.tasks.length === 0)
42
+ return "no tasks";
43
+ const done = run.tasks.filter((item) => item.status === "done").length;
44
+ const running = run.tasks.filter((item) => item.status === "running" || item.status === "verifying").length;
45
+ const failed = run.tasks.filter((item) => item.status === "failed").length;
46
+ const blocked = run.tasks.filter((item) => item.status === "blocked").length;
47
+ const suffix = [
48
+ running > 0 ? `${running} running` : "",
49
+ failed > 0 ? `${failed} failed` : "",
50
+ blocked > 0 ? `${blocked} blocked` : "",
51
+ ]
52
+ .filter(Boolean)
53
+ .join(", ");
54
+ return `${done}/${run.tasks.length} tasks done${suffix ? ` (${suffix})` : ""}`;
55
+ }
56
+ export function formatGoalVerifierSummary(run) {
57
+ if (run.verifier?.lastResult)
58
+ return `verifier ${run.verifier.lastResult.status}`;
59
+ if (run.verifier?.command)
60
+ return "verifier command ready";
61
+ if (run.verifier?.description)
62
+ return "verifier described";
63
+ return "no verifier";
64
+ }
65
+ export function getGoalReadinessText(run) {
66
+ if (goalHasBlockingPrerequisites(run))
67
+ return "needs user input";
68
+ if (run.status === "running" || run.status === "verifying")
69
+ return "work in progress";
70
+ if (run.status === "passed")
71
+ return "verified";
72
+ if (run.verifier?.command)
73
+ return "ready to verify";
74
+ if (run.tasks.length > 0)
75
+ return "ready to run";
76
+ return "drafting plan";
77
+ }
78
+ export function formatGoalProgressText(run) {
79
+ const prereqTotal = run.prerequisites.length;
80
+ const prereqMet = run.prerequisites.filter((item) => item.status === "met").length;
81
+ const taskTotal = run.tasks.length;
82
+ const taskDone = run.tasks.filter((item) => item.status === "done").length;
83
+ const prereq = prereqTotal > 0 ? `prereqs ${prereqMet}/${prereqTotal}` : "no prereqs";
84
+ const tasks = taskTotal > 0 ? `tasks ${taskDone}/${taskTotal}` : "no tasks";
85
+ return `${prereq} · ${tasks}`;
86
+ }
87
+ export function getGoalStatusCountsText(runs) {
88
+ const counts = summarizeGoalCountsFromRuns(runs);
89
+ return `${counts.passed} passed · ${counts.running} running · ${counts.pending} pending · ${counts.blocked} blocked`;
90
+ }
91
+ export function clampGoalScrollOffset(offset, itemCount, viewportRows) {
92
+ const visibleRows = Math.max(1, Math.floor(viewportRows));
93
+ const maxOffset = Math.max(0, itemCount - visibleRows);
94
+ if (!Number.isFinite(offset))
95
+ return 0;
96
+ return Math.min(Math.max(0, Math.floor(offset)), maxOffset);
97
+ }
98
+ export function getGoalOverlayViewportRows(terminalRows, reservedRows = 8) {
99
+ if (!Number.isFinite(terminalRows))
100
+ return 8;
101
+ return Math.max(4, Math.floor(terminalRows) - reservedRows);
102
+ }
103
+ export function getGoalScrollOffsetForSelection({ selectedIndex, currentOffset, itemCount, viewportRows, }) {
104
+ const selected = clampGoalSelectedIndex(selectedIndex, itemCount);
105
+ const offset = clampGoalScrollOffset(currentOffset, itemCount, viewportRows);
106
+ const rows = Math.max(1, Math.floor(viewportRows));
107
+ if (selected < offset)
108
+ return selected;
109
+ if (selected >= offset + rows)
110
+ return clampGoalScrollOffset(selected - rows + 1, itemCount, rows);
111
+ return offset;
112
+ }
113
+ export function getGoalDetailRowCount(run) {
114
+ let count = 2;
115
+ count += 1 + Math.max(1, run.successCriteria.length);
116
+ if (run.prerequisites.length > 0) {
117
+ count += 1;
118
+ for (const prerequisite of run.prerequisites) {
119
+ count += 1;
120
+ if (isBlockingGoalPrerequisite(prerequisite) || prerequisite.evidence)
121
+ count += 1;
122
+ }
123
+ }
124
+ count += 1;
125
+ if (run.tasks.length === 0) {
126
+ count += 1;
127
+ }
128
+ else {
129
+ for (const task of run.tasks) {
130
+ count += 1;
131
+ if (task.lastSummary)
132
+ count += 1;
133
+ }
134
+ }
135
+ if (run.harness.length > 0)
136
+ count += 1 + run.harness.length;
137
+ if (run.evidencePlan.length > 0)
138
+ count += 1 + run.evidencePlan.length;
139
+ if (run.verifier)
140
+ count += 2;
141
+ if (run.blockers.length > 0)
142
+ count += 1 + run.blockers.length;
143
+ if (run.evidence.length > 0)
144
+ count += 1 + Math.min(5, run.evidence.length);
145
+ return count;
146
+ }
147
+ export function getGoalCardExtraRowCount(run) {
148
+ let count = 0;
149
+ if (goalHasBlockingPrerequisites(run))
150
+ count += 1;
151
+ else if (run.status === "running" || run.status === "verifying")
152
+ count += 1;
153
+ if (run.blockers.length > 0)
154
+ count += 1;
155
+ return count;
156
+ }
157
+ export function getGoalListCardRowCount({ run }) {
158
+ const compactCardRows = 1 + // title/status row
159
+ 2 + // compact summary rows
160
+ getGoalCardExtraRowCount(run);
161
+ const marginRows = 1;
162
+ return compactCardRows + marginRows;
163
+ }
164
+ function compareGoalListWindows({ candidate, current, selectedIndex, }) {
165
+ if (!current)
166
+ return candidate;
167
+ const candidateCount = candidate.end - candidate.start;
168
+ const currentCount = current.end - current.start;
169
+ if (candidateCount !== currentCount)
170
+ return candidateCount > currentCount ? candidate : current;
171
+ if (candidate.rowsUsed !== current.rowsUsed)
172
+ return candidate.rowsUsed > current.rowsUsed ? candidate : current;
173
+ const candidateBalance = Math.abs(selectedIndex - candidate.start - (candidate.end - selectedIndex - 1));
174
+ const currentBalance = Math.abs(selectedIndex - current.start - (current.end - selectedIndex - 1));
175
+ if (candidateBalance !== currentBalance)
176
+ return candidateBalance < currentBalance ? candidate : current;
177
+ return candidate.start > current.start ? candidate : current;
178
+ }
179
+ export function getGoalListWindow({ runs, selectedIndex, viewportRows, }) {
180
+ const rows = Number.isFinite(viewportRows) ? Math.max(1, Math.floor(viewportRows)) : 8;
181
+ const fixedRows = 1;
182
+ if (runs.length === 0) {
183
+ return { start: 0, end: 0, hiddenBefore: 0, hiddenAfter: 0, rowsUsed: fixedRows };
184
+ }
185
+ const selected = clampGoalSelectedIndex(selectedIndex, runs.length);
186
+ let best = null;
187
+ for (let start = 0; start <= selected; start++) {
188
+ let cardRows = 0;
189
+ for (let end = start + 1; end <= runs.length; end++) {
190
+ const index = end - 1;
191
+ const run = runs[index];
192
+ if (!run)
193
+ continue;
194
+ cardRows += getGoalListCardRowCount({ run });
195
+ if (end <= selected)
196
+ continue;
197
+ const hiddenBefore = start;
198
+ const hiddenAfter = runs.length - end;
199
+ const indicatorRows = (hiddenBefore > 0 ? 1 : 0) + (hiddenAfter > 0 ? 1 : 0);
200
+ const rowsUsed = fixedRows + indicatorRows + cardRows;
201
+ if (rowsUsed > rows)
202
+ continue;
203
+ best = compareGoalListWindows({
204
+ candidate: { start, end, hiddenBefore, hiddenAfter, rowsUsed },
205
+ current: best,
206
+ selectedIndex: selected,
207
+ });
208
+ }
209
+ }
210
+ if (best)
211
+ return best;
212
+ const start = selected;
213
+ const end = selected + 1;
214
+ const hiddenBefore = start;
215
+ const hiddenAfter = runs.length - end;
216
+ const indicatorRows = (hiddenBefore > 0 ? 1 : 0) + (hiddenAfter > 0 ? 1 : 0);
217
+ const run = runs[selected];
218
+ const cardRows = run ? getGoalListCardRowCount({ run }) : 0;
219
+ return {
220
+ start,
221
+ end,
222
+ hiddenBefore,
223
+ hiddenAfter,
224
+ rowsUsed: fixedRows + indicatorRows + cardRows,
225
+ };
226
+ }
227
+ export function getGoalExpandedDetailViewportRows({ viewportRows, cardExtraRows, }) {
228
+ const rows = Number.isFinite(viewportRows) ? Math.max(1, Math.floor(viewportRows)) : 8;
229
+ const selectedCardRows = 1 + Math.max(0, Math.floor(cardExtraRows));
230
+ const fixedRows = 1 + // Goals heading
231
+ selectedCardRows +
232
+ 2 + // selected card border
233
+ 1 + // detail top margin
234
+ 1; // selected card bottom margin
235
+ return Math.max(1, rows - fixedRows);
236
+ }
237
+ export function clampGoalDetailScrollOffset(offset, detailRowCount, viewportRows) {
238
+ const visibleRows = Math.max(1, Math.floor(viewportRows));
239
+ const scrolledBodyRows = Math.max(1, visibleRows - 1);
240
+ const maxOffset = Math.max(0, detailRowCount - scrolledBodyRows);
241
+ if (!Number.isFinite(offset))
242
+ return 0;
243
+ return Math.min(Math.max(0, Math.floor(offset)), maxOffset);
244
+ }
245
+ export function getGoalDetailScrollWindow({ detailRowCount, scrollOffset, viewportRows, }) {
246
+ const rows = Math.max(1, Math.floor(viewportRows));
247
+ const start = clampGoalDetailScrollOffset(scrollOffset, detailRowCount, rows);
248
+ const topIndicatorRows = start > 0 && rows > 2 ? 1 : 0;
249
+ let bodyRows = Math.max(1, rows - topIndicatorRows);
250
+ let hiddenAfter = Math.max(0, detailRowCount - start - bodyRows);
251
+ if (hiddenAfter > 0 && bodyRows > 1) {
252
+ bodyRows -= 1;
253
+ hiddenAfter = Math.max(0, detailRowCount - start - bodyRows);
254
+ }
255
+ return {
256
+ start,
257
+ end: Math.min(detailRowCount, start + bodyRows),
258
+ hiddenBefore: start,
259
+ hiddenAfter,
260
+ };
261
+ }
262
+ export function sortGoalRunsForOverlay(runs) {
263
+ return [...runs].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
264
+ }
265
+ export function shouldPersistGoalOverlayRuns(previousRuns, nextRuns) {
266
+ if (nextRuns.length > 0)
267
+ return true;
268
+ if (previousRuns.length === 0)
269
+ return true;
270
+ return !previousRuns.some((run) => run.status === "running" ||
271
+ run.status === "verifying" ||
272
+ run.activeWorkerId !== undefined ||
273
+ run.tasks.some((task) => task.status === "running" || task.status === "verifying"));
274
+ }
275
+ function GoalGradientText({ text }) {
276
+ const chars = [];
277
+ let colorIdx = 0;
278
+ for (let i = 0; i < text.length; i++) {
279
+ const ch = text[i];
280
+ if (ch === " ") {
281
+ chars.push(ch);
282
+ }
283
+ else {
284
+ const color = GRADIENT[colorIdx % GRADIENT.length];
285
+ chars.push(_jsx(Text, { color: color, children: ch }, i));
286
+ colorIdx++;
287
+ }
288
+ }
289
+ return _jsx(Text, { children: chars });
290
+ }
291
+ function formatDisplayPath(cwd) {
292
+ const home = process.env.HOME ?? "";
293
+ return home && cwd.startsWith(home) ? `~${cwd.slice(home.length)}` : cwd;
294
+ }
295
+ function statusColor(status) {
296
+ switch (status) {
297
+ case "passed":
298
+ return GOAL_SUCCESS;
299
+ case "running":
300
+ case "verifying":
301
+ case "blocked":
302
+ return GOAL_ACTIVE;
303
+ case "failed":
304
+ return "red";
305
+ case "paused":
306
+ case "draft":
307
+ case "ready":
308
+ return "";
309
+ }
310
+ }
311
+ export function getGoalCardStatusColor({ status, selected, primaryColor, textColor, }) {
312
+ return statusColor(status) || (selected ? primaryColor : textColor);
313
+ }
314
+ export function getGoalCardTitleColor({ selected, primaryColor, textColor, }) {
315
+ return selected ? primaryColor : textColor;
316
+ }
317
+ function verifierSummaryColor(run, fallbackColor) {
318
+ if (run.verifier?.lastResult)
319
+ return verifierStatusColor(run.verifier.lastResult.status);
320
+ if (run.verifier?.command)
321
+ return "cyan";
322
+ if (run.verifier?.description)
323
+ return "magenta";
324
+ return fallbackColor;
325
+ }
326
+ function taskStatusColor(status) {
327
+ switch (status) {
328
+ case "done":
329
+ return "green";
330
+ case "failed":
331
+ return "red";
332
+ case "blocked":
333
+ return "yellow";
334
+ case "running":
335
+ case "verifying":
336
+ return "cyan";
337
+ case "pending":
338
+ return "blue";
339
+ }
340
+ }
341
+ function prerequisiteStatusColor(status) {
342
+ switch (status) {
343
+ case "met":
344
+ return "green";
345
+ case "missing":
346
+ return "yellow";
347
+ case "unknown":
348
+ return "cyan";
349
+ }
350
+ }
351
+ function evidencePlanStatusColor(status) {
352
+ switch (status) {
353
+ case "ready":
354
+ return "green";
355
+ case "blocked":
356
+ return "yellow";
357
+ case "planned":
358
+ return "cyan";
359
+ }
360
+ }
361
+ function verifierStatusColor(status) {
362
+ switch (status) {
363
+ case "pass":
364
+ return "green";
365
+ case "fail":
366
+ return "red";
367
+ case "unknown":
368
+ return "yellow";
369
+ }
370
+ }
371
+ function evidenceKindColor(kind) {
372
+ switch (kind) {
373
+ case "command":
374
+ return "cyan";
375
+ case "file":
376
+ return "blue";
377
+ case "log":
378
+ return "yellow";
379
+ case "screenshot":
380
+ return "magenta";
381
+ case "summary":
382
+ return "green";
383
+ }
384
+ }
385
+ export function getGoalDetailTaskHeading(run) {
386
+ return run.prerequisites.length > 0 ? "2. Worker tasks" : "Worker tasks";
387
+ }
388
+ export function getGoalUserPrerequisiteHeading(run) {
389
+ return run.prerequisites.length > 0 ? "1. User prerequisites" : null;
390
+ }
391
+ export function formatGoalTaskDetailSummary(summary) {
392
+ const firstLine = summary
393
+ .split("\n")
394
+ .map((line) => line.trim())
395
+ .find((line) => line.length > 0);
396
+ if (!firstLine)
397
+ return "";
398
+ return firstLine.length > 180 ? `${firstLine.slice(0, 177)}…` : firstLine;
399
+ }
400
+ function truncateGoalDetailText(text, maxLength = 220) {
401
+ const collapsed = text.replace(/\s+/g, " ").trim();
402
+ return collapsed.length > maxLength ? `${collapsed.slice(0, maxLength - 1)}…` : collapsed;
403
+ }
404
+ function GoalHeader({ cwd, runs, agentRunning, }) {
405
+ const theme = useTheme();
406
+ const { columns } = useTerminalSize();
407
+ const displayPath = formatDisplayPath(cwd);
408
+ const counts = summarizeGoalCountsFromRuns(runs);
409
+ if (columns < SIDE_BY_SIDE_MIN) {
410
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, width: columns, children: [_jsx(GoalGradientText, { text: GOAL_LOGO[0] }), _jsx(GoalGradientText, { text: GOAL_LOGO[1] }), _jsx(GoalGradientText, { text: GOAL_LOGO[2] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: GOAL_SUCCESS, bold: true, children: "Goal Pane" }), agentRunning && _jsx(Text, { color: GOAL_ACTIVE, children: " (agent running)" }), _jsxs(Text, { color: theme.textDim, children: [" \u00B7 ", basename(cwd)] })] }), _jsx(Text, { color: theme.textDim, wrap: "truncate", children: displayPath }), _jsxs(Text, { children: [_jsxs(Text, { color: GOAL_SUCCESS, children: [counts.passed, " passed"] }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsxs(Text, { color: GOAL_ACTIVE, children: [counts.running, " active"] }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsxs(Text, { color: theme.text, children: [counts.pending, " pending"] }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsxs(Text, { color: GOAL_ACTIVE, children: [counts.blocked, " blocked"] })] })] }));
411
+ }
412
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, width: columns, children: [_jsxs(Box, { children: [_jsx(GoalGradientText, { text: GOAL_LOGO[0] }), _jsx(Text, { children: GAP }), _jsx(Text, { color: GOAL_SUCCESS, bold: true, children: "Goal Pane" }), agentRunning && _jsx(Text, { color: GOAL_ACTIVE, children: " (agent running)" })] }), _jsxs(Box, { children: [_jsx(GoalGradientText, { text: GOAL_LOGO[1] }), _jsx(Text, { children: GAP }), _jsx(Text, { color: theme.textDim, wrap: "truncate", children: displayPath })] }), _jsxs(Box, { children: [_jsx(GoalGradientText, { text: GOAL_LOGO[2] }), _jsx(Text, { children: GAP }), _jsxs(Text, { children: [_jsxs(Text, { color: GOAL_SUCCESS, children: [counts.passed, " passed"] }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsxs(Text, { color: GOAL_ACTIVE, children: [counts.running, " active"] }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsxs(Text, { color: theme.text, children: [counts.pending, " pending"] }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsxs(Text, { color: GOAL_ACTIVE, children: [counts.blocked, " blocked"] })] })] })] }));
413
+ }
414
+ function StatusChip({ label, color }) {
415
+ return (_jsxs(Text, { color: color, bold: true, children: ["\u25D6 ", label, " \u25D7"] }));
416
+ }
417
+ function GoalDetail({ run, maxRows, scrollOffset, }) {
418
+ const theme = useTheme();
419
+ const rows = [
420
+ _jsxs(Text, { children: [_jsx(Text, { color: theme.primary, bold: true, children: "Goal" }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsx(Text, { color: statusColor(run.status) || theme.secondary, children: getGoalReadinessText(run) }), _jsxs(Text, { color: theme.textDim, children: [" \u00B7 ", formatGoalProgressText(run)] })] }, "goal-heading"),
421
+ _jsx(Text, { color: theme.text, children: truncateGoalDetailText(run.goal || run.title) }, "goal-text"),
422
+ _jsx(Text, { color: theme.primary, bold: true, children: "Success criteria" }, "success-heading"),
423
+ ];
424
+ if (run.successCriteria.length === 0) {
425
+ rows.push(_jsx(Text, { color: theme.textDim, children: "- none recorded" }, "success-none"));
426
+ }
427
+ else {
428
+ for (const [index, criterion] of run.successCriteria.entries()) {
429
+ rows.push(_jsxs(Text, { children: [_jsx(Text, { color: "green", children: "\u2713 " }), _jsx(Text, { color: theme.text, children: truncateGoalDetailText(criterion) })] }, `success-${index}`));
430
+ }
431
+ }
432
+ if (run.prerequisites.length > 0) {
433
+ rows.push(_jsx(Text, { color: theme.primary, bold: true, children: getGoalUserPrerequisiteHeading(run) }, "prereq-heading"));
434
+ for (const prerequisite of run.prerequisites) {
435
+ rows.push(_jsxs(Text, { children: [_jsxs(Text, { color: prerequisiteStatusColor(prerequisite.status), children: ["\u25CF ", prerequisite.status] }), _jsxs(Text, { color: theme.text, bold: isBlockingGoalPrerequisite(prerequisite), children: [" ", prerequisite.label] }), isBlockingGoalPrerequisite(prerequisite) ? (_jsx(Text, { color: theme.warning, children: " \u00B7 user action required" })) : null] }, `prereq-${prerequisite.id}`));
436
+ if (isBlockingGoalPrerequisite(prerequisite)) {
437
+ rows.push(_jsxs(Text, { color: theme.textDim, wrap: "truncate", children: ["\u2514\u2500 ", formatGoalPrerequisiteInstruction(prerequisite)] }, `prereq-${prerequisite.id}-instruction`));
438
+ }
439
+ else if (prerequisite.evidence) {
440
+ rows.push(_jsxs(Text, { color: theme.textDim, wrap: "truncate", children: ["\u2514\u2500 ", prerequisite.evidence] }, `prereq-${prerequisite.id}-evidence`));
441
+ }
442
+ }
443
+ }
444
+ rows.push(_jsx(Text, { color: theme.primary, bold: true, children: getGoalDetailTaskHeading(run) }, "task-heading"));
445
+ if (run.tasks.length === 0) {
446
+ rows.push(_jsx(Text, { color: theme.textDim, children: goalHasBlockingPrerequisites(run)
447
+ ? "⏸ Waiting for prerequisites before workers can start."
448
+ : "✨ No worker tasks yet — run the goal to generate focused work." }, "no-tasks"));
449
+ }
450
+ else {
451
+ for (const task of run.tasks) {
452
+ rows.push(_jsxs(Text, { children: [_jsxs(Text, { color: taskStatusColor(task.status), children: ["\u25CF ", task.status] }), _jsxs(Text, { color: theme.text, children: [" ", task.title] }), _jsxs(Text, { color: theme.textDim, children: [" \u00B7 try ", task.attempts] }), task.workerId ? _jsxs(Text, { color: theme.textDim, children: [" \u00B7 ", task.workerId] }) : null] }, `task-${task.id}`));
453
+ if (task.lastSummary) {
454
+ rows.push(_jsxs(Text, { color: theme.textDim, wrap: "truncate", children: ["\u2514\u2500 ", formatGoalTaskDetailSummary(task.lastSummary)] }, `task-${task.id}-summary`));
455
+ }
456
+ }
457
+ }
458
+ if (run.harness.length > 0) {
459
+ rows.push(_jsx(Text, { color: theme.primary, bold: true, children: "Harness" }, "harness-heading"));
460
+ for (const item of run.harness) {
461
+ rows.push(_jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "\u25E6 " }), _jsx(Text, { color: theme.text, children: item.label }), item.command ? _jsxs(Text, { color: theme.secondary, children: [" \u00B7 ", item.command] }) : null, !item.command && item.path ? _jsxs(Text, { color: theme.secondary, children: [" \u00B7 ", item.path] }) : null] }, `harness-${item.id}`));
462
+ }
463
+ }
464
+ if (run.evidencePlan.length > 0) {
465
+ rows.push(_jsx(Text, { color: theme.primary, bold: true, children: "Evidence plan" }, "evidence-plan-heading"));
466
+ for (const item of run.evidencePlan) {
467
+ rows.push(_jsxs(Text, { children: [_jsxs(Text, { color: evidencePlanStatusColor(item.status), children: ["\u25CF ", item.status] }), _jsxs(Text, { color: theme.text, children: [" \u00B7 ", item.label] }), item.command ? _jsxs(Text, { color: theme.secondary, children: [" \u00B7 ", item.command] }) : null, !item.command && item.path ? _jsxs(Text, { color: theme.secondary, children: [" \u00B7 ", item.path] }) : null] }, `evidence-plan-${item.id}`));
468
+ }
469
+ }
470
+ if (run.verifier) {
471
+ rows.push(_jsx(Text, { color: theme.primary, bold: true, children: "Verifier" }, "verifier-heading"), _jsxs(Text, { wrap: "truncate", children: [run.verifier.lastResult ? (_jsxs(Text, { color: verifierStatusColor(run.verifier.lastResult.status), children: ["\u25CF ", formatGoalVerifierSummary(run)] })) : (_jsxs(Text, { color: run.verifier.command ? "cyan" : theme.textDim, children: ["\u25CF ", formatGoalVerifierSummary(run)] })), run.verifier.command ? (_jsxs(Text, { color: theme.secondary, children: [" \u00B7 ", run.verifier.command] })) : null] }, "verifier-summary"));
472
+ }
473
+ if (run.blockers.length > 0) {
474
+ rows.push(_jsx(Text, { color: theme.warning, bold: true, children: "Blockers" }, "blockers-heading"));
475
+ for (const [index, blocker] of run.blockers.entries()) {
476
+ rows.push(_jsxs(Text, { color: theme.warning, children: ["- ", truncateGoalDetailText(blocker)] }, `blocker-${index}`));
477
+ }
478
+ }
479
+ if (run.evidence.length > 0) {
480
+ rows.push(_jsx(Text, { color: theme.primary, bold: true, children: "Recent evidence" }, "evidence-heading"));
481
+ for (const item of run.evidence.slice(-5)) {
482
+ rows.push(_jsxs(Text, { children: [_jsxs(Text, { color: evidenceKindColor(item.kind), children: ["[", item.kind, "]"] }), _jsxs(Text, { color: theme.text, children: [" ", item.label] }), item.path ? _jsxs(Text, { color: theme.secondary, children: [" \u00B7 ", item.path] }) : null] }, `evidence-${item.id}`));
483
+ }
484
+ }
485
+ const window = getGoalDetailScrollWindow({
486
+ detailRowCount: rows.length,
487
+ scrollOffset,
488
+ viewportRows: maxRows,
489
+ });
490
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, paddingLeft: 2, height: maxRows, overflowY: "hidden", children: [window.hiddenBefore > 0 ? (_jsxs(Text, { color: theme.secondary, children: ["\u2191 ", window.hiddenBefore, " detail row(s) above \u00B7 PgUp"] })) : null, rows.slice(window.start, window.end), window.hiddenAfter > 0 ? (_jsxs(Text, { color: theme.secondary, children: ["\u2193 ", window.hiddenAfter, " more detail row(s) \u00B7 PgDn"] })) : null] }));
491
+ }
492
+ export function GoalOverlay({ cwd, onClose, onRunGoal, onVerifyGoal, onPauseGoal, agentRunning, }) {
493
+ const theme = useTheme();
494
+ const [runs, setRuns] = useState([]);
495
+ const [selectedIndex, setSelectedIndex] = useState(0);
496
+ const [loaded, setLoaded] = useState(false);
497
+ const [expandedRunId, setExpandedRunId] = useState(null);
498
+ const [mode, setMode] = useState("normal");
499
+ const [status, setStatus] = useState("");
500
+ const [detailScrollOffset, setDetailScrollOffset] = useState(0);
501
+ const statusTimer = useRef(null);
502
+ const saveTimer = useRef(null);
503
+ const lastPersistedRunsRef = useRef([]);
504
+ const showStatus = useCallback((message) => {
505
+ setStatus(message);
506
+ if (statusTimer.current)
507
+ clearTimeout(statusTimer.current);
508
+ statusTimer.current = setTimeout(() => setStatus(""), 2500);
509
+ }, []);
510
+ useEffect(() => {
511
+ let cancelled = false;
512
+ const load = () => {
513
+ void loadGoalRuns(cwd).then((nextRuns) => {
514
+ if (cancelled)
515
+ return;
516
+ setRuns((previousRuns) => {
517
+ const sorted = sortGoalRunsForOverlay(nextRuns);
518
+ if (!shouldPersistGoalOverlayRuns(previousRuns, sorted)) {
519
+ showStatus("Goal store reload looked empty while work is active; preserving local state.");
520
+ return previousRuns;
521
+ }
522
+ return JSON.stringify(previousRuns) === JSON.stringify(sorted) ? previousRuns : sorted;
523
+ });
524
+ setLoaded(true);
525
+ });
526
+ };
527
+ load();
528
+ const interval = setInterval(load, 1000);
529
+ return () => {
530
+ cancelled = true;
531
+ clearInterval(interval);
532
+ if (statusTimer.current)
533
+ clearTimeout(statusTimer.current);
534
+ if (saveTimer.current)
535
+ clearTimeout(saveTimer.current);
536
+ };
537
+ }, [cwd]);
538
+ useEffect(() => {
539
+ setSelectedIndex((index) => clampGoalSelectedIndex(index, runs.length));
540
+ }, [runs.length]);
541
+ useEffect(() => {
542
+ if (!loaded)
543
+ return;
544
+ if (saveTimer.current)
545
+ clearTimeout(saveTimer.current);
546
+ saveTimer.current = setTimeout(() => {
547
+ if (!shouldPersistGoalOverlayRuns(lastPersistedRunsRef.current, runs)) {
548
+ showStatus("Refusing to save an empty Goal list while work is active.");
549
+ return;
550
+ }
551
+ lastPersistedRunsRef.current = runs;
552
+ void saveGoalRuns(cwd, runs);
553
+ }, 100);
554
+ }, [cwd, loaded, runs]);
555
+ const { rows } = useTerminalSize();
556
+ const viewportRows = getGoalOverlayViewportRows(rows);
557
+ const selectedRun = runs[selectedIndex];
558
+ const expandedRun = selectedRun && selectedRun.id === expandedRunId ? selectedRun : null;
559
+ const selectedCardExtraRows = selectedRun ? getGoalCardExtraRowCount(selectedRun) : 0;
560
+ const expandedCardExtraRows = expandedRun ? selectedCardExtraRows : 0;
561
+ const detailViewportRows = expandedRun
562
+ ? getGoalExpandedDetailViewportRows({
563
+ viewportRows,
564
+ cardExtraRows: expandedCardExtraRows,
565
+ })
566
+ : 0;
567
+ const listWindow = expandedRun
568
+ ? null
569
+ : getGoalListWindow({
570
+ runs,
571
+ selectedIndex,
572
+ viewportRows,
573
+ });
574
+ const scrollOffset = expandedRun ? selectedIndex : (listWindow?.start ?? 0);
575
+ const visibleRuns = expandedRun
576
+ ? [expandedRun]
577
+ : runs.slice(listWindow?.start ?? 0, listWindow?.end ?? 0);
578
+ const hiddenBefore = expandedRun ? 0 : (listWindow?.hiddenBefore ?? 0);
579
+ const hiddenAfter = expandedRun ? 0 : (listWindow?.hiddenAfter ?? 0);
580
+ const detailRowCount = expandedRun ? getGoalDetailRowCount(expandedRun) : 0;
581
+ useEffect(() => {
582
+ setDetailScrollOffset(0);
583
+ }, [expandedRunId]);
584
+ useEffect(() => {
585
+ setDetailScrollOffset((offset) => clampGoalDetailScrollOffset(offset, detailRowCount, detailViewportRows));
586
+ }, [detailRowCount, detailViewportRows]);
587
+ useInput((input, key) => {
588
+ if (mode === "confirmDelete") {
589
+ if (key.escape || input === "n") {
590
+ setMode("normal");
591
+ showStatus("Archive cancelled");
592
+ return;
593
+ }
594
+ if (input === "y" && selectedRun) {
595
+ setRuns((previousRuns) => previousRuns.filter((run) => run.id !== selectedRun.id));
596
+ setExpandedRunId(null);
597
+ setMode("normal");
598
+ showStatus("Goal archived");
599
+ }
600
+ return;
601
+ }
602
+ if (key.escape) {
603
+ onClose();
604
+ return;
605
+ }
606
+ if (expandedRun && (key.pageUp || input === "[")) {
607
+ setDetailScrollOffset((offset) => clampGoalDetailScrollOffset(offset - Math.max(1, detailViewportRows - 1), detailRowCount, detailViewportRows));
608
+ return;
609
+ }
610
+ if (expandedRun && (key.pageDown || input === "]")) {
611
+ setDetailScrollOffset((offset) => clampGoalDetailScrollOffset(offset + Math.max(1, detailViewportRows - 1), detailRowCount, detailViewportRows));
612
+ return;
613
+ }
614
+ if (expandedRun && key.home) {
615
+ setDetailScrollOffset(0);
616
+ return;
617
+ }
618
+ if (expandedRun && key.end) {
619
+ setDetailScrollOffset(clampGoalDetailScrollOffset(detailRowCount, detailRowCount, detailViewportRows));
620
+ return;
621
+ }
622
+ if (expandedRun && (key.upArrow || input === "k")) {
623
+ setDetailScrollOffset((offset) => clampGoalDetailScrollOffset(offset - 1, detailRowCount, detailViewportRows));
624
+ return;
625
+ }
626
+ if (expandedRun && (key.downArrow || input === "j")) {
627
+ setDetailScrollOffset((offset) => clampGoalDetailScrollOffset(offset + 1, detailRowCount, detailViewportRows));
628
+ return;
629
+ }
630
+ if (key.upArrow || input === "k") {
631
+ setSelectedIndex((index) => clampGoalSelectedIndex(index - 1, runs.length));
632
+ return;
633
+ }
634
+ if (key.downArrow || input === "j") {
635
+ setSelectedIndex((index) => clampGoalSelectedIndex(index + 1, runs.length));
636
+ return;
637
+ }
638
+ if ((key.return || input === "d") && selectedRun) {
639
+ setExpandedRunId((current) => (current === selectedRun.id ? null : selectedRun.id));
640
+ return;
641
+ }
642
+ if (input === "r" && selectedRun) {
643
+ onRunGoal(selectedRun);
644
+ return;
645
+ }
646
+ if (input === "v" && selectedRun) {
647
+ onVerifyGoal(selectedRun);
648
+ return;
649
+ }
650
+ if (input === "p" && selectedRun) {
651
+ onPauseGoal(selectedRun);
652
+ return;
653
+ }
654
+ if (input === "x" && selectedRun) {
655
+ setMode("confirmDelete");
656
+ showStatus("Archive goal? y/n");
657
+ }
658
+ });
659
+ return (_jsxs(Box, { flexDirection: "column", height: rows, overflow: "hidden", children: [_jsx(GoalHeader, { cwd: cwd, runs: runs, agentRunning: agentRunning }), agentRunning ? (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: theme.textDim, children: "Agent is running; Goal pane stays available without resetting chat." }) })) : null, !loaded ? (_jsx(Box, { borderStyle: "round", borderColor: theme.textDim, paddingX: 1, children: _jsx(Text, { color: theme.textDim, children: "Loading goals\u2026" }) })) : runs.length === 0 ? (_jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: theme.primary, paddingX: 1, paddingY: 1, children: [_jsx(Text, { color: theme.primary, bold: true, children: "Start a durable Goal run" }), _jsx(Text, { color: theme.textDim, children: "No goals yet. Ask the agent to start a durable Goal." }), _jsx(Text, { color: theme.textDim, children: "Prerequisites, worker tasks, evidence, and verifier results will appear in this pane." })] })) : (_jsxs(Box, { flexDirection: "column", height: viewportRows, overflowY: "hidden", children: [_jsx(Text, { color: theme.textDim, bold: true, children: "Goals" }), hiddenBefore > 0 ? (_jsxs(Text, { color: theme.textDim, children: ["\u2191 ", hiddenBefore, " earlier goal", hiddenBefore === 1 ? "" : "s"] })) : null, visibleRuns.map((run, visibleIndex) => {
660
+ const index = scrollOffset + visibleIndex;
661
+ const selected = index === selectedIndex;
662
+ const blocked = goalHasBlockingPrerequisites(run);
663
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, borderStyle: expandedRun?.id === run.id ? "round" : undefined, borderColor: expandedRun?.id === run.id ? theme.primary : undefined, paddingX: expandedRun?.id === run.id ? 1 : 0, children: [_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: selected ? theme.primary : theme.textDim, children: selected ? "❯ " : " " }), _jsx(StatusChip, { label: run.status, color: getGoalCardStatusColor({
664
+ status: run.status,
665
+ selected,
666
+ primaryColor: theme.primary,
667
+ textColor: theme.text,
668
+ }) }), _jsxs(Text, { color: getGoalCardTitleColor({
669
+ selected,
670
+ primaryColor: theme.primary,
671
+ textColor: theme.text,
672
+ }), bold: selected, children: [" ", run.title] }), _jsxs(Text, { color: theme.textDim, children: [" \u00B7 ", run.id.slice(0, 8)] })] }), expandedRun?.id === run.id ? null : (_jsxs(_Fragment, { children: [_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: theme.textDim, children: selected ? " " : " " }), _jsx(Text, { color: statusColor(run.status) || theme.secondary, children: getGoalReadinessText(run) }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsx(Text, { color: theme.text, children: formatGoalProgressText(run) }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsx(Text, { color: verifierSummaryColor(run, theme.textDim), children: formatGoalVerifierSummary(run) })] }), _jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: theme.textDim, children: selected ? " " : " " }), _jsx(Text, { color: goalHasBlockingPrerequisites(run) ? theme.warning : GOAL_SUCCESS, children: formatGoalPrerequisiteSummary(run) }), _jsx(Text, { color: theme.textDim, children: " \u00B7 " }), _jsx(Text, { color: run.tasks.length > 0 ? GOAL_SUCCESS : theme.text, children: formatGoalTaskSummary(run) })] })] })), blocked ? (_jsxs(Text, { color: theme.warning, wrap: "truncate", children: [selected ? " " : " ", "\u26A0 prerequisite needed before workers continue"] })) : run.status === "running" || run.status === "verifying" ? (_jsxs(Text, { color: GOAL_ACTIVE, wrap: "truncate", children: [selected ? " " : " ", "\u25CF active \u2014 watching worker/verifier progress"] })) : null, run.blockers.length > 0 ? (_jsxs(Text, { color: theme.warning, wrap: "truncate", children: [selected ? " " : " ", "blocker: ", run.blockers[0]] })) : null, expandedRun?.id === run.id ? (_jsx(GoalDetail, { run: run, maxRows: detailViewportRows, scrollOffset: detailScrollOffset })) : null] }, run.id));
673
+ }), hiddenAfter > 0 ? (_jsxs(Text, { color: theme.textDim, children: ["\u2193 ", hiddenAfter, " later goal", hiddenAfter === 1 ? "" : "s"] })) : null] })), _jsx(Box, { marginTop: 1, children: mode === "confirmDelete" ? (_jsx(Text, { color: theme.warning, children: "Confirm archive selected goal: y/n" })) : (_jsxs(Text, { color: theme.textDim, children: [_jsx(Text, { color: theme.primary, children: "\u2191\u2193/jk" }), expandedRun ? " scroll detail · " : " select · ", _jsx(Text, { color: theme.primary, children: "Enter/d" }), expandedRun ? " close detail · " : " detail · ", expandedRun ? (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.primary, children: "PgUp/PgDn" }), " page detail · "] })) : null, _jsx(Text, { color: theme.primary, children: "r" }), " run · ", _jsx(Text, { color: theme.primary, children: "v" }), " verify · ", _jsx(Text, { color: theme.primary, children: "p" }), " pause · ", _jsx(Text, { color: theme.primary, children: "x" }), " archive · ", _jsx(Text, { color: theme.primary, children: "Esc" }), " close"] })) }), status ? (_jsx(Box, { children: _jsx(Text, { color: theme.secondary, children: status }) })) : null] }));
674
+ }
675
+ //# sourceMappingURL=GoalOverlay.js.map