@sma1lboy/rove 0.8.89

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 (82) hide show
  1. package/README.md +60 -0
  2. package/dist/cli/index.js +959 -0
  3. package/dist/cli/kobe.js +959 -0
  4. package/dist/cli/pty-host-node.mjs +1015 -0
  5. package/dist/cli/rove.js +959 -0
  6. package/dist/pulse-n3cq1btw.wav +0 -0
  7. package/dist/skills/kobe/SKILL.md +317 -0
  8. package/dist/web-ui/assets/AppShell-BTjvuY-t.js +5 -0
  9. package/dist/web-ui/assets/AppShell-HiyATJse.css +1 -0
  10. package/dist/web-ui/assets/Board-DPB4h6mJ.js +1 -0
  11. package/dist/web-ui/assets/BoardPeek-69VJptGV.js +2 -0
  12. package/dist/web-ui/assets/ChatTerminal-BrP-ENHg.css +1 -0
  13. package/dist/web-ui/assets/ChatTerminal-MCI1aBbT.js +144 -0
  14. package/dist/web-ui/assets/ChatTranscript-DLthbnmB.js +1 -0
  15. package/dist/web-ui/assets/ConfirmDialog-CDPOtXww.js +1 -0
  16. package/dist/web-ui/assets/IssueIntakePanel-XYsIcIhp.js +1 -0
  17. package/dist/web-ui/assets/IssuePeek-CP_rAkqO.js +1 -0
  18. package/dist/web-ui/assets/IssuesPage-BR5mpuo-.js +1 -0
  19. package/dist/web-ui/assets/RichEditor-B4sEOPyN.css +1 -0
  20. package/dist/web-ui/assets/RichEditor-DJFl5TvH.js +173 -0
  21. package/dist/web-ui/assets/SettingsPage-CLRhr-sg.js +2 -0
  22. package/dist/web-ui/assets/SlideOver-Dxtk6Gn2.js +1 -0
  23. package/dist/web-ui/assets/ViewToggle-BdPCMBWa.js +1 -0
  24. package/dist/web-ui/assets/WorkspaceTabs-CMKlvN_Y.js +3 -0
  25. package/dist/web-ui/assets/WorkspaceTabs-DLzL-Tad.css +1 -0
  26. package/dist/web-ui/assets/active-task-GeQZqbJK.js +1 -0
  27. package/dist/web-ui/assets/activity-BjTd1D8q.js +1 -0
  28. package/dist/web-ui/assets/arrow-left-DNM2CHhS.js +1 -0
  29. package/dist/web-ui/assets/board-CGiK0u0M.js +1 -0
  30. package/dist/web-ui/assets/chips-Da37C4KZ.js +1 -0
  31. package/dist/web-ui/assets/columns-3-CQGAnX-4.js +1 -0
  32. package/dist/web-ui/assets/createLucideIcon-CM5xLVj1.js +1 -0
  33. package/dist/web-ui/assets/desktop-BThq9eSR.js +2 -0
  34. package/dist/web-ui/assets/engines-Cnxy1hW9.js +1 -0
  35. package/dist/web-ui/assets/external-link-BwT2u1hD.js +1 -0
  36. package/dist/web-ui/assets/external-store-DJlWpyYC.js +1 -0
  37. package/dist/web-ui/assets/harness-q9gT7Jic.js +1 -0
  38. package/dist/web-ui/assets/index-CgL6oDIY.js +10 -0
  39. package/dist/web-ui/assets/index-MuA3NLRu.css +1 -0
  40. package/dist/web-ui/assets/issues-1SCRkcB0.js +4 -0
  41. package/dist/web-ui/assets/issues-BKkua1D9.js +1 -0
  42. package/dist/web-ui/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  43. package/dist/web-ui/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  44. package/dist/web-ui/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  45. package/dist/web-ui/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  46. package/dist/web-ui/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
  47. package/dist/web-ui/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
  48. package/dist/web-ui/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
  49. package/dist/web-ui/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
  50. package/dist/web-ui/assets/lazy-issue-panels-0Rhl2uhh.js +6 -0
  51. package/dist/web-ui/assets/plus-BbX5qXba.js +1 -0
  52. package/dist/web-ui/assets/react-dom-DCnDkJvp.js +1 -0
  53. package/dist/web-ui/assets/rotate-cw-D-UUtiD0.js +1 -0
  54. package/dist/web-ui/assets/routes-SBb-uSy8.js +1 -0
  55. package/dist/web-ui/assets/search-BxbFZoup.js +1 -0
  56. package/dist/web-ui/assets/settings-tPcmEHCP.js +1 -0
  57. package/dist/web-ui/assets/store-uT65Mask.js +2 -0
  58. package/dist/web-ui/assets/tabs-Dx-TnbvG.js +1 -0
  59. package/dist/web-ui/assets/task._taskId-BlZ0vG_1.js +2 -0
  60. package/dist/web-ui/assets/task._taskId-BmObFoVZ.js +1 -0
  61. package/dist/web-ui/assets/terminal-qBEkzc-m.js +1 -0
  62. package/dist/web-ui/assets/text-match-DW3sD-Rt.js +1 -0
  63. package/dist/web-ui/assets/time-kviT26Tm.js +1 -0
  64. package/dist/web-ui/assets/toast-BXjAT0ix.js +1 -0
  65. package/dist/web-ui/assets/triage-7QLsCY8d.js +1 -0
  66. package/dist/web-ui/assets/use-focus-trap-DNMrlNR0.js +1 -0
  67. package/dist/web-ui/assets/vendor-CdtpTJrf.js +1 -0
  68. package/dist/web-ui/assets/web-transport-D0bugxxv.js +1 -0
  69. package/dist/web-ui/assets/with-selector-B5R3h-Ow.js +1 -0
  70. package/dist/web-ui/assets/worktrees-C_XKA7jM.js +1 -0
  71. package/dist/web-ui/assets/x-7cB9X7Hi.js +1 -0
  72. package/dist/web-ui/favicon.ico +0 -0
  73. package/dist/web-ui/index.html +35 -0
  74. package/dist/web-ui/logo192.png +0 -0
  75. package/dist/web-ui/logo512.png +0 -0
  76. package/dist/web-ui/manifest.json +25 -0
  77. package/dist/web-ui/origin-policy.mjs +41 -0
  78. package/dist/web-ui/pty-scrollback.mjs +51 -0
  79. package/dist/web-ui/pty-server.mjs +212 -0
  80. package/dist/web-ui/pty-session-lifecycle.mjs +282 -0
  81. package/dist/web-ui/robots.txt +3 -0
  82. package/package.json +94 -0
Binary file
@@ -0,0 +1,317 @@
1
+ ---
2
+ name: kobe
3
+ description: Use when controlling Rove tasks, parallel coding attempts, hosted agent sessions, task lifecycle, or the daemon-owned issue tracker from a shell. Also the ONLY channel for messaging another agent session on this machine — `rove api send`, never a peer/MCP side channel.
4
+ ---
5
+
6
+ <!-- kobe-skill-version: 21 — bump in lockstep with KOBE_SKILL_VERSION (src/lib/skill-install.ts). -->
7
+
8
+ # Rove shell control
9
+
10
+ Use `rove api` to manage local coding tasks. Each Task owns a git Worktree,
11
+ branch, and Hosted PTY engine sessions. API automation works without an open
12
+ TUI; prompted `send`, `add`, and `fan-out` ensure the canonical engine session.
13
+
14
+ ## Inside a Rove session, Rove verbs come first
15
+
16
+ Check where you are before choosing how to delegate or parallelize:
17
+
18
+ ```bash
19
+ test -n "${KOBE_TASK_ID:-}"
20
+ ```
21
+
22
+ When that passes, you are an engine session Rove manages — `$KOBE_TASK_ID`
23
+ is your task, `$KOBE_TAB_ID` your tab. Coordination should then go through
24
+ Rove, not around it, because work routed through `rove api` gets what
25
+ ad-hoc subprocesses never do: its own Worktree and branch (no file
26
+ collisions with you), a sidebar row with live state the user can watch,
27
+ lifecycle tracking, and an explicit outcome contract.
28
+
29
+ - Parallel attempts of one prompt → `fan-out`, not N hand-rolled subagents.
30
+ - Delegating a scoped piece of work → `add --prompt`, not a raw `claude -p`
31
+ child the user cannot see or manage.
32
+ - Following up on a task you started → `send`; comparing → `collect`;
33
+ finished your own task and were spawned by another → a bare `send`
34
+ (no `--task-id`) replies to the DISPATCHER — the exact task + tab that
35
+ created you, recorded at creation (`.task.dispatcher` on `get-task`).
36
+ If that tab died it falls back to the dispatcher task's live canonical
37
+ engine tab; nothing alive fails loud (`DISPATCHER_UNREACHABLE`) — it
38
+ never spawns a new engine, so a failed reply is visible, not fake-ok.
39
+ - Messaging another agent session on this machine → `send`, and ONLY `send`
40
+ — never relay through the user, a side file, or a generic peer channel
41
+ (an MCP server offering to message "other instances" is exactly that
42
+ channel: it reaches a process, not a task, so nothing it delivers is
43
+ attributable, watchable, or replyable). Sent from
44
+ inside a Rove task, the prompt arrives prefixed `[KOBE PEER] from
45
+ "<title>" (task <id> — load the Rove agent skill FIRST …)`, so the
46
+ receiver knows who is talking, that this skill is required reading, and
47
+ how to answer — the baked-in reply command is tab-precise
48
+ (`--task-id <sender> --tab <sender's tab>`), so peer conversations need
49
+ no coordinator and no human relay. That prefix is the contract: do not
50
+ strip it with `--plain` for
51
+ coordination messages (`--plain` is only for a verbatim paste the
52
+ receiver should treat as content, not conversation). Received a
53
+ `[KOBE PEER]` message yourself? Load this skill first — required, not
54
+ optional — then reply with the baked-in command, not by asking the user.
55
+ - `dispatch` stays the dispatcher's verb (deliver-only into an
56
+ already-hosted session; never impersonate the user in someone else's
57
+ terminal).
58
+
59
+ Your own engine's in-context subagents remain fine for read-only
60
+ research/exploration inside your task — the boundary is WORK: anything that
61
+ edits files, runs long, or the user should be able to see and steer belongs
62
+ in a Rove task. Do not recursively fan out from a spawned task.
63
+
64
+ When the check fails, none of this applies — use `rove api` only if the
65
+ user asks for Rove by name.
66
+
67
+ ## Vocabulary — what the user's words map to
68
+
69
+ | Term | What it is | Isolation it gives | Users also say |
70
+ |---|---|---|---|
71
+ | **Task** | one Worktree + branch + the Terminal Tabs inside it — one sidebar row | its own files AND its own branch | "a task", "a new one", "a separate attempt" |
72
+ | **Worktree** | that task's file tree on disk (`.task.worktreePath`) | — | "workspace", "this checkout", "this branch", "here" |
73
+ | **Terminal Tab** | one engine session inside a task | its own conversation, SAME files | "tab", "chattab", "another chat", "a second agent on this" |
74
+ | **Split** | the tree that divides ONE Terminal Tab into several regions (the `pane-open` verb's unit; a leaf is not called a pane) | none — same session's screen, same files | "split it", "side by side", "put the logs next to it" |
75
+
76
+ Two of those colloquialisms are traps, so read them as INTENT, not as
77
+ product terms: in Rove's own vocabulary **Workspace** is the center Terminal
78
+ Tab region of the UI (CONTEXT.md), not a checkout, and **ChatTab** is
79
+ retired vocabulary for Terminal Tab. A user saying "in this workspace" means
80
+ the worktree they are looking at — answer the intent, keep writing the real
81
+ term.
82
+
83
+ They nest — **Task ⊃ Terminal Tab ⊃ Split** — and isolation drops at every
84
+ level down:
85
+
86
+ ```text
87
+ new Task → own worktree + own branch (parallel work can't collide)
88
+ new Tab → own engine session, SAME files (a helper in the same checkout)
89
+ new Split → same session's screen, one tab divided (a monitor beside the work)
90
+ ```
91
+
92
+ The distinction that decides every routing call: **a new tab shares the
93
+ worktree and branch; only a new task gets its own.** Two tabs in one task
94
+ edit the same files, so they can collide — that is a feature when the user
95
+ wants a helper in the same checkout, and a bug when they wanted parallel
96
+ attempts. A split isolates nothing at all: it is a layout, for watching
97
+ something (logs, `btop`, a test loop) next to the work — never the answer to
98
+ "do this work".
99
+
100
+ ### Where does this work land?
101
+
102
+ Inside a Rove session (`$KOBE_TASK_ID` non-empty — check first: it is what
103
+ makes the tab/split rows addressable at all), match top to bottom and take
104
+ the first row that fits:
105
+
106
+ | The user says | Lands in | Command |
107
+ |---|---|---|
108
+ | "you do it", "just fix it", "change X to Y" | you, right here | no Rove verb — edit the files yourself |
109
+ | "try it N ways", "compare approaches" | N new tasks | `rove api fan-out --repo "$PWD" --count N --prompt "…"` |
110
+ | "split", "side by side", "keep an eye on X while…" | a new region in the CURRENT tab | `rove api pane-open --command "…"` |
111
+ | names a tab: "tell the agent in tab 3" | that exact tab | `rove api send --task-id <id> --tab tab-3 --prompt "…"` |
112
+ | a LOCATION word: "in this workspace/worktree/checkout", "on this branch", "here", "same task" | THIS task, a NEW Terminal Tab | `rove api send --task-id "$KOBE_TASK_ID" --tab new --prompt "…"` |
113
+ | names an ENGINE for the same files: "let codex take over here", "try this one with claude instead" | THIS task, a new tab pinned to that engine | `rove api send --task-id "$KOBE_TASK_ID" --tab new --vendor codex --prompt "…"` |
114
+ | **anything else — no row above matched** | a NEW task — new worktree + branch | `rove api add --repo "$PWD" --prompt "…"` |
115
+
116
+ Order is the tiebreak: a count ("3 ways in this workspace") beats a location
117
+ word, and delegation language loses to "you do it" — the user asking YOU is
118
+ not asking for a fleet. Two more rules the table can't show:
119
+
120
+ - No location word at all ⇒ new task. It is the only routing whose isolation
121
+ cannot corrupt work-in-progress, so it is the safe default.
122
+ - "this repo" / "this project" are NOT location words — they name the repo,
123
+ not the checkout. Only worktree-scoped words route to a tab.
124
+
125
+ Outside a Rove session none of this applies: there is no "this task" to add
126
+ a tab to, so `add` / `fan-out` are the only routings available.
127
+
128
+ ### Know where you are before you route
129
+
130
+ ```bash
131
+ echo "$KOBE_TASK_ID / $KOBE_TAB_ID" # who you are (empty = not a Rove session)
132
+ rove api get-task --task-id "$KOBE_TASK_ID" # .task.worktreePath, .task.branch, .running, .tabs[]
133
+ ```
134
+
135
+ `get-task` is the per-task read that answers "what is my worktree, my
136
+ branch, and which sibling tabs exist" — `.tabs[]` carries each tab's `id`, `kind`,
137
+ `vendor`, `lastTitle` and `alive`, which is exactly the target list for
138
+ `send --tab`. A tab flagged `unregistered: true` is a live session the tab
139
+ snapshot lost; it is addressable like any other.
140
+
141
+ ## Discover before calling
142
+
143
+ ```bash
144
+ rove api schema
145
+ rove api schema --verb add
146
+ rove api schema --group create
147
+ rove api <verb> --help
148
+ ```
149
+
150
+ Do not guess flags. Commands emit one JSON object; errors use
151
+ `{"error":{"message","code",...}}` on stderr. Common rejections also carry
152
+ `hint` (what to do) and `nextCommandArgs` (argv for the same `Rove`
153
+ executable — run `rove <args...>` verbatim to recover, e.g. `["api","list"]`
154
+ after `TASK_NOT_FOUND`). Add `--pretty` for readable output.
155
+
156
+ ## Common operations
157
+
158
+ ```bash
159
+ # Create one task and start its first engine turn.
160
+ rove api add --repo "$PWD" --title "focused title" --vendor claude \
161
+ --prompt "<complete scoped instruction>"
162
+
163
+ # Parallel attempts of the same prompt (hard cap 10; prefer 3-4).
164
+ rove api fan-out --repo "$PWD" --count 3 --prompt "<prompt>"
165
+ rove api fan-out --repo "$PWD" --agents claude:2,codex:1 --prompt "<prompt>"
166
+
167
+ # Follow up. Use an explicit id for unattended work; the active task can drift.
168
+ # From inside a Rove task this auto-prefixes [KOBE PEER] provenance
169
+ # (sender + reply command); --plain sends verbatim.
170
+ rove api send --task-id <id> --prompt "<complete next turn>"
171
+
172
+ # Reply home: no --task-id inside a dispatched task = the dispatcher's tab.
173
+ rove api send --prompt "succeeded: <one line> (branch <final branch>)"
174
+
175
+ # A task can hold several Terminal Tabs. `get-task` lists ONE task's tabs (the
176
+ # usual read before addressing one); `inspect` is the wider diagnostic — every
177
+ # task's snapshot plus daemon activity and live pty sessions.
178
+ rove api inspect --task-id <id>
179
+ rove api send --task-id <id> --tab tab-3 --prompt "<turn>" # exact alive tab
180
+ rove api send --task-id <id> --tab new --prompt "<turn>" # fresh engine tab
181
+ # Same worktree, DIFFERENT agent — the API twin of the TUI's ctrl+e pick. The
182
+ # engine is pinned to that tab (survives restarts, unaffected by a later
183
+ # set-vendor) and the task's own vendor is left alone. --tab new only.
184
+ rove api send --task-id <id> --tab new --vendor codex --prompt "<turn>"
185
+
186
+ rove api get-task --task-id <id>
187
+ rove api collect --task-ids <id1>,<id2>,<id3> --pretty
188
+ rove api list --pretty
189
+ ```
190
+
191
+ `.running` means the task's canonical Hosted PTY engine session is alive.
192
+ Omitting BOTH `--task-id` and `--tab` inside a task that has a dispatcher
193
+ targets that dispatcher's tab (see the reply rule above); otherwise the
194
+ target is the active task. Omitting only `--tab` targets a live engine tab
195
+ (`tab-1` first, then any surviving engine tab). Only when the task has NO live session at all does `send`
196
+ auto-start the canonical engine in the task's worktree (`started: true` in
197
+ the result marks that fresh session). If live tabs exist but none resolves
198
+ as an engine, it refuses with `NO_ENGINE_TAB` — address one with `--tab
199
+ tab-N` or spawn one with `--tab new`; it never silently spawns a duplicate
200
+ engine.
201
+
202
+ ## Terminal panes
203
+
204
+ Split the workspace terminal the user is watching (tmux-style) or open a
205
+ separate command tab — the attached TUI performs it, so this is a no-op
206
+ headless:
207
+
208
+ ```bash
209
+ # Split the focused tab; the pane runs the command via `sh -lc` and
210
+ # closes when it exits. Omit --command for an interactive shell.
211
+ rove api pane-open --command "btop"
212
+ rove api pane-open --direction down --command "watch -n1 git status -sb"
213
+ rove api pane-open --placement tab --title logs --command "tail -f app.log"
214
+
215
+ # Close panes you opened, by their --title (engine panes are never closed).
216
+ rove api pane-close --title logs
217
+
218
+ # Toast a one-liner in every attached Rove UI — surface "done / needs input /
219
+ # error" moments without touching any session (kinds get severity styling).
220
+ rove api notify --title "build green, artifacts in dist/" --kind done
221
+ ```
222
+
223
+ Defaults: the caller's own task (`$KOBE_TASK_ID`, then the active task),
224
+ `--placement split`, `--direction right`. Alternate right/down to build a
225
+ grid; screen size bounds splitting — a split that would shrink any pane
226
+ below the minimum usable size (20×6 cells) falls back to a tab.
227
+ Panes land in the USER'S live workspace — open them when asked (monitors,
228
+ logs, dashboards), don't scatter panes for work `add`/`fan-out` should own.
229
+
230
+ ## Lifecycle
231
+
232
+ | Verb | Purpose |
233
+ |---|---|
234
+ | `rename --task-id ID --title T` | Rename a task |
235
+ | `set-branch --task-id ID --branch B` | Rename its branch |
236
+ | `set-vendor --task-id ID --vendor V` | Change engine for the next launch |
237
+ | `set-status --task-id ID --status S` | Set lifecycle status |
238
+ | `archive --task-id ID [--archived=false]` | Archive/unarchive; stops live sessions |
239
+ | `pin --task-id ID [--pinned=false]` | Pin/unpin |
240
+ | `set-active --task-id ID` / `--none` | Change shared active task |
241
+ | `ensure-worktree --task-id ID` | Materialize without starting an engine |
242
+ | `land --task-id ID [--strategy merge\|squash] [--delete-branch] [--then-archive] [--remove-worktree]` | Merge the task's branch into the base repo's current branch; `--remove-worktree` cleans up the Worktree after (branch stays; dirty/self/base refused, outcome in the result's `worktree` field) |
243
+ | `delete --task-id ID [--force]` | Destructive task + Worktree removal |
244
+ | `discover-adoptable --repo PATH` | Find untracked Worktrees |
245
+ | `adopt --repo PATH --worktree PATH` | Import a Worktree |
246
+
247
+ Prefer `archive` unless the user explicitly authorizes deletion.
248
+
249
+ ## Issue tracker
250
+
251
+ Issues are daemon-owned, not repo files:
252
+
253
+ ```bash
254
+ rove api issue-list --repo "$PWD" --pretty
255
+ rove api issue-create --repo "$PWD" --title "title" --body "context"
256
+ rove api issue-set-status --repo "$PWD" --id <n> --status done
257
+ rove api issue-update --repo "$PWD" --id <n> --title "new" --body "body"
258
+ rove api issue-update --repo "$PWD" --id <n> --task <taskId> # link; `--task none` unlinks
259
+ ```
260
+
261
+ ### Kanban semantics
262
+
263
+ The TUI and web render issues as a Backlog / In progress / Done board whose
264
+ columns derive from the issue's own lifecycle — do NOT move cards with
265
+ `issue-set-status doing`:
266
+
267
+ - **In progress** = the issue has a linked task; `issue-update --task <taskId>`
268
+ IS the move (typical flow: `issue-create` → `add` a task → link them).
269
+ - **Done** = `status done`; the daemon mirrors it automatically when the
270
+ linked task finishes.
271
+ - **Backlog** = everything else (`open`/`doing`/`hold`, unlinked).
272
+
273
+ ## Fan-out rules
274
+
275
+ Fan out only when the user requests parallel approaches, comparison, or an
276
+ explicit count. Give each task a scoped prompt, report returned IDs, then use
277
+ `collect` to compare. Do not recursively fan out from spawned tasks. Do not
278
+ poll `send` in a tight loop or use it as casual chat; every call is a full
279
+ engine turn.
280
+
281
+ ### Completion flows back through chat (`send`)
282
+
283
+ Outcomes are explicit, never inferred — and they travel as a MESSAGE to the
284
+ spawning agent's chat tab, not as stored state nobody reads.
285
+
286
+ **Worker side** — a task created from inside another Rove task records its
287
+ dispatcher (the creating task + tab); when the work is finished, a bare
288
+ `rove api send --prompt "<succeeded|failed>: <one line> (branch <final
289
+ branch>)"` routes the outcome back to that exact tab. Include the final
290
+ branch name — the spawner needs it to `land`. The first-prompt coda still
291
+ names the spawner for an explicit `--task-id` send.
292
+
293
+ **Coordinator side** — do NOT block or poll. Keep working (or end your
294
+ turn); each worker's outcome arrives in your chat as a `[KOBE PEER]` message
295
+ with its task id. What arrives is the worker's claim, not Rove-verified —
296
+ verify the winner's actual diff before landing. Silence never proves a
297
+ worker died (it may be mid-turn or stuck on a permission prompt): peek with
298
+ `collect`/`get-task`, nudge with `send`, and never mark a silent task failed
299
+ or auto-retry it.
300
+
301
+ ### Closing a round
302
+
303
+ After comparing attempts, finish the round instead of leaving tasks behind:
304
+
305
+ ```bash
306
+ # Land the winner: merge its branch into the base repo's CURRENT branch.
307
+ # Verify the base checkout is on the intended branch first.
308
+ rove api land --task-id <winner> --then-archive
309
+
310
+ # Archive the losers (non-destructive; branches survive).
311
+ rove api archive --task-id <loser1>
312
+ rove api archive --task-id <loser2>
313
+ ```
314
+
315
+ `land` refuses a dirty base checkout; on merge conflict it aborts cleanly and
316
+ returns the conflicted files for manual resolution. Only `delete` destroys a
317
+ Worktree — never use it on a loser without explicit user authorization.
@@ -0,0 +1,5 @@
1
+ import{l as e,o as t}from"./terminal-qBEkzc-m.js";import{_ as n,f as r,l as i,r as a,y as o}from"./tabs-Dx-TnbvG.js";import{d as s,t as c}from"./createLucideIcon-CM5xLVj1.js";import{a as l,n as u,r as d}from"./toast-BXjAT0ix.js";import{n as f,t as p}from"./ViewToggle-BdPCMBWa.js";import{n as m,t as h}from"./store-uT65Mask.js";import{n as g,t as _}from"./active-task-GeQZqbJK.js";import{t as v}from"./external-store-DJlWpyYC.js";import{c as y,d as b,i as x,l as S,p as C,r as w,t as T,u as E}from"./triage-7QLsCY8d.js";import{i as D,r as O,t as k}from"./WorkspaceTabs-CMKlvN_Y.js";import{t as A}from"./SettingsPage-CLRhr-sg.js";import{t as j}from"./ChatTranscript-DLthbnmB.js";import{t as ee}from"./plus-BbX5qXba.js";import{t as te}from"./search-BxbFZoup.js";import{t as ne}from"./x-7cB9X7Hi.js";import{n as M,t as N}from"./activity-BjTd1D8q.js";import{t as P}from"./use-focus-trap-DNMrlNR0.js";import{t as re}from"./engines-Cnxy1hW9.js";import{n as ie}from"./settings-tPcmEHCP.js";import{i as ae,r as oe}from"./vendor-CdtpTJrf.js";import{r as F}from"./web-transport-D0bugxxv.js";import{n as se,t as I}from"./time-kviT26Tm.js";import{n as L,t as R}from"./ConfirmDialog-CDPOtXww.js";import{t as z}from"./text-match-DW3sD-Rt.js";import{t as B}from"./SlideOver-Dxtk6Gn2.js";import{n as V,r as ce,t as le}from"./chips-Da37C4KZ.js";var ue=c(`circle-question-mark`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),de=c(`folder-input`,[[`path`,{d:`M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1`,key:`fm4g5t`}],[`path`,{d:`M2 13h10`,key:`pgb2dq`}],[`path`,{d:`m9 16 3-3-3-3`,key:`6m91ic`}]]),H=c(`loader-circle`,[[`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`,key:`13zald`}]]),fe=c(`panel-right`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M15 3v18`,key:`14nvp0`}]]),U=e(o(),1),W=s();function pe({onClose:e}){let{tasks:t}=m(),n=l(),i=(0,U.useRef)(null);P(i);let a=(0,U.useMemo)(()=>{let e=new Set,n=[];for(let r of t)r.repo&&!e.has(r.repo)&&(e.add(r.repo),n.push(r.repo));return n.sort()},[t]),o=(0,U.useMemo)(()=>new Set(t.map(e=>e.worktreePath).filter(Boolean)),[t]),[s,c]=(0,U.useState)(a[0]??``),[f,p]=(0,U.useState)(null),[_,v]=(0,U.useState)(!1),[y,b]=(0,U.useState)(null),[x,S]=(0,U.useState)(!1),C=async e=>{if(e){v(!0),p(null);try{let{worktrees:t}=await h(`worktree.discoverAdoptable`,{repo:e});p(t)}catch(e){d(`scan worktrees`,e),p([])}finally{v(!1)}}},T=async t=>{b(t.path);try{let{task:i}=await h(`worktree.adopt`,{repo:s,worktreePath:t.path,branch:t.branch,ifExists:`return`});r(i.id),g(i.id),n({to:`/task/$taskId`,params:{taskId:i.id}}),u(`success`,`Adopted ${t.branch||t.path}`),e()}catch(e){d(`adopt worktree`,e)}finally{b(null)}};return x?(0,W.jsx)(w,{onClose:e}):a.length===0?(0,W.jsx)(`div`,{className:`fixed inset-0 z-40 flex items-center justify-center bg-black/60`,onClick:e,onKeyDown:t=>{t.key===`Escape`&&e()},role:`presentation`,children:(0,W.jsxs)(`div`,{ref:i,role:`dialog`,"aria-modal":`true`,"aria-label":`Adopt worktree`,className:`flex w-[32rem] max-w-[calc(100vw-2rem)] flex-col border border-line bg-surface shadow-xl`,onClick:e=>e.stopPropagation(),onKeyDown:()=>{},children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between border-b border-line px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-fg`,children:`Adopt worktree`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:`pull an existing worktree into Rove`})]}),(0,W.jsxs)(`div`,{className:`px-3 py-6 text-center`,children:[(0,W.jsx)(`p`,{className:`text-[12px] leading-relaxed text-subtle`,children:`No repos known to Rove yet. Create a task in a repo first, then come back to adopt its worktrees.`}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>S(!0),className:`mt-4 border border-primary bg-inset px-3 py-1.5 text-[11px] text-fg transition-colors hover:bg-primary/10`,children:`Create a task`})]}),(0,W.jsx)(`div`,{className:`flex justify-end border-t border-line px-3 py-2`,children:(0,W.jsx)(`button`,{type:`button`,onClick:e,className:`border border-line bg-bg px-3 py-1.5 text-[11px] text-muted transition-colors hover:border-primary hover:text-fg`,children:`Close`})})]})}):(0,W.jsx)(`div`,{className:`fixed inset-0 z-40 flex items-center justify-center bg-black/60`,onClick:e,onKeyDown:t=>{t.key===`Escape`&&e()},role:`presentation`,children:(0,W.jsxs)(`div`,{ref:i,role:`dialog`,"aria-modal":`true`,"aria-label":`Adopt worktree`,className:`flex max-h-[80vh] w-[32rem] max-w-[calc(100vw-2rem)] flex-col border border-line bg-surface shadow-xl`,onClick:e=>e.stopPropagation(),onKeyDown:()=>{},children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between border-b border-line px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-fg`,children:`Adopt worktree`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:`pull an existing worktree into Rove`})]}),(0,W.jsxs)(`div`,{className:`space-y-2 px-3 py-3`,children:[(0,W.jsx)(`div`,{className:`mb-1 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Repo`}),(0,W.jsxs)(`div`,{className:`flex gap-2`,children:[(0,W.jsx)(`select`,{value:s,onChange:e=>c(e.target.value),className:`min-w-0 flex-1 border border-line bg-bg px-2 py-1.5 text-[12px] text-fg focus:border-line-active focus:outline-none`,children:a.map(e=>(0,W.jsx)(`option`,{value:e,children:e},e))}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>void C(s),disabled:!s||_,className:`shrink-0 border border-primary bg-inset px-3 py-1.5 text-[11px] text-fg transition-colors hover:bg-primary/10 disabled:opacity-40`,children:_?`Scanning…`:`Scan`})]})]}),(0,W.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto border-t border-line`,children:f===null?(0,W.jsx)(`p`,{className:`px-3 py-6 text-center text-[12px] text-subtle`,children:`Pick a repo and Scan to find adoptable worktrees.`}):f.length===0?(0,W.jsx)(`p`,{className:`px-3 py-6 text-center text-[12px] text-subtle`,children:`No adoptable worktrees found for this repo.`}):f.map(e=>{let t=o.has(e.path);return(0,W.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-line-subtle px-3 py-2 last:border-b-0`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-mono text-[12px] text-fg`,children:e.branch||`(detached)`}),e.dirty&&(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-kobe-yellow`,children:`dirty`}),e.kobeManaged&&(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-subtle`,children:`rove`})]}),(0,W.jsxs)(`div`,{className:`mt-0.5 flex items-center gap-2 text-[10px] text-subtle`,children:[(0,W.jsx)(`span`,{className:`truncate font-mono`,children:e.path}),e.lastActivityMs>0&&(0,W.jsx)(`span`,{className:`ml-auto shrink-0`,children:se(e.lastActivityMs)})]})]}),t?(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-subtle`,children:`tracked`}):(0,W.jsx)(`button`,{type:`button`,onClick:()=>void T(e),disabled:y!==null,className:`shrink-0 border border-line bg-bg px-2 py-1 text-[11px] text-muted transition-colors hover:border-primary hover:text-fg disabled:opacity-40`,children:y===e.path?`Adopting…`:`Adopt`})]},e.path)})}),(0,W.jsx)(`div`,{className:`flex justify-end border-t border-line px-3 py-2`,children:(0,W.jsx)(`button`,{type:`button`,onClick:e,className:`border border-line bg-bg px-3 py-1.5 text-[11px] text-muted transition-colors hover:border-primary hover:text-fg`,children:`Close`})})]})})}var G=v({query:``,statusFilter:`all`,sortMode:`default`,showArchived:!1}),K=null;function q(e){G.update(t=>({...t,...e}))}function J(e){q({query:e})}function Y(e){q({statusFilter:e})}function me(e){q({sortMode:e})}function he(e){q({showArchived:e})}function ge(e){!e||e===K||(K=e,q({sortMode:e}))}function _e(){return G.useSnapshot()}function ve(e){let t=Date.parse(e.updatedAt||e.createdAt);return Number.isFinite(t)?t:0}function ye(e,t){let n=ve(t)-ve(e);return n===0?t.id.localeCompare(e.id):n}function be(e,t){let n=e.filter(e=>e.kind===`main`),r=e.filter(e=>e.kind!==`main`&&e.pinned),i=e.filter(e=>e.kind!==`main`&&!e.pinned);return t===`recent`&&(r.sort(ye),i.sort(ye)),[...n,...r,...i]}function xe(e,t){return z([e.title,e.branch,e.repo,e.worktreePath,e.vendor,e.status].filter(Boolean).join(` `),t)}function Se({task:e,onClose:t}){return(0,W.jsx)(B,{open:e!==null,onClose:t,title:e?(0,W.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`shrink-0 border border-line px-1 py-0.5 font-mono text-[9px] uppercase tracking-wide text-subtle`,children:`Archived`}),(0,W.jsx)(`span`,{className:`min-w-0 truncate`,children:e.title||e.branch})]}):void 0,children:e&&(0,W.jsx)(j,{worktreePath:e.worktreePath??null,vendor:e.vendor??`claude`,title:e.title||e.branch})})}function Ce({children:e,suffix:t}){return(0,W.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:e}),t?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(`span`,{className:`h-px flex-1 bg-line`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] font-bold uppercase text-primary`,children:t})]}):null]})}function we({task:e,engine:t,job:n,changes:r,engineName:i,active:a,onClick:o}){let s=n?.phase===`running`,c=s?`materializing…`:M(t?.state),l=I(e.updatedAt||e.createdAt);return(0,W.jsxs)(`button`,{type:`button`,"data-task-id":e.id,onClick:o,className:`group w-full border-l-2 px-3 py-2 text-left transition-colors ${a?`border-primary bg-inset`:`border-transparent hover:bg-surface`}`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[s?(0,W.jsx)(H,{size:10,strokeWidth:2.5,className:`shrink-0 animate-spin text-primary`}):(0,W.jsx)(`span`,{className:`h-1.5 w-1.5 shrink-0 rounded-full ${N(t?.state)}`}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[13px] ${a?`text-fg`:`text-fg/90`}`,children:e.title||e.branch}),(0,W.jsx)(ce,{pr:e.prStatus}),e.pinned&&(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-subtle`,children:`PIN`}),(0,W.jsx)(le,{counts:r})]}),(0,W.jsxs)(`div`,{className:`mt-0.5 flex items-center gap-2 pl-3.5 text-[11px] text-subtle`,children:[(0,W.jsx)(`span`,{className:`min-w-0 truncate`,children:e.branch||`—`}),(0,W.jsxs)(`span`,{className:`ml-auto flex shrink-0 items-center gap-2`,children:[(0,W.jsx)(V,{label:i}),c&&(0,W.jsx)(`span`,{className:`text-muted`,children:c}),l&&(0,W.jsx)(`span`,{className:`text-subtle`,children:l})]})]})]})}function Te({task:e,onRestore:t,onPreview:n}){let r=e.title||e.branch;return(0,W.jsxs)(`div`,{className:`group flex items-center gap-2 border-l-2 border-transparent px-3 py-1.5`,children:[n?(0,W.jsx)(`button`,{type:`button`,onClick:n,title:`Preview history`,className:`min-w-0 flex-1 truncate text-left text-[12px] text-subtle transition-colors hover:text-fg`,children:r}):(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[12px] text-subtle`,children:r}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`shrink-0 border border-line bg-surface px-1.5 py-0.5 text-[10px] text-muted opacity-0 transition-opacity hover:border-primary hover:text-fg group-hover:opacity-100`,children:`Restore`})]})}function Ee({onOpenSettings:e,onNewTask:t,onAdopt:i}){let{tasks:a,engineStates:o,jobs:s,worktreeChanges:c,uiPrefs:u,hydrated:f,streamConnected:p}=m(),{selectedTaskId:_}=n(),v=re(),y=(0,U.useMemo)(()=>oe(a),[a]),b=e=>ae(v,e,y),{query:S,statusFilter:C,sortMode:w,showArchived:E}=_e(),D=(0,U.useRef)(null),O=(0,U.useRef)(null);(0,U.useEffect)(()=>{_&&D.current?.querySelector(`[data-task-id="${CSS.escape(_)}"]`)?.scrollIntoView({block:`nearest`})},[_]);let k=u?.sortMode;(0,U.useEffect)(()=>{ge(k)},[k]);let A=(0,U.useMemo)(()=>a.filter(e=>!e.archived),[a]),j=(0,U.useMemo)(()=>a.filter(e=>e.archived&&e.kind!==`main`),[a]),M=(0,U.useMemo)(()=>be(A.filter(e=>xe(e,S)&&T(o[e.id],c[e.worktreePath],C)),w),[A,S,C,w,o,c]),N=M.filter(e=>e.kind===`main`),P=M.filter(e=>e.kind!==`main`),F=!f||!p&&a.length===0,se=l(),I=e=>{r(e),g(e),se({to:`/task/$taskId`,params:{taskId:e}})};(0,U.useEffect)(()=>{let e=e=>{if(e.metaKey||e.ctrlKey||e.altKey)return;let t=e.key,n=t===`ArrowDown`||t===`ArrowUp`,r=t===`j`||t===`ArrowDown`,i=t===`k`||t===`ArrowUp`,a=t===`/`;if(!r&&!i&&!a)return;let o=e.target;if(o&&(o.tagName===`INPUT`||o.tagName===`TEXTAREA`||o.tagName===`SELECT`||o.isContentEditable)||document.querySelector(`[role=dialog],[role=alertdialog]`)||document.querySelector(`[data-settings-open]`))return;if(a){e.preventDefault(),O.current?.focus();return}if(n&&o&&o!==document.body&&!D.current?.contains(o)||M.length===0)return;e.preventDefault();let s=M.findIndex(e=>e.id===_),c=s===-1?0:Math.min(Math.max(s+(r?1:-1),0),M.length-1);I(M[c].id)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[M,_]);let L=e=>{h(`task.archive`,{taskId:e.id,archived:!1}).catch(t=>d(`restore "${e.title||e.branch}"`,t))},[R,z]=(0,U.useState)(!1),[B,V]=(0,U.useState)(null);return(0,U.useEffect)(()=>{let e=!0;return ie().then(t=>{e&&z(t.archivedHistoryPreview===!0)}).catch(()=>{}),()=>{e=!1}},[]),(0,W.jsxs)(`aside`,{className:`flex w-64 shrink-0 flex-col border-r border-line bg-bg`,children:[(0,W.jsxs)(`div`,{className:`border-b border-line bg-surface/50 px-3 py-2`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Tasks`}),(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`button`,{type:`button`,onClick:()=>me(w==="default"?`recent`:`default`),className:`font-mono text-[10px] uppercase ${w===`recent`?`text-primary`:`text-muted hover:text-fg`}`,title:`Toggle task sort`,children:`sort`}),(0,W.jsxs)(`span`,{className:`font-mono text-[10px] text-muted`,children:[M.length,`/`,A.length]}),(0,W.jsx)(`button`,{type:`button`,onClick:i,className:`text-muted transition-colors hover:text-primary`,title:`Adopt an existing worktree`,"aria-label":`Adopt worktree`,children:(0,W.jsx)(de,{size:14,strokeWidth:1.9})}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`text-muted transition-colors hover:text-primary`,title:`New task`,"aria-label":`New task`,children:(0,W.jsx)(ee,{size:14,strokeWidth:2.2})})]})]}),(0,W.jsxs)(`label`,{className:`mt-2 flex h-8 items-center gap-2 border border-line bg-bg px-2 text-[12px] text-muted focus-within:border-line-active`,children:[(0,W.jsx)(te,{size:14,strokeWidth:1.8,className:`shrink-0 text-subtle`}),(0,W.jsx)(`input`,{ref:O,value:S,onChange:e=>J(e.target.value),onKeyDown:e=>{e.key===`Enter`&&M.length>0?(e.preventDefault(),I(M[0].id),e.currentTarget.blur()):e.key===`Escape`&&S&&(e.preventDefault(),J(``))},placeholder:`Filter tasks`,className:`min-w-0 flex-1 bg-transparent text-fg placeholder:text-subtle focus:outline-none`}),S&&(0,W.jsx)(`button`,{type:`button`,onClick:()=>J(``),className:`shrink-0 text-subtle hover:text-fg`,"aria-label":`clear task filter`,title:`Clear filter`,children:(0,W.jsx)(ne,{size:13,strokeWidth:2})})]}),(0,W.jsx)(`div`,{className:`mt-2 flex items-center gap-1`,children:[{key:`all`,label:`All`,title:`All tasks`},{key:`attention`,label:`Needs`,title:`Needs input / errored / rate-limited`}].map(e=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>Y(e.key),title:e.title,className:`border px-1.5 py-0.5 text-[10px] transition-colors ${C===e.key?`border-primary bg-inset text-fg`:`border-line bg-bg text-subtle hover:border-primary hover:text-fg`}`,children:e.label},e.key))})]}),(0,W.jsxs)(`div`,{ref:D,className:`flex-1 overflow-y-auto`,children:[F?(0,W.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-4 text-[12px] text-subtle`,children:[(0,W.jsx)(H,{size:13,strokeWidth:2,className:`animate-spin`}),(0,W.jsx)(`span`,{children:`connecting…`})]}):A.length===0?(0,W.jsxs)(`div`,{className:`px-3 py-4 text-[12px] leading-relaxed text-subtle`,children:[(0,W.jsx)(`p`,{children:`No tasks yet.`}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`mt-3 border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`+ New task`})]}):M.length===0?(0,W.jsxs)(`div`,{className:`px-3 py-4 text-[12px] leading-relaxed text-subtle`,children:[(0,W.jsx)(`div`,{children:S?`No matches for “${S}”.`:`No tasks in this status.`}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>{J(``),Y(`all`)},className:`mt-3 border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`Clear filter`})]}):(0,W.jsxs)(W.Fragment,{children:[N.length>0&&(0,W.jsx)(Ce,{children:`Projects`}),N.map(e=>(0,W.jsx)(we,{task:e,engine:o[e.id],job:s[e.id],changes:c[e.worktreePath],engineName:b(e),active:e.id===_,onClick:()=>I(e.id)},e.id)),P.length>0&&(0,W.jsx)(Ce,{suffix:w==="default"?void 0:w,children:`Worktrees`}),P.map(e=>(0,W.jsx)(we,{task:e,engine:o[e.id],job:s[e.id],changes:c[e.worktreePath],engineName:b(e),active:e.id===_,onClick:()=>I(e.id)},e.id))]}),!F&&j.length>0&&(0,W.jsxs)(`div`,{className:`mt-2 border-t border-line-subtle pb-2`,children:[(0,W.jsxs)(`button`,{type:`button`,onClick:()=>he(!E),className:`flex w-full items-center gap-2 px-3 py-2 text-left`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Archived`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:j.length}),(0,W.jsx)(`span`,{className:`ml-auto font-mono text-[10px] text-subtle`,children:E?`−`:`+`})]}),E&&j.map(e=>(0,W.jsx)(Te,{task:e,onRestore:()=>L(e),onPreview:R?()=>V(e):void 0},e.id))]})]}),(0,W.jsx)(Se,{task:B,onClose:()=>V(null)}),(0,W.jsx)(`div`,{className:`border-t border-line p-2`,children:(0,W.jsxs)(`button`,{type:`button`,onClick:e,className:`flex w-full items-center gap-2 border border-line bg-surface px-2 py-2 text-left text-[12px] text-muted transition-colors hover:border-primary hover:bg-inset hover:text-fg`,children:[(0,W.jsx)(x,{size:15,strokeWidth:1.8}),(0,W.jsx)(`span`,{children:`Settings`})]})})]})}async function De(e){try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}function X(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}var Oe=/^\/api\/issue-assets\/[a-f0-9]{16}\/[A-Za-z0-9_-]+\.[a-z0-9]+$/;function ke(e){let t=e.trim();return Oe.test(t)?t:null}function Ae(e){let t=e.trim();return/^https?:\/\//i.test(t)?t:t.startsWith(`//`)?null:t.startsWith(`/`)||t.startsWith(`#`)||t.startsWith(`./`)||t.startsWith(`../`)?t:null}function je(e){let t=e;return t.includes(`]`)&&t.includes(`)`)&&(t=t.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,(e,t,n)=>{let r=ke(n.replace(/&amp;/g,`&`));return r?`<img src="${X(r)}" alt="${X(t)}" loading="lazy" class="kobe-md-img">`:`![${t}](${n})`})),t.includes(`]`)&&t.includes(`)`)&&(t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,t,n)=>{let r=Ae(n.replace(/&amp;/g,`&`));return r?`<a href="${X(r)}" target="_blank" rel="noopener noreferrer" class="kobe-md-link">${t}</a>`:`${t}(${n})`})),t=t.replace(/\*\*(.+?)\*\*/g,`<strong>$1</strong>`),t=t.replace(/(^|[^*])\*([^*]+)\*/g,`$1<em>$2</em>`),t}function Z(e){return e.split(/(`[^`]+`)/g).map((e,t)=>t%2==1?`<code class="kobe-md-code">${e.slice(1,-1)}</code>`:je(e)).join(``)}function Me(e){let t=e.replace(/\r\n/g,`
2
+ `).split(`
3
+ `),n=[],r=0,i=null,a=()=>{i&&=(n.push(`</${i}>`),null)};for(;r<t.length;){let e=t[r];if(/^```/.test(e)){a();let e=[];for(r++;r<t.length&&!/^```/.test(t[r]);)e.push(X(t[r])),r++;r++,n.push(`<pre class="kobe-md-pre"><code>${e.join(`
4
+ `)}</code></pre>`);continue}if(/^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(e)){a(),n.push(`<hr class="kobe-md-hr" />`),r++;continue}let o=/^(#{1,6})\s+(.*)$/.exec(e);if(o){a();let e=o[1].length;n.push(`<h${e} class="kobe-md-h">${Z(X(o[2]))}</h${e}>`),r++;continue}if(/^>\s?/.test(e)){a(),n.push(`<blockquote class="kobe-md-quote">${Z(X(e.replace(/^>\s?/,``)))}</blockquote>`),r++;continue}let s=/^\s*[-*]\s+(.*)$/.exec(e);if(s){i!==`ul`&&(a(),n.push(`<ul class="kobe-md-ul">`),i=`ul`),n.push(`<li>${Z(X(s[1]))}</li>`),r++;continue}let c=/^\s*\d+\.\s+(.*)$/.exec(e);if(c){i!==`ol`&&(a(),n.push(`<ol class="kobe-md-ol">`),i=`ol`),n.push(`<li>${Z(X(c[1]))}</li>`),r++;continue}if(e.trim()===``){a(),r++;continue}a();let l=[e];for(r++;r<t.length&&t[r].trim()!==``&&!/^(#{1,6}\s|>\s?|```|\s*[-*]\s|\s*\d+\.\s|\s*(-{3,}|\*{3,}|_{3,})\s*$)/.test(t[r]);)l.push(t[r]),r++;n.push(`<p class="kobe-md-p">${Z(X(l.join(` `)))}</p>`)}return a(),n.join(`
5
+ `)}async function Ne(e){return(await t.get(`/api/notes`,{query:{taskId:e},label:`load notes`})).markdown??``}async function Pe(e,n){await t.put(`/api/notes`,{taskId:e,markdown:n},{label:`save notes`})}function Fe(e){switch(e){case`saving`:return`saving…`;case`saved`:return`saved`;case`error`:return`save failed`;default:return``}}var Ie=600;function Le({children:e,right:t}){return(0,W.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:e}),t]})}function Re({taskId:e,full:t=!1}){let[n,r]=(0,U.useState)(``),[i,a]=(0,U.useState)(!1),[o,s]=(0,U.useState)(!1),[c,l]=(0,U.useState)(`idle`),u=(0,U.useMemo)(()=>Me(n),[n]),d=(0,U.useRef)(null),f=(0,U.useRef)(null),p=(0,U.useRef)(null),m=(0,U.useCallback)(()=>{d.current&&=(clearTimeout(d.current),null);let e=p.current;if(!e)return;p.current=null;let{taskId:t,value:n}=e;Pe(t,n).then(()=>{f.current===t&&l(`saved`)}).catch(()=>{f.current===t&&l(`error`)})},[]);(0,U.useEffect)(()=>{if(f.current=e,m(),l(`idle`),r(``),a(!1),!e)return;let t=!1;return s(!0),Ne(e).then(n=>{!t&&f.current===e&&r(n)}).catch(()=>{!t&&f.current===e&&r(``)}).finally(()=>{t||s(!1)}),()=>{t=!0}},[e,m]),(0,U.useEffect)(()=>()=>{m()},[m]);let h=(0,U.useCallback)(t=>{if(r(t),!e)return;let n=e;l(`saving`),p.current={taskId:n,value:t},d.current&&clearTimeout(d.current),d.current=setTimeout(m,Ie)},[e,m]);return(0,W.jsxs)(`div`,{className:`flex h-full min-h-0 flex-1 flex-col bg-bg`,children:[(0,W.jsx)(Le,{right:e?(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[c!==`idle`&&(0,W.jsx)(`span`,{className:`text-[10px] ${c===`error`?`text-kobe-red`:`text-subtle`}`,children:Fe(c)}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>a(e=>!e),className:`border px-1.5 py-0.5 text-[10px] transition-colors ${i?`border-primary bg-inset text-fg`:`border-line bg-bg text-muted hover:border-primary hover:text-fg`}`,title:`Toggle markdown preview`,children:i?`Edit`:`Preview`})]}):null,children:`Notes`}),(0,W.jsx)(`div`,{className:`min-h-0 flex-1 ${t?`px-0 pb-0`:`px-3 pb-3`}`,children:e?i?(0,W.jsx)(`div`,{className:`h-full w-full overflow-auto bg-surface px-4 py-3 ${t?`border-t border-line`:`rounded border border-line`}`,children:n.trim()?(0,W.jsx)(`div`,{className:`kobe-md text-[12px] leading-relaxed text-fg`,dangerouslySetInnerHTML:{__html:u}}):(0,W.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`Nothing to preview yet.`})}):(0,W.jsx)(`textarea`,{value:n,onChange:e=>h(e.target.value),spellCheck:!1,placeholder:o?`loading notes…`:`Notes for this task — markdown, autosaved.`,disabled:o,className:`h-full w-full resize-none border-line bg-surface px-4 py-3 font-mono text-[12px] leading-relaxed text-fg placeholder:text-subtle focus:border-line-active focus:outline-none disabled:opacity-60 ${t?`border-x-0 border-b-0 border-t`:`rounded border`}`}):(0,W.jsx)(`div`,{className:`flex h-full items-center justify-center px-4 text-center`,children:(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`text-[12px] font-semibold text-fg`,children:`No task selected`}),(0,W.jsx)(`div`,{className:`mt-1 max-w-48 text-[12px] leading-relaxed text-subtle`,children:`Pick a task to open its web-only scratchpad.`})]})})})]})}var ze=[`backlog`,`in_progress`,`in_review`,`done`,`canceled`,`error`],Be=`DIRTY_WORKTREE`;function Ve(e){return e.replace(/_/g,` `)}function Q({name:e,value:t,mono:n=!1}){return(0,W.jsxs)(`div`,{className:`min-w-0 border-b border-line-subtle py-2 last:border-b-0`,children:[(0,W.jsx)(`div`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:e}),(0,W.jsx)(`div`,{className:`mt-1 min-w-0 truncate text-[12px] text-fg ${n?`font-mono`:``}`,title:t,children:t||`—`})]})}function $({children:e,onClick:t,disabled:n,danger:r=!1}){return(0,W.jsx)(`button`,{type:`button`,onClick:t,disabled:n,className:`border px-2 py-1 text-[11px] transition-colors disabled:opacity-40 ${r?`border-kobe-red/40 text-kobe-red hover:bg-kobe-red/10`:`border-line bg-surface text-muted hover:border-primary hover:text-fg`}`,children:e})}function He({task:e}){let[t,n]=(0,U.useState)(e?.title??``),[r,i]=(0,U.useState)(e?.branch??``),[o,s]=(0,U.useState)(null),[c,f]=(0,U.useState)(!1),p=(0,U.useRef)(null);(0,U.useEffect)(()=>()=>{p.current&&clearTimeout(p.current)},[]);let[m,v]=(0,U.useState)(null),y=re(),b=l();if((0,U.useEffect)(()=>{n(e?.title??``)},[e?.title]),(0,U.useEffect)(()=>{i(e?.branch??``)},[e?.branch]),!e)return(0,W.jsx)(`div`,{className:`flex h-full items-center justify-center px-4 text-center`,children:(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`text-[12px] font-semibold text-fg`,children:`No task selected`}),(0,W.jsx)(`div`,{className:`mt-1 max-w-48 text-[12px] leading-relaxed text-subtle`,children:`Pick a task to edit its metadata and worktree state.`})]})});let x=async(e,t)=>{s(e);try{await t()}catch(t){d(e.split(`:`)[0],t)}finally{s(null)}},S=()=>{let n=t.trim();!n||n===e.title||x(`rename`,()=>h(`task.rename`,{taskId:e.id,title:n}))},C=()=>{let t=r.trim();!t||t===e.branch||x(`branch`,()=>h(`task.setBranch`,{taskId:e.id,branch:t}))},w=()=>{De(e.worktreePath).then(e=>{e&&(f(!0),p.current&&clearTimeout(p.current),p.current=setTimeout(()=>f(!1),1200))})},T=()=>{v(null),x(`archive`,async()=>{await h(`task.archive`,{taskId:e.id,archived:!0}),a(),b({to:`/`}),await _(null)})},E=()=>{x(`restore`,()=>h(`task.archive`,{taskId:e.id,archived:!1}))},D=t=>{v(null),s(`delete`),(async()=>{try{await h(`task.delete`,{taskId:e.id,force:t}),a(),b({to:`/`}),g(null),u(`success`,`Deleted "${e.title||e.branch}"`)}catch(e){let n=e instanceof Error?e.message:String(e);!t&&n.includes(Be)?v({kind:`delete`,force:!0}):d(`delete`,e)}finally{s(null)}})()};return(0,W.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,W.jsxs)(`div`,{className:`border-b border-line px-3 py-3`,children:[(0,W.jsx)(`div`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Task`}),(0,W.jsxs)(`div`,{className:`mt-2 flex gap-2`,children:[(0,W.jsx)(`input`,{value:t,onChange:e=>n(e.target.value),onBlur:S,onKeyDown:e=>{e.key===`Enter`&&S()},className:`min-w-0 flex-1 border border-line bg-bg px-2 py-1.5 text-[12px] text-fg focus:border-line-active focus:outline-none`}),(0,W.jsx)($,{onClick:S,disabled:o===`rename`,children:`Save`})]}),e.archived&&(0,W.jsxs)(`div`,{className:`mt-2 flex items-center justify-between gap-2 border border-kobe-yellow/40 bg-kobe-yellow/10 px-2 py-1.5`,children:[(0,W.jsx)(`span`,{className:`text-[11px] text-kobe-yellow`,children:`archived`}),(0,W.jsx)($,{onClick:E,disabled:o!==null,children:`Restore`})]})]}),(0,W.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 py-2`,children:[e.kind===`main`?(0,W.jsx)(Q,{name:`Branch`,value:e.branch,mono:!0}):(0,W.jsxs)(`div`,{className:`min-w-0 border-b border-line-subtle py-2`,children:[(0,W.jsx)(`div`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Branch`}),(0,W.jsx)(`div`,{className:`mt-1 flex gap-2`,children:(0,W.jsx)(`input`,{value:r,onChange:e=>i(e.target.value),onBlur:C,onKeyDown:e=>{e.key===`Enter`&&C()},className:`min-w-0 flex-1 border border-line bg-bg px-2 py-1 font-mono text-[12px] text-fg focus:border-line-active focus:outline-none`})})]}),(0,W.jsx)(Q,{name:`Vendor`,value:e.vendor??`claude`}),(0,W.jsx)(Q,{name:`Worktree`,value:e.worktreePath,mono:!0}),(0,W.jsx)(Q,{name:`Repo`,value:e.repo,mono:!0}),(0,W.jsxs)(`div`,{className:`mt-4`,children:[(0,W.jsx)(`div`,{className:`mb-2 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Status`}),(0,W.jsx)(`div`,{className:`grid grid-cols-2 gap-1.5`,children:ze.map(t=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>void x(`status:${t}`,()=>h(`task.status`,{taskId:e.id,status:t})),disabled:o!==null,className:`border px-2 py-1.5 text-left text-[11px] capitalize transition-colors disabled:opacity-40 ${e.status===t?`border-primary bg-inset text-fg`:`border-line bg-surface text-muted hover:border-primary hover:text-fg`}`,children:Ve(t)},t))})]}),(0,W.jsxs)(`div`,{className:`mt-4`,children:[(0,W.jsx)(`div`,{className:`mb-2 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Vendor`}),(0,W.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:y.map(t=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>void x(`vendor:${t.id}`,()=>h(`task.setVendor`,{taskId:e.id,vendor:t.id})),disabled:o!==null,className:`border px-2 py-1 text-[11px] transition-colors disabled:opacity-40 ${(e.vendor??`claude`)===t.id?`border-primary bg-inset text-fg`:`border-line bg-surface text-muted hover:border-primary hover:text-fg`}`,children:t.label},t.id))})]}),(0,W.jsxs)(`div`,{className:`mt-4 grid grid-cols-2 gap-2`,children:[(0,W.jsx)($,{onClick:()=>void x(`pin`,()=>h(`task.pin`,{taskId:e.id,pinned:!e.pinned})),disabled:o!==null,children:e.pinned?`Unpin`:`Pin`}),(0,W.jsx)($,{onClick:()=>void x(`worktree`,()=>h(`task.ensureWorktree`,{taskId:e.id})),disabled:o!==null,children:`Ensure worktree`}),(0,W.jsx)($,{onClick:w,children:c?`Copied`:`Copy path`}),!e.archived&&(0,W.jsx)($,{onClick:()=>v({kind:`archive`}),disabled:o!==null,danger:!0,children:`Archive`})]}),e.kind!==`main`&&(0,W.jsxs)(`div`,{className:`mt-4 border-t border-line-subtle pt-3`,children:[(0,W.jsx)(`div`,{className:`mb-2 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Danger zone`}),(0,W.jsx)($,{onClick:()=>v({kind:`delete`,force:!1}),disabled:o!==null,danger:!0,children:`Delete task + worktree`})]})]}),m?.kind===`archive`&&(0,W.jsx)(R,{title:`Archive task`,body:`Archive "${e.title||e.branch}"? Its Hosted PTY sessions will be stopped; the worktree stays on disk and the task can be restored from the Archived section.`,confirmLabel:`Archive`,danger:!0,busy:o===`archive`,onConfirm:T,onCancel:()=>v(null)}),m?.kind===`delete`&&(0,W.jsx)(R,{title:m.force?`Worktree has uncommitted changes`:`Delete task`,body:m.force?`"${e.title||e.branch}" has uncommitted or untracked changes in its worktree. Force-delete discards them permanently.`:`Delete "${e.title||e.branch}"? This removes the task, kills its engine session, and removes its worktree (branch history stays in git).`,confirmLabel:m.force?`Force delete`:`Delete`,danger:!0,busy:o===`delete`,onConfirm:()=>D(m.force),onCancel:()=>v(null)})]})}function Ue({drawer:e=!1,onClose:t}={}){let[r,a]=(0,U.useState)(`overview`),{selectedTaskId:o}=n(),{tasks:s}=m(),c=o?s.find(e=>e.id===o)??null:null;return(0,W.jsxs)(`aside`,{className:e?`flex h-full w-full flex-col bg-bg`:`flex w-80 shrink-0 flex-col border-l border-line bg-bg`,children:[(0,W.jsxs)(`div`,{className:`flex h-9 shrink-0 items-stretch border-b border-line bg-surface`,children:[[`overview`,`notes`,`changes`].map(e=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>a(e),className:`px-3 text-[10px] font-bold uppercase tracking-[0.12em] ${r===e?`border-b-2 border-primary text-fg`:`text-subtle hover:text-muted`}`,children:e===`overview`?`Task`:e===`notes`?`Notes`:`Changes`},e)),e&&t&&(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`ml-auto px-3 text-subtle hover:text-fg`,"aria-label":`Close tools`,children:(0,W.jsx)(ne,{size:14,strokeWidth:2})})]}),(0,W.jsx)(`div`,{className:`min-h-0 flex-1`,children:r===`overview`?(0,W.jsx)(He,{task:c}):r===`notes`?(0,W.jsx)(Re,{taskId:o,full:!0}):(0,W.jsx)(O,{worktreePath:c?.worktreePath??null,onOpenFile:e=>{o&&i(o,e)}})})]})}function We({onToggleTools:e,onShowHelp:t}){let{daemonConnected:r,streamConnected:i,tasks:a}=m(),{selectedTaskId:o}=n(),s=o?a.find(e=>e.id===o):null,c=F({daemonConnected:r,streamConnected:i});return(0,W.jsxs)(`header`,{"data-kobe-topbar":!0,className:`flex h-10 shrink-0 items-center gap-3 border-b border-line bg-surface px-3`,children:[(0,W.jsx)(L,{}),(0,W.jsx)(`span`,{className:`font-mono text-[13px] font-bold text-primary`,children:`[rove]`}),(0,W.jsx)(p,{}),s?(0,W.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`max-w-56 truncate rounded bg-inset px-2 py-0.5 text-[11px] text-fg`,children:s.title||s.branch}),(0,W.jsx)(`span`,{className:`hidden max-w-40 truncate font-mono text-[11px] text-subtle md:inline`,children:s.branch})]}):(0,W.jsx)(`span`,{className:`rounded bg-inset px-2 py-0.5 text-[11px] text-muted`,children:`Workspace`}),(0,W.jsxs)(`div`,{className:`ml-auto flex items-center gap-3 text-[11px] text-subtle`,children:[(0,W.jsxs)(`span`,{className:`hidden items-center gap-1.5 sm:flex`,title:c.title,children:[(0,W.jsx)(`span`,{className:`h-1.5 w-1.5 rounded-full ${c.ok?`bg-kobe-green`:`bg-kobe-yellow`}`}),(0,W.jsx)(`span`,{children:c.label})]}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`hidden items-center text-muted transition-colors hover:text-fg sm:flex`,"aria-label":`Keyboard shortcuts`,title:`Keyboard shortcuts (?)`,children:(0,W.jsx)(ue,{size:15,strokeWidth:1.8})}),(0,W.jsx)(`button`,{type:`button`,onClick:e,className:`flex items-center text-muted transition-colors hover:text-fg lg:hidden`,"aria-label":`Toggle task tools`,title:`Task tools`,children:(0,W.jsx)(fe,{size:15,strokeWidth:1.8})})]})]})}function Ge(){let{tasks:e,update:t}=m(),{selectedTaskId:r}=n(),i=r?e.find(e=>e.id===r):null,a=e.filter(e=>!e.archived).length;return(0,W.jsxs)(`footer`,{className:`flex h-7 shrink-0 items-center gap-4 border-t border-line bg-surface px-3 text-[11px] text-subtle`,children:[(0,W.jsxs)(`span`,{children:[a,` task`,a===1?``:`s`]}),i&&(0,W.jsxs)(`span`,{className:`min-w-0 truncate text-muted`,children:[i.kind===`main`?`project`:`worktree`,` ·`,` `,D(i.worktreePath,54)]}),(0,W.jsx)(`span`,{className:`ml-auto`,children:t?.latest?`update ${t.latest} available`:`Rove web`})]})}function Ke(){let{settingsOpen:e}=C(),[t,n]=(0,U.useState)(!1),[r,i]=(0,U.useState)(!1);return(0,U.useEffect)(()=>{let e=e=>{e.key===`Escape`&&i(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]),(0,W.jsxs)(`div`,{className:`flex h-screen flex-col overflow-hidden bg-bg text-fg`,children:[(0,W.jsx)(We,{onToggleTools:()=>i(e=>!e),onShowHelp:S}),(0,W.jsx)(f,{}),(0,W.jsxs)(`div`,{className:`flex min-h-0 flex-1`,children:[(0,W.jsx)(Ee,{onOpenSettings:b,onNewTask:E,onAdopt:()=>n(!0)}),e?(0,W.jsx)(A,{onClose:y}):(0,W.jsx)(k,{}),(0,W.jsx)(`div`,{className:`hidden lg:flex`,children:(0,W.jsx)(Ue,{})}),r&&(0,W.jsx)(`div`,{className:`fixed inset-0 z-30 flex justify-end bg-black/50 lg:hidden`,onClick:()=>i(!1),onKeyDown:e=>{e.key===`Escape`&&i(!1)},role:`presentation`,children:(0,W.jsx)(`div`,{role:`dialog`,"aria-modal":`true`,"aria-label":`Task tools`,className:`h-full w-80 max-w-[85vw] border-l border-line bg-bg shadow-2xl`,onClick:e=>e.stopPropagation(),onKeyDown:()=>{},children:(0,W.jsx)(Ue,{drawer:!0,onClose:()=>i(!1)})})})]}),(0,W.jsx)(Ge,{}),t&&(0,W.jsx)(pe,{onClose:()=>n(!1)})]})}export{Ke as AppShell};
@@ -0,0 +1 @@
1
+ .kobe-md>:first-child{margin-top:0}.kobe-md-h{color:var(--color-fg);margin:.9em 0 .4em;font-weight:700;line-height:1.3}.kobe-md h1.kobe-md-h{font-size:1.4em}.kobe-md h2.kobe-md-h{font-size:1.2em}.kobe-md h3.kobe-md-h{font-size:1.08em}.kobe-md-p{margin:.5em 0}.kobe-md-ul,.kobe-md-ol{margin:.5em 0;padding-left:1.4em}.kobe-md-ul{list-style:outside}.kobe-md-ol{list-style:decimal}.kobe-md-ul li,.kobe-md-ol li{margin:.15em 0}.kobe-md-quote{border-left:2px solid var(--color-line-active);color:var(--color-muted);margin:.5em 0;padding-left:.75rem}.kobe-md-code{font-family:var(--font-mono,ui-monospace, monospace);background:var(--color-inset);border:1px solid var(--color-line);border-radius:3px;padding:0 .3em;font-size:.9em}.kobe-md-pre{background:var(--color-bg);border:1px solid var(--color-line);border-radius:4px;margin:.6em 0;padding:.6rem .75rem;overflow-x:auto}.kobe-md-pre code{font-family:var(--font-mono,ui-monospace, monospace);white-space:pre;color:var(--color-muted);font-size:.92em}.kobe-md-link{color:var(--color-primary);text-decoration:underline}.kobe-md-hr{border:0;border-top:1px solid var(--color-line);margin:.9em 0}.kobe-md strong{color:var(--color-fg);font-weight:700}.kobe-md em{font-style:italic}
@@ -0,0 +1 @@
1
+ import{l as e}from"./terminal-qBEkzc-m.js";import{f as t,y as n}from"./tabs-Dx-TnbvG.js";import{d as r}from"./createLucideIcon-CM5xLVj1.js";import{a as i,n as a,r as o}from"./toast-BXjAT0ix.js";import{n as s,t as c}from"./ViewToggle-BdPCMBWa.js";import{n as l}from"./store-uT65Mask.js";import{n as u}from"./active-task-GeQZqbJK.js";import{t as d}from"./external-store-DJlWpyYC.js";import{t as f}from"./external-link-BwT2u1hD.js";import{a as p,i as m,n as h,r as g,t as _}from"./lazy-issue-panels-0Rhl2uhh.js";import{t as v}from"./plus-BbX5qXba.js";import{t as y}from"./search-BxbFZoup.js";import{t as b}from"./x-7cB9X7Hi.js";import{n as ee,t as x}from"./ConfirmDialog-CDPOtXww.js";import{_ as S,a as C,d as te,g as w,h as T,m as E,p as D,s as ne,u as O}from"./issues-1SCRkcB0.js";var k=e(n(),1),A={query:``,repo:null};function j(e){M.update(t=>({...t,...e}))}var M=d(A);function N(){return M.useSnapshot()}function P(e){e!==M.getSnapshot().query&&j({query:e})}function F(e){e!==M.getSnapshot().repo&&j({repo:e})}function re(e){let{issueRepos:t,issueData:n,refreshIssues:r}=e,[i,a]=(0,k.useState)(!1),[s,c]=(0,k.useState)(null),[l,u]=(0,k.useState)(new Map);return(0,k.useEffect)(()=>{u(e=>{if(e.size===0)return e;let r=new Map(e),i=!1;for(let e of t){let t=n[e];if(!(!t||!t.exists))for(let n of t.issues)n.taskId&&r.delete(`${e}:${n.id}`)&&(i=!0)}return i?r:e})},[t,n]),{issueBusy:i,quickStartingId:s,pendingLinks:l,saveIssue:async(e,t,n)=>{a(!0);try{return await T(e,t,n),r([e]),!0}catch(e){return o(`update issue`,e),!1}finally{a(!1)}},deleteIssueConfirmed:async(e,t)=>{a(!0);try{return await C(e,t.id),r([e]),!0}catch(e){return o(`delete issue`,e),!1}finally{a(!1)}},quickStart:async(e,t,n,r,i)=>{if(s===null){c(t.id);try{let{taskId:a,workspaceTaskId:o}=await E(e,t,{vendor:n,effort:r,placement:i});return i!==`project`&&u(n=>{let r=new Map(n);return r.set(`${e}:${t.id}`,{repo:e,issueId:t.id,taskId:a}),r}),o}catch(e){o(`quick start issue`,e);return}finally{c(null)}}}}}var I=r();function L({repo:e,column:t,onNewIssue:n,onPeekIssue:r,onOpenTask:i,onDeleteIssue:a}){return(0,I.jsxs)(`section`,{"data-column":`${e}:${t.key}`,className:`flex h-full shrink-0 flex-col border border-transparent ${t.key===`backlog`?`w-96`:`w-72`}`,children:[(0,I.jsxs)(`div`,{className:`mb-2 flex items-baseline gap-2`,children:[(0,I.jsx)(`h2`,{className:`text-[11px] font-bold uppercase tracking-[0.12em] ${t.accent}`,children:t.title}),(0,I.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:t.cards.length+t.hiddenCount}),n&&(0,I.jsxs)(`button`,{type:`button`,onClick:n,className:`ml-auto flex items-center gap-0.5 text-[10px] text-subtle transition-colors hover:text-fg`,title:`New story in this project`,children:[(0,I.jsx)(v,{size:11,strokeWidth:2}),(0,I.jsx)(`span`,{children:`New story`})]})]}),(0,I.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto pb-2`,children:[t.cards.length===0?(0,I.jsx)(`div`,{className:`border border-dashed border-line-subtle p-3 text-center text-[11px] text-subtle`,children:`none`}):t.cards.map(e=>{let{issue:t}=e,n=S(t)?t.taskId:void 0;return(0,I.jsxs)(`div`,{className:`group/wrap relative`,children:[(0,I.jsx)(m,{issue:t,onOpen:()=>r(t),onDelete:()=>a(t)}),n&&(0,I.jsxs)(`button`,{type:`button`,onClick:()=>i(n),"aria-label":`Open task for issue #${t.id}`,title:`Started — open task`,className:`absolute bottom-2 right-2 flex items-center gap-1 border border-line bg-surface px-1.5 py-0.5 text-[10px] text-subtle opacity-0 transition-opacity hover:border-primary hover:text-fg focus-visible:opacity-100 group-hover/wrap:opacity-100`,children:[(0,I.jsx)(f,{size:10,strokeWidth:1.8}),(0,I.jsx)(`span`,{children:`open task`})]})]},`issue:${t.id}`)}),t.hiddenCount>0&&(0,I.jsxs)(`div`,{className:`p-2 text-center text-[10px] text-subtle`,children:[`+`,t.hiddenCount,` more — finish stories to thin this column`]})]})]})}function ie({board:e,onNewIssue:t,onPeekIssue:n,onOpenTask:r,onDeleteIssue:i}){return(0,I.jsx)(`div`,{className:`flex h-full min-w-max gap-4`,children:e.columns.map(a=>(0,I.jsx)(L,{repo:e.repo,column:a,onNewIssue:a.key===`backlog`?()=>t(e.repo):void 0,onPeekIssue:n,onOpenTask:r,onDeleteIssue:t=>i(e.repo,t)},a.key))})}function R(){let{tasks:e,hydrated:n,daemonConnected:r}=l(),{query:d,repo:f}=N(),m=i(),S=(0,k.useRef)(null),[C,T]=(0,k.useState)(null),[E,A]=(0,k.useState)(null),[j,M]=(0,k.useState)(null),[L,R]=(0,k.useState)([]);(0,k.useEffect)(()=>{let e=!1;return ne().then(t=>{e||R(t)}).catch(e=>o(`load projects`,e)),()=>{e=!0}},[]);let z=(0,k.useMemo)(()=>O(e,L),[e,L]),B=(0,k.useMemo)(()=>z.map(e=>e.repo),[z]),V=(0,k.useMemo)(()=>D(z,f),[z,f]),{data:H,pending:U,refresh:W}=p(B),{issueBusy:G,quickStartingId:K,pendingLinks:q,saveIssue:J,deleteIssueConfirmed:ae,quickStart:oe}=re({issueRepos:B,issueData:H,refreshIssues:W}),{allIssues:Y,repoChips:se,projectBoards:X,shownCount:Z,hasAnyCard:Q}=(0,k.useMemo)(()=>w({issueData:H,issueRepos:B,pendingLinks:q,query:d,repoFilter:V}),[H,B,q,d,V]);(0,k.useEffect)(()=>{C&&(Y.some(e=>e.repo===C.repo&&e.issue.id===C.id)||T(null))},[Y,C]),(0,k.useEffect)(()=>{let e=e=>{if(C||E||j||e.metaKey||e.ctrlKey||e.altKey)return;let t=e.target,n=!!t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.tagName===`SELECT`||t.isContentEditable);e.key===`/`&&!n?(e.preventDefault(),S.current?.focus()):e.key===`Escape`&&t===S.current&&d&&(e.preventDefault(),P(``))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[d,C,E,j]),(0,k.useEffect)(()=>{f!==V&&F(V)},[V,f]);let ce=!!d,$=e=>{t(e),u(e),m({to:`/task/$taskId`,params:{taskId:e}})};return(0,I.jsxs)(`div`,{className:`flex h-screen flex-col overflow-hidden bg-bg text-fg`,children:[(0,I.jsxs)(`header`,{"data-kobe-topbar":!0,className:`flex h-10 shrink-0 items-center gap-3 border-b border-line bg-surface px-3`,children:[(0,I.jsx)(ee,{}),(0,I.jsx)(`span`,{className:`font-mono text-[13px] font-bold text-primary`,children:`[rove]`}),(0,I.jsx)(c,{}),(0,I.jsxs)(`label`,{className:`flex h-7 items-center gap-1.5 border border-line bg-bg px-2 text-muted focus-within:border-line-active`,children:[(0,I.jsx)(y,{size:13,strokeWidth:1.8,className:`shrink-0 text-subtle`}),(0,I.jsx)(`input`,{ref:S,value:d,onChange:e=>P(e.target.value),placeholder:`Filter stories ( / )`,className:`w-44 bg-transparent text-[12px] text-fg placeholder:text-subtle focus:outline-none`}),d&&(0,I.jsx)(`button`,{type:`button`,onClick:()=>P(``),className:`shrink-0 text-subtle hover:text-fg`,"aria-label":`clear filter`,title:`Clear filter`,children:(0,I.jsx)(b,{size:13,strokeWidth:2})})]}),z.length>0&&(0,I.jsxs)(`label`,{className:`flex h-7 min-w-0 max-w-[24rem] items-center gap-1.5 border border-line bg-bg px-2 text-muted focus-within:border-line-active`,children:[(0,I.jsx)(`span`,{className:`shrink-0 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Project`}),(0,I.jsx)(`select`,{value:V??``,onChange:e=>F(e.target.value),title:V??`Select project`,className:`min-w-0 flex-1 bg-transparent font-mono text-[11px] text-fg focus:outline-none`,children:z.map(e=>{let t=se.find(t=>t.repo===e.repo)?.count??0;return(0,I.jsxs)(`option`,{value:e.repo,title:e.repo,className:`bg-surface text-fg`,children:[e.label,` · `,t,` · `,e.repo]},e.repo)})})]}),(0,I.jsx)(`div`,{className:`ml-auto flex items-center gap-3 font-mono text-[11px] text-subtle`,children:(0,I.jsxs)(`span`,{children:[Z,` stor`,Z===1?`y`:`ies`]})})]}),(0,I.jsx)(s,{}),(0,I.jsx)(`div`,{className:`min-h-0 flex-1 overflow-x-auto overflow-y-hidden p-4`,children:!n||U&&!Q?(0,I.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`Loading…`}):Z===0&&ce&&Q?(0,I.jsxs)(`div`,{className:`text-[12px] leading-relaxed text-subtle`,children:[(0,I.jsx)(`p`,{children:`No stories match.`}),(0,I.jsx)(`button`,{type:`button`,onClick:()=>{P(``)},className:`mt-3 border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`Clear filters`})]}):Z===0&&!r?(0,I.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`Can't reach the daemon — issue list may be incomplete.`}):X[0]?(0,I.jsx)(ie,{board:X[0],onNewIssue:A,onPeekIssue:e=>T({repo:X[0].repo,id:e.id}),onOpenTask:$,onDeleteIssue:(e,t)=>M({repo:e,issue:t})}):(0,I.jsxs)(`div`,{className:`text-[12px] leading-relaxed text-subtle`,children:[(0,I.jsx)(`p`,{children:`No projects yet. Create a task from the workspace to track stories against its repo.`}),(0,I.jsx)(`div`,{className:`mt-3 flex items-center gap-2`,children:(0,I.jsx)(`button`,{type:`button`,onClick:()=>m({to:`/`}),className:`border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`Back to workspace`})})]})}),(()=>{let e=V??X[0]?.repo??B[0];return e?(0,I.jsx)(`button`,{type:`button`,onClick:()=>A(e),title:`New story`,"aria-label":`New story`,className:`fixed bottom-6 right-6 z-20 flex h-12 w-12 items-center justify-center rounded-full border border-primary bg-primary text-bg shadow-lg transition-transform hover:scale-105`,children:(0,I.jsx)(v,{size:22,strokeWidth:2.2})}):null})(),E&&(0,I.jsx)(_,{children:(0,I.jsx)(h,{repoRoot:E,open:!0,onClose:()=>A(null),onCreated:(e,t)=>{E&&W([E]),a(`success`,t?`Story #${e.id} created — starting its session`:`Story #${e.id} created`)}})}),(()=>{if(!C)return null;let e=Y.find(e=>e.repo===C.repo&&e.issue.id===C.id);return e?(0,I.jsx)(_,{children:(0,I.jsx)(g,{issue:e.issue,repoRoot:e.repo,busy:G,starting:K===e.issue.id,onClose:()=>T(null),onSave:t=>J(e.repo,e.issue.id,t),onStart:async({vendor:t,effort:n,placement:r,watch:i})=>{let a=await oe(e.repo,e.issue,t,n,r);i&&a?(T(null),$(a)):T(null)},onOpenSession:e.issue.taskId?()=>{let t=e.issue.taskId;T(null),t&&$(t)}:void 0,onPromptMerge:e.issue.taskId?()=>{let t=e.issue.taskId;t&&te(t,e.issue).then(()=>a(`success`,`Prompt inserted for story #${e.issue.id}`)).catch(e=>o(`prompt issue merge`,e))}:void 0},`${e.repo}:${e.issue.id}`)}):null})(),j&&(0,I.jsx)(x,{title:`Delete issue`,body:`Delete issue #${j.issue.id}: "${j.issue.title}"? This removes it from the daemon issue tracker only; it does not delete any task, branch, worktree, or engine session.`,confirmLabel:`Delete`,danger:!0,busy:G,onConfirm:()=>void ae(j.repo,j.issue).then(e=>{e&&(M(null),C?.repo===j.repo&&C.id===j.issue.id&&T(null))}),onCancel:()=>M(null)})]})}export{R as Board};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ChatTerminal-MCI1aBbT.js","assets/terminal-qBEkzc-m.js","assets/tabs-Dx-TnbvG.js","assets/createLucideIcon-CM5xLVj1.js","assets/store-uT65Mask.js","assets/rotate-cw-D-UUtiD0.js","assets/web-transport-D0bugxxv.js","assets/ChatTerminal-BrP-ENHg.css"])))=>i.map(i=>d[i]);
2
+ import{l as e}from"./terminal-qBEkzc-m.js";import{c as t,y as n}from"./tabs-Dx-TnbvG.js";import{d as r,t as i}from"./createLucideIcon-CM5xLVj1.js";import{i as a}from"./store-uT65Mask.js";import{t as o}from"./ChatTranscript-DLthbnmB.js";import{t as s}from"./external-link-BwT2u1hD.js";import{t as c}from"./x-7cB9X7Hi.js";import{n as l,t as u}from"./activity-BjTd1D8q.js";import{t as d}from"./use-focus-trap-DNMrlNR0.js";var f=i(`clipboard-check`,[[`rect`,{width:`8`,height:`4`,x:`8`,y:`2`,rx:`1`,ry:`1`,key:`tgr4d6`}],[`path`,{d:`M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2`,key:`116196`}],[`path`,{d:`m9 14 2 2 4-4`,key:`df797q`}]]),p=i(`git-pull-request`,[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M13 6h3a2 2 0 0 1 2 2v7`,key:`1yeb86`}],[`line`,{x1:`6`,x2:`6`,y1:`9`,y2:`21`,key:`rroup`}]]),m=e(n(),1),h=r(),g=(0,m.lazy)(()=>a(()=>import(`./ChatTerminal-MCI1aBbT.js`).then(e=>({default:e.ChatTerminal})),__vite__mapDeps([0,1,2,3,4,5,6,7])));function _({task:e,engine:n,onClose:r,onOpenWorkspace:i,onReview:a,onCreatePr:_}){let[v,y]=(0,m.useState)(`engine`),[b]=(0,m.useState)(()=>t(e.id)),x=(0,m.useRef)(null);d(x,!0),(0,m.useEffect)(()=>{let e=e=>{if(e.key!==`Escape`)return;let t=e.target;t?.closest(`.xterm`)||t&&(t.tagName===`TEXTAREA`||t.tagName===`INPUT`)||(e.preventDefault(),r())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[r]);let S=l(n?.state),C=e=>`border-b-2 px-2 py-1.5 text-[11px] transition-colors ${e?`border-primary text-fg`:`border-transparent text-muted hover:text-fg`}`;return(0,h.jsxs)(`div`,{className:`fixed inset-0 z-40 flex justify-end`,children:[(0,h.jsx)(`button`,{type:`button`,"aria-label":`Close peek`,onClick:r,className:`absolute inset-0 cursor-default bg-black/40`}),(0,h.jsxs)(`div`,{ref:x,role:`dialog`,"aria-modal":`true`,"aria-label":`Session peek: ${e.title||e.branch||e.id}`,className:`relative flex h-full w-[640px] max-w-[92vw] flex-col border-l border-line bg-bg shadow-2xl`,children:[(0,h.jsxs)(`header`,{className:`flex h-10 shrink-0 items-center gap-2 border-b border-line bg-surface px-3`,children:[(0,h.jsx)(`span`,{className:`h-1.5 w-1.5 shrink-0 rounded-full ${u(n?.state)}`}),(0,h.jsx)(`span`,{className:`min-w-0 truncate text-[13px] text-fg`,children:e.title||e.branch||e.id}),(0,h.jsx)(`span`,{className:`hidden min-w-0 truncate font-mono text-[11px] text-subtle sm:inline`,children:e.branch}),S&&(0,h.jsx)(`span`,{className:`shrink-0 text-[11px] text-muted`,children:S}),(0,h.jsxs)(`div`,{className:`ml-auto flex shrink-0 items-center gap-2`,children:[a&&(0,h.jsxs)(`button`,{type:`button`,onClick:a,className:`flex items-center gap-1 text-muted transition-colors hover:text-fg`,title:`Review → done if it passes`,children:[(0,h.jsx)(f,{size:13,strokeWidth:1.8}),(0,h.jsx)(`span`,{className:`text-[11px]`,children:`Review`})]}),_&&(0,h.jsxs)(`button`,{type:`button`,onClick:_,className:`flex items-center gap-1 text-muted transition-colors hover:text-fg`,title:`Open a PR for this branch`,children:[(0,h.jsx)(p,{size:13,strokeWidth:1.8}),(0,h.jsx)(`span`,{className:`text-[11px]`,children:`PR`})]}),(0,h.jsxs)(`button`,{type:`button`,onClick:i,className:`flex items-center gap-1 text-muted transition-colors hover:text-fg`,title:`Open in workspace`,children:[(0,h.jsx)(s,{size:13,strokeWidth:1.8}),(0,h.jsx)(`span`,{className:`text-[11px]`,children:`Workspace`})]}),(0,h.jsx)(`button`,{type:`button`,onClick:r,className:`flex items-center text-muted transition-colors hover:text-fg`,"aria-label":`Close peek`,title:`Close (Esc)`,children:(0,h.jsx)(c,{size:15,strokeWidth:1.8})})]})]}),(0,h.jsxs)(`nav`,{className:`flex shrink-0 items-center gap-1 border-b border-line bg-surface px-2`,children:[(0,h.jsx)(`button`,{type:`button`,onClick:()=>y(`engine`),className:C(v===`engine`),children:`Engine`}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>y(`transcript`),className:C(v===`transcript`),children:`Transcript`})]}),(0,h.jsx)(`div`,{className:`min-h-0 flex-1`,children:v===`engine`?(0,h.jsx)(m.Suspense,{fallback:(0,h.jsx)(`div`,{className:`flex h-full items-center justify-center text-[12px] text-subtle`,children:`Loading terminal…`}),children:(0,h.jsx)(g,{tabId:b,taskId:e.id,mode:`engine`},b)}):(0,h.jsx)(o,{worktreePath:e.worktreePath,vendor:e.vendor??`claude`,title:e.title||e.branch})})]})]})}export{_ as BoardPeek};
@@ -0,0 +1 @@
1
+ .xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}