@bastani/atomic 0.8.21-0 → 0.8.22-0

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 (235) hide show
  1. package/CHANGELOG.md +46 -9
  2. package/dist/builtin/intercom/broker/broker.ts +3 -3
  3. package/dist/builtin/intercom/config.ts +3 -3
  4. package/dist/builtin/intercom/index.ts +1 -1
  5. package/dist/builtin/intercom/package.json +1 -1
  6. package/dist/builtin/intercom/ui/compose.ts +2 -2
  7. package/dist/builtin/mcp/host-html-template.ts +0 -3
  8. package/dist/builtin/mcp/package.json +1 -1
  9. package/dist/builtin/subagents/CHANGELOG.md +13 -4
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
  11. package/dist/builtin/subagents/agents/debugger.md +6 -6
  12. package/dist/builtin/subagents/package.json +1 -1
  13. package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
  14. package/dist/builtin/subagents/skills/browser-use/SKILL.md +234 -0
  15. package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +76 -0
  16. package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +92 -0
  17. package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
  18. package/dist/builtin/subagents/src/agents/skills.ts +19 -1
  19. package/dist/builtin/subagents/src/extension/index.ts +24 -22
  20. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +7 -1
  21. package/dist/builtin/subagents/src/runs/background/async-execution.ts +23 -7
  22. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +98 -3
  23. package/dist/builtin/subagents/src/runs/background/async-status.ts +3 -1
  24. package/dist/builtin/subagents/src/runs/background/run-status.ts +1 -1
  25. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +3 -0
  26. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +37 -12
  27. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +15 -15
  28. package/dist/builtin/subagents/src/runs/foreground/execution.ts +26 -2
  29. package/dist/builtin/subagents/src/runs/shared/nested-render.ts +1 -1
  30. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +7 -0
  31. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +28 -1
  32. package/dist/builtin/subagents/src/shared/fast-mode.ts +80 -0
  33. package/dist/builtin/subagents/src/shared/formatters.ts +4 -2
  34. package/dist/builtin/subagents/src/shared/types.ts +4 -2
  35. package/dist/builtin/subagents/src/shared/utils.ts +3 -61
  36. package/dist/builtin/subagents/src/tui/render.ts +303 -157
  37. package/dist/builtin/web-access/package.json +1 -1
  38. package/dist/builtin/workflows/CHANGELOG.md +101 -35
  39. package/dist/builtin/workflows/README.md +228 -41
  40. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +535 -541
  41. package/dist/builtin/workflows/builtin/goal.ts +39 -25
  42. package/dist/builtin/workflows/builtin/open-claude-design.ts +66 -69
  43. package/dist/builtin/workflows/builtin/ralph.ts +21 -21
  44. package/dist/builtin/workflows/package.json +6 -5
  45. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
  46. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +2 -2
  47. package/dist/builtin/workflows/src/extension/discovery.ts +25 -146
  48. package/dist/builtin/workflows/src/extension/dispatcher.ts +72 -24
  49. package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +363 -0
  50. package/dist/builtin/workflows/src/extension/index.ts +690 -352
  51. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +99 -62
  52. package/dist/builtin/workflows/src/extension/render-call.ts +2 -1
  53. package/dist/builtin/workflows/src/extension/render-result.ts +9 -3
  54. package/dist/builtin/workflows/src/extension/renderers.ts +5 -3
  55. package/dist/builtin/workflows/src/extension/runtime.ts +68 -33
  56. package/dist/builtin/workflows/src/extension/status-writer.ts +1 -1
  57. package/dist/builtin/workflows/src/extension/wiring.ts +34 -13
  58. package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +142 -0
  59. package/dist/builtin/workflows/src/extension/workflow-schema.ts +4 -4
  60. package/dist/builtin/workflows/src/index.ts +2 -0
  61. package/dist/builtin/workflows/src/intercom/result-intercom.ts +1 -1
  62. package/dist/builtin/workflows/src/runs/background/runner.ts +6 -4
  63. package/dist/builtin/workflows/src/runs/background/status.ts +45 -21
  64. package/dist/builtin/workflows/src/runs/foreground/executor.ts +624 -52
  65. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +1 -1
  66. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +80 -24
  67. package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +61 -24
  68. package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +32 -10
  69. package/dist/builtin/workflows/src/sdk-surface.ts +6 -0
  70. package/dist/builtin/workflows/src/shared/expanded-workflow-graph.ts +178 -0
  71. package/dist/builtin/workflows/src/shared/persistence-restore.ts +92 -12
  72. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +21 -3
  73. package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +1 -2
  74. package/dist/builtin/workflows/src/shared/run-visibility.ts +9 -0
  75. package/dist/builtin/workflows/src/shared/schema-introspection.ts +121 -0
  76. package/dist/builtin/workflows/src/shared/serializable.ts +132 -0
  77. package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +91 -9
  78. package/dist/builtin/workflows/src/shared/store-types.ts +31 -3
  79. package/dist/builtin/workflows/src/shared/store.ts +58 -14
  80. package/dist/builtin/workflows/src/shared/types.ts +105 -40
  81. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +129 -13
  82. package/dist/builtin/workflows/src/tui/chat-surface.ts +6 -1
  83. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +3 -2
  84. package/dist/builtin/workflows/src/tui/graph-canvas.ts +1 -1
  85. package/dist/builtin/workflows/src/tui/graph-view.ts +91 -65
  86. package/dist/builtin/workflows/src/tui/inline-form-card.ts +1 -1
  87. package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +3 -2
  88. package/dist/builtin/workflows/src/tui/inputs-overlay.ts +3 -2
  89. package/dist/builtin/workflows/src/tui/inputs-picker.ts +8 -7
  90. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +2 -0
  91. package/dist/builtin/workflows/src/tui/node-card.ts +34 -8
  92. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -11
  93. package/dist/builtin/workflows/src/tui/prompt-card.ts +98 -50
  94. package/dist/builtin/workflows/src/tui/session-list.ts +7 -2
  95. package/dist/builtin/workflows/src/tui/session-picker.ts +2 -0
  96. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +226 -55
  97. package/dist/builtin/workflows/src/tui/status-helpers.ts +2 -0
  98. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +37 -158
  99. package/dist/builtin/workflows/src/tui/toast.ts +2 -2
  100. package/dist/builtin/workflows/src/tui/widget.ts +53 -12
  101. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +270 -19
  102. package/dist/builtin/workflows/src/tui/workflow-notice-card.ts +184 -0
  103. package/dist/builtin/workflows/src/workflows/define-workflow.ts +138 -43
  104. package/dist/config.d.ts +9 -0
  105. package/dist/config.d.ts.map +1 -1
  106. package/dist/config.js +45 -0
  107. package/dist/config.js.map +1 -1
  108. package/dist/core/agent-session.d.ts +27 -9
  109. package/dist/core/agent-session.d.ts.map +1 -1
  110. package/dist/core/agent-session.js +196 -17
  111. package/dist/core/agent-session.js.map +1 -1
  112. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  113. package/dist/core/atomic-guide-command.js +2 -2
  114. package/dist/core/atomic-guide-command.js.map +1 -1
  115. package/dist/core/codex-fast-mode.d.ts +36 -0
  116. package/dist/core/codex-fast-mode.d.ts.map +1 -0
  117. package/dist/core/codex-fast-mode.js +117 -0
  118. package/dist/core/codex-fast-mode.js.map +1 -0
  119. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  120. package/dist/core/compaction/branch-summarization.js +1 -1
  121. package/dist/core/compaction/branch-summarization.js.map +1 -1
  122. package/dist/core/compaction/compaction.d.ts.map +1 -1
  123. package/dist/core/compaction/compaction.js +1 -1
  124. package/dist/core/compaction/compaction.js.map +1 -1
  125. package/dist/core/extensions/index.d.ts +4 -1
  126. package/dist/core/extensions/index.d.ts.map +1 -1
  127. package/dist/core/extensions/index.js +1 -0
  128. package/dist/core/extensions/index.js.map +1 -1
  129. package/dist/core/extensions/loader.d.ts +7 -2
  130. package/dist/core/extensions/loader.d.ts.map +1 -1
  131. package/dist/core/extensions/loader.js +23 -8
  132. package/dist/core/extensions/loader.js.map +1 -1
  133. package/dist/core/extensions/reactive-widget.d.ts +58 -0
  134. package/dist/core/extensions/reactive-widget.d.ts.map +1 -0
  135. package/dist/core/extensions/reactive-widget.js +182 -0
  136. package/dist/core/extensions/reactive-widget.js.map +1 -0
  137. package/dist/core/extensions/runner.d.ts.map +1 -1
  138. package/dist/core/extensions/runner.js +1 -0
  139. package/dist/core/extensions/runner.js.map +1 -1
  140. package/dist/core/extensions/types.d.ts +26 -12
  141. package/dist/core/extensions/types.d.ts.map +1 -1
  142. package/dist/core/extensions/types.js.map +1 -1
  143. package/dist/core/messages.d.ts +1 -1
  144. package/dist/core/messages.d.ts.map +1 -1
  145. package/dist/core/messages.js +8 -2
  146. package/dist/core/messages.js.map +1 -1
  147. package/dist/core/model-registry.d.ts +4 -0
  148. package/dist/core/model-registry.d.ts.map +1 -1
  149. package/dist/core/model-registry.js +11 -0
  150. package/dist/core/model-registry.js.map +1 -1
  151. package/dist/core/resource-loader.d.ts +9 -1
  152. package/dist/core/resource-loader.d.ts.map +1 -1
  153. package/dist/core/resource-loader.js +49 -21
  154. package/dist/core/resource-loader.js.map +1 -1
  155. package/dist/core/sdk.d.ts.map +1 -1
  156. package/dist/core/sdk.js +22 -13
  157. package/dist/core/sdk.js.map +1 -1
  158. package/dist/core/session-manager.d.ts +7 -5
  159. package/dist/core/session-manager.d.ts.map +1 -1
  160. package/dist/core/session-manager.js +5 -3
  161. package/dist/core/session-manager.js.map +1 -1
  162. package/dist/core/settings-manager.d.ts +16 -0
  163. package/dist/core/settings-manager.d.ts.map +1 -1
  164. package/dist/core/settings-manager.js +64 -5
  165. package/dist/core/settings-manager.js.map +1 -1
  166. package/dist/core/slash-commands.d.ts.map +1 -1
  167. package/dist/core/slash-commands.js +1 -0
  168. package/dist/core/slash-commands.js.map +1 -1
  169. package/dist/core/system-prompt.d.ts.map +1 -1
  170. package/dist/core/system-prompt.js +7 -4
  171. package/dist/core/system-prompt.js.map +1 -1
  172. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  173. package/dist/core/tools/ask-user-question/ask-user-question.js +2 -2
  174. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  175. package/dist/index.d.ts +4 -3
  176. package/dist/index.d.ts.map +1 -1
  177. package/dist/index.js +3 -2
  178. package/dist/index.js.map +1 -1
  179. package/dist/main.d.ts +3 -0
  180. package/dist/main.d.ts.map +1 -1
  181. package/dist/main.js +12 -0
  182. package/dist/main.js.map +1 -1
  183. package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -1
  184. package/dist/modes/interactive/chat-input-actions.js.map +1 -1
  185. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/diff.js +0 -1
  187. package/dist/modes/interactive/components/diff.js.map +1 -1
  188. package/dist/modes/interactive/components/fast-mode-selector.d.ts +27 -0
  189. package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -0
  190. package/dist/modes/interactive/components/fast-mode-selector.js +105 -0
  191. package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -0
  192. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/footer.js +7 -12
  194. package/dist/modes/interactive/components/footer.js.map +1 -1
  195. package/dist/modes/interactive/components/index.d.ts +1 -0
  196. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  197. package/dist/modes/interactive/components/index.js +1 -0
  198. package/dist/modes/interactive/components/index.js.map +1 -1
  199. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  200. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  201. package/dist/modes/interactive/interactive-mode.js +132 -30
  202. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  203. package/dist/modes/print-mode.d.ts.map +1 -1
  204. package/dist/modes/print-mode.js +53 -6
  205. package/dist/modes/print-mode.js.map +1 -1
  206. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  207. package/dist/modes/rpc/rpc-mode.js +3 -0
  208. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  209. package/docs/compaction.md +1 -1
  210. package/docs/custom-provider.md +2 -2
  211. package/docs/development.md +2 -2
  212. package/docs/docs.json +2 -2
  213. package/docs/extensions.md +18 -13
  214. package/docs/providers.md +5 -1
  215. package/docs/quickstart.md +5 -3
  216. package/docs/rpc.md +5 -5
  217. package/docs/sdk.md +12 -12
  218. package/docs/settings.md +18 -0
  219. package/docs/themes.md +6 -6
  220. package/docs/tui.md +20 -18
  221. package/docs/usage.md +2 -0
  222. package/docs/workflows.md +403 -39
  223. package/examples/extensions/qna.ts +2 -2
  224. package/package.json +4 -4
  225. package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +0 -392
  226. package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +0 -23
  227. package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +0 -39
  228. package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +0 -87
  229. package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +0 -241
  230. package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +0 -225
  231. package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +0 -305
  232. package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +0 -275
  233. package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +0 -134
  234. package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +0 -139
  235. package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +0 -143
@@ -16,7 +16,7 @@
16
16
  * │ │ <text input / choice cycler> │ │
17
17
  * │ ╰───────────────────────────────────────╯ │
18
18
  * │ │
19
- * │ ↵ submit · esc skip
19
+ * │ ↵ submit · ctrl+c skip
20
20
  * ╰───────────────────────────────────────────────╯
21
21
  *
22
22
  * cross-ref:
@@ -110,15 +110,22 @@ export function handlePromptCardInput(
110
110
  state: PromptCardState,
111
111
  keybindings?: KeybindingsLike,
112
112
  ): PromptCardAction {
113
- if (matchesKey(data, Key.ctrl("c")) || matchesKey(data, Key.escape)) {
113
+ if (matchesKey(data, Key.ctrl("c"))) {
114
114
  return { kind: "cancel" };
115
115
  }
116
+ // The Escape key shares its leading byte with arrow/navigation sequences in
117
+ // terminal raw mode. Treat Escape as a consumed no-op for prompt cards so a
118
+ // split prefix can never resolve a prompt to its default response; Ctrl+C is
119
+ // the explicit skip/default key for this surface.
120
+ if (isPromptEscapeInput(data)) {
121
+ return { kind: "noop" };
122
+ }
116
123
 
117
124
  switch (state.prompt.kind) {
118
125
  case "confirm":
119
126
  return handleConfirm(data, state);
120
127
  case "select":
121
- return handleSelect(data, state);
128
+ return handleSelect(data, state, keybindings);
122
129
  case "input":
123
130
  return handleInput(data, state, keybindings);
124
131
  case "editor":
@@ -126,18 +133,22 @@ export function handlePromptCardInput(
126
133
  }
127
134
  }
128
135
 
136
+ export function isPromptEscapeInput(data: string): boolean {
137
+ return matchesKey(data, Key.escape);
138
+ }
139
+
129
140
  function handleConfirm(
130
141
  data: string,
131
142
  state: PromptCardState,
132
143
  ): PromptCardAction {
133
- if (matchesKey(data, Key.left) || matchesKey(data, Key.right) || matchesKey(data, Key.space) || matchesKey(data, Key.tab)) {
144
+ if (matchesAnyKey(data, [Key.left, Key.right, Key.space, Key.tab])) {
134
145
  state.confirmValue = !state.confirmValue;
135
146
  return { kind: "noop" };
136
147
  }
137
- if (matchesKey(data, "y") || matchesKey(data, Key.shift("y"))) {
148
+ if (matchesAnyKey(data, ["y", Key.shift("y")])) {
138
149
  return { kind: "submit", response: true };
139
150
  }
140
- if (matchesKey(data, "n") || matchesKey(data, Key.shift("n"))) {
151
+ if (matchesAnyKey(data, ["n", Key.shift("n")])) {
141
152
  return { kind: "submit", response: false };
142
153
  }
143
154
  if (matchesKey(data, Key.enter)) {
@@ -146,23 +157,29 @@ function handleConfirm(
146
157
  return { kind: "noop" };
147
158
  }
148
159
 
149
- function handleSelect(data: string, state: PromptCardState): PromptCardAction {
160
+ function handleSelect(
161
+ data: string,
162
+ state: PromptCardState,
163
+ keybindings: KeybindingsLike | undefined,
164
+ ): PromptCardAction {
150
165
  const choices = state.prompt.choices ?? [];
151
166
  if (choices.length === 0) {
152
- if (matchesKey(data, Key.enter)) {
167
+ if (matchesSelectSubmit(data, keybindings)) {
153
168
  return { kind: "submit", response: "" };
154
169
  }
155
170
  return { kind: "noop" };
156
171
  }
157
172
 
158
- let action: PromptCardAction = { kind: "noop" };
159
- const list = createPromptSelectList(state);
160
- list.onSelect = (item) => {
161
- const idx = Number(item.value);
162
- action = { kind: "submit", response: choices[idx] ?? choices[0] };
163
- };
164
- list.handleInput(normalizeSelectKeyData(data));
165
- return action;
173
+ state.selectedIndex = normalizeSelectIndex(state.selectedIndex, choices.length);
174
+ const movement = selectMovementDelta(data, keybindings, choices.length);
175
+ if (movement !== 0) {
176
+ state.selectedIndex = normalizeSelectIndex(state.selectedIndex + movement, choices.length);
177
+ return { kind: "noop" };
178
+ }
179
+ if (matchesSelectSubmit(data, keybindings)) {
180
+ return { kind: "submit", response: choices[state.selectedIndex] ?? choices[0] };
181
+ }
182
+ return { kind: "noop" };
166
183
  }
167
184
 
168
185
  function handleInput(
@@ -249,47 +266,30 @@ function applyTextEdit(
249
266
  return { kind: "noop" };
250
267
  }
251
268
  if (matchesAction(keybindings, data, "tui.editor.deleteWordBackward")) {
252
- const start = wordLeft(state.rawText, caret);
253
- const result = deleteRange(state.rawText, start, caret, caret);
254
- state.rawText = result.text;
255
- state.caret = result.caret;
269
+ applyDeleteRange(state, wordLeft(state.rawText, caret), caret, caret);
256
270
  return { kind: "noop" };
257
271
  }
258
272
  if (matchesAction(keybindings, data, "tui.editor.deleteWordForward")) {
259
- const end = wordRight(state.rawText, caret);
260
- const result = deleteRange(state.rawText, caret, end, caret);
261
- state.rawText = result.text;
262
- state.caret = result.caret;
273
+ applyDeleteRange(state, caret, wordRight(state.rawText, caret), caret);
263
274
  return { kind: "noop" };
264
275
  }
265
276
  if (matchesAction(keybindings, data, "tui.editor.deleteToLineStart")) {
266
- const start = lineStart(state.rawText, caret);
267
- const result = deleteRange(state.rawText, start, caret, caret);
268
- state.rawText = result.text;
269
- state.caret = result.caret;
277
+ applyDeleteRange(state, lineStart(state.rawText, caret), caret, caret);
270
278
  return { kind: "noop" };
271
279
  }
272
280
  if (matchesAction(keybindings, data, "tui.editor.deleteToLineEnd")) {
273
- const end = lineEnd(state.rawText, caret);
274
- const result = deleteRange(state.rawText, caret, end, caret);
275
- state.rawText = result.text;
276
- state.caret = result.caret;
281
+ applyDeleteRange(state, caret, lineEnd(state.rawText, caret), caret);
277
282
  return { kind: "noop" };
278
283
  }
279
284
  if (matchesTextAction(keybindings, data, "tui.editor.deleteCharBackward", Key.backspace)) {
280
285
  if (caret > 0) {
281
- const prev = previousGraphemeBoundary(state.rawText, caret);
282
- const result = deleteRange(state.rawText, prev, caret, caret);
283
- state.rawText = result.text;
284
- state.caret = result.caret;
286
+ applyDeleteRange(state, previousGraphemeBoundary(state.rawText, caret), caret, caret);
285
287
  }
286
288
  return { kind: "noop" };
287
289
  }
288
290
  if (matchesAction(keybindings, data, "tui.editor.deleteCharForward")) {
289
291
  if (caret < state.rawText.length) {
290
- const result = deleteRange(state.rawText, caret, nextGraphemeBoundary(state.rawText, caret), caret);
291
- state.rawText = result.text;
292
- state.caret = result.caret;
292
+ applyDeleteRange(state, caret, nextGraphemeBoundary(state.rawText, caret), caret);
293
293
  }
294
294
  return { kind: "noop" };
295
295
  }
@@ -372,6 +372,19 @@ function matchesTextAction(
372
372
  return matchesAction(keybindings, data, action) || (fallback !== undefined && matchesKey(data, fallback));
373
373
  }
374
374
 
375
+ function matchesAnyKey(
376
+ data: string,
377
+ keys: readonly Parameters<typeof matchesKey>[1][],
378
+ ): boolean {
379
+ return keys.some((key) => matchesKey(data, key));
380
+ }
381
+
382
+ function applyDeleteRange(state: PromptCardState, start: number, end: number, caret: number): void {
383
+ const result = deleteRange(state.rawText, start, end, caret);
384
+ state.rawText = result.text;
385
+ state.caret = result.caret;
386
+ }
387
+
375
388
  function visualColumnAt(text: string, caret: number): number {
376
389
  return visibleWidth(text.slice(0, clampGraphemeBoundary(text, caret)));
377
390
  }
@@ -487,13 +500,48 @@ function normalizeSelectIndex(index: number, length: number): number {
487
500
  return ((n % length) + length) % length;
488
501
  }
489
502
 
490
- function normalizeSelectKeyData(data: string): string {
491
- // The historical prompt card accepted left/right as select aliases; feed the
492
- // corresponding vertical key into pi-tui's SelectList so it owns the actual
493
- // wrap/clamp/selection update behavior.
494
- if (matchesKey(data, Key.right)) return "\x1b[B";
495
- if (matchesKey(data, Key.left)) return "\x1b[A";
496
- return data;
503
+ const SELECT_PAGE_STEP = 5;
504
+
505
+ function selectMovementDelta(
506
+ data: string,
507
+ keybindings: KeybindingsLike | undefined,
508
+ choiceCount: number,
509
+ ): number {
510
+ if (
511
+ matchesAction(keybindings, data, TUI_ACTION.selectUp) ||
512
+ matchesKey(data, Key.up) ||
513
+ matchesKey(data, Key.left)
514
+ ) {
515
+ return -1;
516
+ }
517
+ if (
518
+ matchesAction(keybindings, data, TUI_ACTION.selectDown) ||
519
+ matchesKey(data, Key.down) ||
520
+ matchesKey(data, Key.right)
521
+ ) {
522
+ return 1;
523
+ }
524
+ const pageStep = Math.max(1, Math.min(SELECT_PAGE_STEP, choiceCount));
525
+ if (
526
+ matchesAction(keybindings, data, TUI_ACTION.selectPageUp) ||
527
+ matchesKey(data, "pageUp")
528
+ ) {
529
+ return -pageStep;
530
+ }
531
+ if (
532
+ matchesAction(keybindings, data, TUI_ACTION.selectPageDown) ||
533
+ matchesKey(data, "pageDown")
534
+ ) {
535
+ return pageStep;
536
+ }
537
+ return 0;
538
+ }
539
+
540
+ function matchesSelectSubmit(
541
+ data: string,
542
+ keybindings: KeybindingsLike | undefined,
543
+ ): boolean {
544
+ return matchesAction(keybindings, data, TUI_ACTION.selectConfirm) || matchesKey(data, Key.enter);
497
545
  }
498
546
 
499
547
  // ---------------------------------------------------------------------------
@@ -833,7 +881,7 @@ function renderHints(kind: PendingPrompt["kind"], theme: GraphTheme): string {
833
881
  sep +
834
882
  graphKeyHint("tui.input.submit", "Newline/Submit", theme) +
835
883
  sep +
836
- graphKeyHint("tui.select.cancel", "Skip", theme)
884
+ graphRawKeyHint("ctrl+c", "Skip", theme)
837
885
  );
838
886
  }
839
887
  if (kind === "confirm") {
@@ -844,7 +892,7 @@ function renderHints(kind: PendingPrompt["kind"], theme: GraphTheme): string {
844
892
  sep +
845
893
  graphKeyHint("tui.select.confirm", "Submit", theme) +
846
894
  sep +
847
- graphKeyHint("tui.select.cancel", "Skip", theme)
895
+ graphRawKeyHint("ctrl+c", "Skip", theme)
848
896
  );
849
897
  }
850
898
  if (kind === "select") {
@@ -853,8 +901,8 @@ function renderHints(kind: PendingPrompt["kind"], theme: GraphTheme): string {
853
901
  sep +
854
902
  graphKeyHint("tui.select.confirm", "Submit", theme) +
855
903
  sep +
856
- graphKeyHint("tui.select.cancel", "Skip", theme)
904
+ graphRawKeyHint("ctrl+c", "Skip", theme)
857
905
  );
858
906
  }
859
- return graphKeyHint("tui.input.submit", "Submit", theme) + sep + graphKeyHint("tui.select.cancel", "Skip", theme);
907
+ return graphKeyHint("tui.input.submit", "Submit", theme) + sep + graphRawKeyHint("ctrl+c", "Skip", theme);
860
908
  }
@@ -9,7 +9,8 @@
9
9
  * - src/tui/session-picker.ts selectRunsForPicker — same bucketing
10
10
  */
11
11
 
12
- import type { RunSnapshot } from "../shared/store-types.js";
12
+ import type { RunSnapshot, StoreSnapshot } from "../shared/store-types.js";
13
+ import { expandWorkflowGraph } from "../shared/expanded-workflow-graph.js";
13
14
  import type { GraphTheme } from "./graph-theme.js";
14
15
  import { renderStatusList } from "./status-list.js";
15
16
  import { selectRunsForPicker } from "./session-picker.js";
@@ -27,6 +28,10 @@ export function renderSessionList(
27
28
  ): string {
28
29
  const now = opts.now ?? Date.now();
29
30
  const rows = selectRunsForPicker(runs, "", opts.includeAll, now);
30
- const filtered = rows.map((row) => row.run);
31
+ const snapshot: StoreSnapshot = { runs, notices: [], version: 0 };
32
+ const filtered = rows.map((row) => ({
33
+ ...row.run,
34
+ stages: expandWorkflowGraph(snapshot, row.run.id).stages.map((stage) => structuredClone(stage)),
35
+ }));
31
36
  return renderStatusList(filtered, { theme: opts.theme, now });
32
37
  }
@@ -19,6 +19,7 @@
19
19
  */
20
20
 
21
21
  import type { RunSnapshot } from "../shared/store-types.js";
22
+ import { isTopLevelWorkflowRun } from "../shared/run-visibility.js";
22
23
  import { elapsedRunMs } from "../shared/timing.js";
23
24
  import type { GraphTheme } from "./graph-theme.js";
24
25
  import { keyText } from "@bastani/atomic";
@@ -79,6 +80,7 @@ export function selectRunsForPicker(
79
80
  const active: PickerRow[] = [];
80
81
  const terminal: PickerRow[] = [];
81
82
  for (const r of runs) {
83
+ if (!isTopLevelWorkflowRun(r)) continue;
82
84
  if (!matches(r)) continue;
83
85
 
84
86
  const endedAt = r.endedAt;