Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
239 commits
Select commit Hold shift + click to select a range
6cb01f8
feat(web): a Verbose chat setting keeps finished turns open
mubeda Oct 24, 2026
1d91f07
fix(web): picking a branch in Create Worktree closes the list (#151)
mubeda Oct 24, 2026
12630c7
feat(web): make the PR Changes file list resizable
mubeda Oct 24, 2026
2dcfba5
feat(web): open the slash menu for a / typed mid-prompt (#152)
mubeda Oct 24, 2026
0f9e2e7
fix(server): keep a bounded preview of a large Claude tool result (#148)
mubeda Oct 24, 2026
a704546
feat(web): open Activity in one click and keep its button visible
mubeda Oct 24, 2026
b43a7a2
feat(device): add Refresh devices to the device panel (#169)
mubeda Oct 24, 2026
0241fbc
feat(web): step between turns from the minimap and page the timeline …
mubeda Oct 24, 2026
423896f
perf(web): parse and highlight streaming chat markdown incrementally …
mubeda Oct 24, 2026
b83d054
feat(web): update outdated providers on every connected environment
mubeda Oct 24, 2026
e1f04a4
fix(web): a failed Source Control action names its step and Git's rea…
mubeda Oct 24, 2026
929eec4
fix(server): the GitLab merge box names the real block and a refused …
mubeda Oct 24, 2026
bfbac11
docs(activity): record each provider's Activity signals against curre…
mubeda Oct 24, 2026
5211d96
docs(plans): propose designs for the remaining open issues
mubeda Oct 24, 2026
8339bf4
fix(web): tell a resize drag from a press by pointer travel
mubeda Oct 24, 2026
734b4e7
fix(web): end a resize drag when its divider unmounts or loses capture
mubeda Oct 24, 2026
71a14aa
test(web): keep PR Changes selection, Viewed and scroll after a resize
mubeda Oct 24, 2026
4270bf3
docs(plans): approve the ten designs for the remaining issues
mubeda Oct 24, 2026
254d94c
fix(web): reset input modes after replaying an exited terminal
mubeda Oct 24, 2026
7b19f99
Merge branch 'batch/streaming-markdown-incremental' into batch/mermai…
mubeda Oct 24, 2026
4a73dcd
fix(server): keep multiplexer variables and fish's terminal query out…
mubeda Oct 24, 2026
403189f
docs(plans): keep the Pierre undo-boundary patch local
mubeda Oct 24, 2026
24ed166
fix(deps): let Pierre's Editor.applyEdits mark an edit as its own und…
mubeda Oct 24, 2026
9e978b0
fix(client-runtime): a dropped connection after action_failed keeps G…
mubeda Oct 24, 2026
8447a7d
fix(web): count the list header when stepping back through turns
mubeda Oct 24, 2026
483a352
fix(web): the create request dialog names a failed branch or commit s…
mubeda Oct 24, 2026
273fb5b
fix(web): create from a picked branch whose name is a number (#151)
mubeda Oct 24, 2026
3045679
fix(web): clear another project's branch when Create Worktree reopens…
mubeda Oct 24, 2026
d6e019e
fix(web): keep a failing Activity section's error on the button
mubeda Oct 24, 2026
a074609
fix(web): reopen the slash menu when a dismissed word is replaced (#152)
mubeda Oct 24, 2026
918d3d2
fix(web): keep page keys in the draft for selections and wrapped lines
mubeda Oct 24, 2026
3b7d3f6
feat(web): keep the fold rows in Verbose chat, open by default
mubeda Oct 24, 2026
3327a2e
fix(server): GitLab 19.5+ cancels auto-merge through cancel_auto_merg…
mubeda Oct 24, 2026
e70fa41
merge: batch/claude-tool-result-cap into the issue batch
mubeda Oct 24, 2026
b61a58a
merge: batch/terminal-spawn-and-replay into the issue batch
mubeda Oct 24, 2026
81037a9
merge: batch/streaming-markdown-incremental into the issue batch
mubeda Oct 24, 2026
da9644d
merge: batch/pr-changes-resizable-r2 into the issue batch
mubeda Oct 24, 2026
15965f8
merge: batch/timeline-verbose-and-navigation-r2 into the issue batch
mubeda Oct 24, 2026
4b0ab5b
fix(web): reach both Activity sections and refocus the panel on reopen
mubeda Oct 24, 2026
62c9b43
feat(web): follow provider updates with remote server installs in Upd…
mubeda Oct 24, 2026
c50749b
fix(device): offer Refresh devices only on servers that have it (#169)
mubeda Oct 24, 2026
dcfcec0
merge: batch/composer-worktree-devices-r2 into the issue batch
mubeda Oct 24, 2026
4c0212f
feat(server): version open files and refuse saves over newer disk con…
mubeda Oct 24, 2026
95430eb
merge: batch/activity-and-provider-updates-r2 into the issue batch
mubeda Oct 24, 2026
ad1164e
merge: batch/scm-failure-messages-r2 into the issue batch
mubeda Oct 24, 2026
0d7307f
feat(web): reload open files changed on disk and block saves over them
mubeda Oct 24, 2026
b02dfaf
refactor(web): share the chat Markdown pipeline with find in thread
mubeda Oct 24, 2026
402f160
test(web): cover the open-file reload waiting for an IME composition
mubeda Oct 24, 2026
aa41517
feat(web): project chat Markdown to the text find in thread searches
mubeda Oct 24, 2026
98d059d
fix(web): keep find's text walk identical for breaks and hidden copies
mubeda Oct 24, 2026
64a5c8e
feat(server): Codex shows retries and compaction, and compacts on /co…
mubeda Oct 24, 2026
81526d7
feat(server): OpenCode 2 chats get a context meter, compaction and re…
mubeda Oct 24, 2026
b8d3b3c
feat(web): locate a timeline entry behind folds and work groups
mubeda Oct 24, 2026
d457528
fix(server): compute turn diffs live from checkpoint refs
mubeda Oct 24, 2026
a198183
docs(plans): format the GitLab live-pipeline design
mubeda Oct 24, 2026
cb3d4e6
merge: batch/codex-opencode-compaction-surfaces-r2 into the issue batch
mubeda Oct 24, 2026
9a04b02
refactor(web): own every timeline disclosure in one place
mubeda Oct 24, 2026
f09e01a
chore(deps): pin pele and dompurify for Mermaid diagrams
mubeda Oct 24, 2026
a839fb8
refactor(web): move the chat render queue into its own module
mubeda Oct 24, 2026
e574f58
refactor(web): keep chat Markdown components across theme switches
mubeda Oct 24, 2026
8942ba1
feat(web): decide from the parse whether a Mermaid fence is closed
mubeda Oct 24, 2026
99ffa7e
feat(web): draw Mermaid diagrams through an allowlist SVG sanitizer
mubeda Oct 24, 2026
958b48c
feat(web): draw closed Mermaid fences as diagrams in chat Markdown
mubeda Oct 24, 2026
26c825b
feat(web): copy a drawn Mermaid diagram as its fenced source
mubeda Oct 24, 2026
83e7d25
feat(web): keep the reading line in place when a diagram draws
mubeda Oct 24, 2026
ddca750
fix(web): halve the Mermaid source limit to meet the render budget
mubeda Oct 24, 2026
5f95022
test(web): capture Mermaid diagrams and hostile SVG in the typography…
mubeda Oct 24, 2026
66e96d1
test(desktop): check Mermaid diagrams in the packaged app
mubeda Oct 24, 2026
92951ac
docs: describe Mermaid diagrams and their SVG trust boundary
mubeda Oct 24, 2026
1a0e181
perf(web): compute a diagram's copy text once per source
mubeda Oct 24, 2026
8d1dc7b
test(deps): count the ledger rows the Markdown and diagram work added
mubeda Oct 24, 2026
a0fde68
test(privacy): list the web dependencies Markdown and diagrams added
mubeda Oct 24, 2026
0dcf11d
fix(web): commit a late-cached diagram outside React's effect flush
mubeda Oct 24, 2026
e4b75d3
feat(server): store provider reasoning as its own thread entity
mubeda Oct 24, 2026
7bf177a
feat(web): index a thread's displayed text for find in thread
mubeda Oct 24, 2026
29ba495
feat(device): run up to four devices at once, each owned by its threa…
mubeda Oct 24, 2026
bb25d7f
feat(server): read one side of a changed file by its object ID
mubeda Oct 24, 2026
4858f98
fix(device): give each emulator its own console port when several sta…
mubeda Oct 24, 2026
87281c7
fix(web): keep a caret on a changed line when a reload also adds lines
mubeda Oct 24, 2026
3bfd724
fix(web): wait for IME before a deletion and stop re-reading a known …
mubeda Oct 24, 2026
bdb678d
fix(web): guard open files from the server read and keep them past 1 MB
mubeda Oct 24, 2026
abb72db
feat(web): remember the Diff panel's layout across restarts
mubeda Oct 24, 2026
ad66235
fix(server): refuse a pipe without blocking and lock spellings of one…
mubeda Oct 24, 2026
60d650b
fix(web): keep the reload's line pairing linear in the hunk size
mubeda Oct 24, 2026
81e8425
feat(web): model the Diff panel's Compare view
mubeda Oct 24, 2026
727bc42
perf(device): watch every running simulator with one simctl poll (#170)
mubeda Oct 24, 2026
49b43e5
feat(web): find in thread bar, reveal and highlights
mubeda Oct 24, 2026
91d8821
feat(web): add the Diff panel's Compare view
mubeda Oct 24, 2026
e82cf8a
test(desktop): run the Mermaid scenario reliably in the packaged app
mubeda Oct 24, 2026
654cb7c
perf(web): hydrate a Compare file once per version pair
mubeda Oct 24, 2026
a70a09b
fix(orchestration): refuse a chat panel whose host is gone (#141)
mubeda Oct 24, 2026
baed8c6
feat(server): list a thread folder's Claude Code terminal sessions fo…
mubeda Oct 24, 2026
832026d
feat(server): fork a copied Claude session under the ID BiBCode assig…
mubeda Oct 24, 2026
f3f50b4
feat(web): add All lines and Changes only to Compare
mubeda Oct 24, 2026
33ec9b3
feat(web): open find in thread with Mod+F, chat.find and the palette
mubeda Oct 24, 2026
d65cec4
feat(web): add a History menu to the composer (#141)
mubeda Oct 24, 2026
cb31e87
feat(device): stop a deleted thread's devices and keep agents to thei…
mubeda Oct 24, 2026
66ef0c5
feat(contracts): name the thread a device is for (#170)
mubeda Oct 24, 2026
f14bcc4
fix(web): build find's projection worker without the DOM entity decoder
mubeda Oct 24, 2026
f82ff14
docs: describe find in thread, chat.find and its packaged checks
mubeda Oct 24, 2026
f5d6929
test(contracts): regenerate the RPC fixture manifest for chat.find
mubeda Oct 24, 2026
b9b37db
feat(web): move between Compare's changes with F7 and Shift+F7
mubeda Oct 24, 2026
da5eed3
docs: describe the Diff panel's Compare view
mubeda Oct 24, 2026
17981e6
chore(deps): record find in thread's parser packages in the ledger
mubeda Oct 24, 2026
1718f28
test(web): cover find's DOM text walk, ranges and highlight owner
mubeda Oct 24, 2026
61247d5
fix(web): keep an unsent diff comment across Changes and Compare
mubeda Oct 24, 2026
46f69e7
feat(server): project Claude thinking and Codex summaries as coalesce…
mubeda Oct 24, 2026
5a51db1
feat(contracts): add thread reasoning and its shared client model
mubeda Oct 24, 2026
23bdc15
feat(web): show Compare's files as a picker in a narrow panel
mubeda Oct 24, 2026
212a323
test(web): keep the ChatView hook harness in step with find's wiring
mubeda Oct 24, 2026
7e0a3b6
test(server): gate the unix-only Claude event helper (#141)
mubeda Oct 24, 2026
154e970
fix(web): compensate a diagram swap unless the list holds its end
mubeda Oct 24, 2026
1ba8ecc
fix(web): build a diagram's copy text only when it is drawn
mubeda Oct 24, 2026
48292bb
test(web): import the timeline once before find's controller tests
mubeda Oct 24, 2026
9ade2b9
fix(web): hold the reading line when new text replaces a diagram
mubeda Oct 24, 2026
0ebf807
test(desktop): give the Mermaid eviction scenario time to draw
mubeda Oct 24, 2026
9ab3955
test(server): name the reasoning row tuple in the engine test
mubeda Oct 24, 2026
c872ac7
feat(web): show provider reasoning as collapsed Thinking rows
mubeda Oct 24, 2026
b018992
feat(web): give each thread its own device in the Device pane (#170)
mubeda Oct 24, 2026
07364af
test(desktop): cover Thinking rows on the packaged real list
mubeda Oct 24, 2026
da5bd35
docs: describe several devices per environment and their owners (#170)
mubeda Oct 24, 2026
d966b4b
feat(contracts): add the revisioned GitLab pipeline copy
mubeda Oct 24, 2026
bfcc0ea
feat(server): poll a running GitLab pipeline live without the detail …
mubeda Oct 24, 2026
eaf197a
feat(web): show the gating GitLab pipeline in the merge box and Pipel…
mubeda Oct 24, 2026
15eec5f
docs: describe provider reasoning and the Thinking rows
mubeda Oct 24, 2026
2d09976
docs: describe the live GitLab pipeline poller
mubeda Oct 24, 2026
1c4305d
chore: satisfy the lint rules on the reasoning tests and trace
mubeda Oct 24, 2026
bcbd55b
refactor(device): keep a simulator's poll registration with its owner…
mubeda Oct 24, 2026
90b3426
test(web): cover a Device pane that works for its thread's root (#170)
mubeda Oct 24, 2026
28e2fc6
merge: batch/open-file-disk-changes into the issue batch
mubeda Oct 24, 2026
44f788d
test(desktop): tell each turn's thought and answer apart in the reaso…
mubeda Oct 24, 2026
da805ff
fix(web): retire find's navigation on a new query and during IME comp…
mubeda Oct 24, 2026
2bd3207
fix(web): recount find after a first scan that missed a live update
mubeda Oct 24, 2026
bc12fc1
fix(web): share find's pending worker projections between scans
mubeda Oct 24, 2026
aa7a640
fix(web): bound find's ranges to what it paints and drop unmounted rows
mubeda Oct 24, 2026
c0caf1c
fix(web): open find from the palette in the chat the user is looking at
mubeda Oct 24, 2026
802684d
test(server): wait on poller progress instead of a fixed round count
mubeda Oct 24, 2026
f991eda
test(server): cover delete_number removing the pipeline row
mubeda Oct 24, 2026
9c49a9a
fix(web): key the timeline by the scoped thread so find never crosses…
mubeda Oct 24, 2026
33e2e36
docs: say where the palette opens find, and check it in packaged runs
mubeda Oct 24, 2026
d52579d
fix(server): count a process this user cannot inspect as running (#141)
mubeda Oct 24, 2026
3a93fbc
fix(server): tell the later of two concurrent opens where the panel i…
mubeda Oct 24, 2026
de59fc7
feat(contracts): describe conversation compaction on the wire (#160)
mubeda Oct 24, 2026
5c25488
fix(server): keep a cut reasoning entry within its bound, and test it…
mubeda Oct 24, 2026
14f34dc
feat(server): compact a full conversation and send the message again …
mubeda Oct 24, 2026
323b421
feat(web): compact through the server and show a recovery (#160)
mubeda Oct 24, 2026
a52788b
docs: describe context-limit recovery, the guard and compaction (#160)
mubeda Oct 24, 2026
2f9690d
feat(server): open a changed file in a diff app through git difftool
mubeda Oct 24, 2026
3947b09
fix(server): keep a refused resume recorded through shutdown (#141)
mubeda Oct 24, 2026
de2bb35
fix(web): retry a History open under the command it was sent with (#141)
mubeda Oct 24, 2026
ea227d7
feat(web): add Open with to the Diff panel
mubeda Oct 24, 2026
4c94679
docs(plans): format the live pipeline design
mubeda Oct 24, 2026
14c94ef
test(desktop): stream fixture replies one delta per chunk
mubeda Oct 24, 2026
eb4798f
docs: describe the Diff panel's Open with and shutdown survivors
mubeda Oct 24, 2026
ddefc5a
style(web): format the Compare hydration test
mubeda Oct 24, 2026
117b4f1
test(desktop): check the remaining Mermaid timeline cases in the pack…
mubeda Oct 24, 2026
cf7e17b
fix(device): trim a device's owner as the client's ThreadId does (#170)
mubeda Oct 24, 2026
5d11260
test(device): hold a real state-poll listing across boot, stop and re…
mubeda Oct 24, 2026
5fbc38f
docs(testing): give the device limit step a fifth image to pick (#170)
mubeda Oct 24, 2026
e3dc94f
fix(web): offer Compact only where it can compact (#160)
mubeda Oct 24, 2026
20371d7
fix(web): keep the newest pipeline copy across a pull request tab swi…
mubeda Oct 24, 2026
d735351
feat(web): re-read the jobs once for a header-only pipeline row (#156)
mubeda Oct 24, 2026
f93e651
fix(server): hold the whole thread behind an unsettled compaction (#160)
mubeda Oct 24, 2026
71ea7dc
fix(server): bound the compaction request and record every settlement…
mubeda Oct 24, 2026
6ada0e5
docs: describe the compaction gate, bounded request and Compact fallb…
mubeda Oct 24, 2026
89b9de1
fix(server): a sign-in failure on the GitLab totals read ends the pol…
mubeda Oct 24, 2026
912680b
fix(server): keep a GitLab host's 429 backoff past another poller's s…
mubeda Oct 24, 2026
f6529ae
fix(server): retry a GitLab pipeline read that stored no copy (#156)
mubeda Oct 24, 2026
41e5b31
test(server): run the pipeline snapshot read test only where its scri…
mubeda Oct 24, 2026
dc25d82
fix(web): keep a reader's place when a thought toggles away from an a…
mubeda Oct 24, 2026
3990fe4
test(desktop): run the reasoning spec as one test, as the packaged su…
mubeda Oct 24, 2026
0777c0e
fix(server): keep a dropped Open with launch owned, and name reposito…
mubeda Oct 24, 2026
4f7a236
fix(web): keep Compare's states honest after refreshes and failures
mubeda Oct 24, 2026
b24877c
docs: describe Compare's refresh, failure and subdirectory behavior
mubeda Oct 24, 2026
12a2db2
docs(plans): record the live pipeline implementation review fixes (#156)
mubeda Oct 24, 2026
4e2b555
merge: batch/gitlab-live-pipeline-c-r2-r2 into the issue batch
mubeda Oct 24, 2026
eaa640c
test(server): keep the dropped-launch test inside its window
mubeda Oct 24, 2026
5426bf7
fix(web): count a pending re-read, and explain an empty truncated patch
mubeda Oct 24, 2026
867c85c
feat(web): put Pull Requests on the repository row in the Repositorie…
mubeda Oct 24, 2026
2c37a2f
fix(server): keep reasoning text that fits its bound whole
mubeda Oct 24, 2026
48b837d
fix(web): keep following an anchored turn when a press toggles a row
mubeda Oct 24, 2026
76cce3d
feat(web): keep sidebar row actions visible without hover
mubeda Oct 24, 2026
b145de8
test(desktop): press Thinking rows as a pointer and check the end mid…
mubeda Oct 25, 2026
4edf517
merge: batch/find-in-thread-f into the issue batch
mubeda Oct 25, 2026
d189f09
merge: batch/composer-history-r2-f into the issue batch
mubeda Oct 25, 2026
96ed2f8
merge: batch/reasoning-thinking-rows-c-r2 into the issue batch
mubeda Oct 25, 2026
59bbaa0
merge: batch/context-limit-auto-recovery-c-r2 into the issue batch
mubeda Oct 25, 2026
ab30fdf
merge: batch/multiple-device-previews-c-r2 into the issue batch
mubeda Oct 25, 2026
2ca005f
merge: batch/diff-compare-layout-c-r2 into the issue batch
mubeda Oct 25, 2026
6145009
fix(server): build the environment's capabilities apart from its desc…
mubeda Oct 25, 2026
3e353dc
merge: batch/mermaid-diagrams-f into the issue batch
mubeda Oct 25, 2026
367adc8
test(deps): count Find in thread's Markdown dependencies beside Merma…
mubeda Oct 25, 2026
eb64ebe
fix(web): keep Mermaid diagrams out of find in thread
mubeda Oct 25, 2026
dece432
docs(plans): propose the Pipelines module design
mubeda Oct 25, 2026
edf31e4
docs(plans): approve the Pipelines module design
mubeda Oct 25, 2026
8ddc9f5
merge: batch/integration-r3 into the issue batch
mubeda Oct 25, 2026
39a9475
fix(web): make Compare's F7 steps built-in instead of shipped defaults
mubeda Oct 25, 2026
c05d239
fix(web): keep an evicted diagram's drawn height while it draws again
mubeda Oct 25, 2026
722a3cf
fix(web): follow a diagram that grows at the end of the timeline
mubeda Oct 25, 2026
1f90628
test(desktop): check every frame of the Mermaid remount and the strea…
mubeda Oct 25, 2026
3f31712
docs(plans): follow a growth at the end and keep a redrawn diagram's …
mubeda Oct 25, 2026
5a83921
merge: batch/mermaid-diagrams-g into the issue batch
mubeda Oct 25, 2026
0afdb03
feat(server): serve GitLab pipelines reads
mubeda Oct 25, 2026
4d2ff34
feat(web): add the Pipelines list on a shared repository module shell
mubeda Oct 25, 2026
6c33d8f
feat(web): add the pipeline page
mubeda Oct 25, 2026
bd879a5
feat(web): add the Pipelines job page with a worker-parsed log
mubeda Oct 25, 2026
100c75b
merge: slice 3 (pipeline page) into slice 4 (job page)
mubeda Oct 25, 2026
68336b8
feat(web): open a pipeline page's jobs on their job pages
mubeda Oct 25, 2026
21dd6bc
feat(pipelines): read GitHub Actions runs as pipelines
mubeda Oct 25, 2026
d9fd6be
feat(pipelines): retry, cancel and play pipelines and jobs
mubeda Oct 25, 2026
636c729
feat(pipelines): open a merge request's jobs and pipeline in Pipelines
mubeda Oct 25, 2026
0e0ad43
fix(web): keep the newer copy of a pipeline that two list pages share
mubeda Oct 25, 2026
d0efdd1
fix(server): read a finished job's log again after a large running copy
mubeda Oct 25, 2026
7b2e0d7
fix(server): let the pipelines poller replace rows another account st…
mubeda Oct 25, 2026
5063b47
fix(server): release idle job logs on any pipelines read
mubeda Oct 25, 2026
4a0d6b8
fix(server): release shared log tails once their 4 s have passed
mubeda Oct 25, 2026
f0259a6
fix(pipelines): show a pipeline the poller can no longer read as refused
mubeda Oct 25, 2026
aa4e5c8
docs(pipelines): describe refused pipelines and log cache release
mubeda Oct 25, 2026
b2ecd88
refactor(web): take a pipeline refusal from its event during render
mubeda Oct 25, 2026
9932383
merge: batch/pipelines-r2 (Pipelines module) into the issue batch
mubeda Oct 25, 2026
2a1f9bd
fix(server): pause live updates for a downloaded running log over 2 MB
mubeda Oct 25, 2026
47e1a1a
docs: link the upstream Effect issue for the RpcClient interrupt patch
mubeda Oct 25, 2026
6af4e0a
docs(changelog): add the v0.12.0 entry
mubeda Oct 25, 2026
15499ff
fix(server): read the job again for a user log read while it was running
mubeda Oct 25, 2026
4cdc047
fix(web): find a streaming diagram's source while its closing fence e…
mubeda Oct 25, 2026
dbb7526
fix(web): mark disconnected environments in the repository row's picker
mubeda Oct 25, 2026
5a3a1d1
fix(server): a finished log read that waited on a running download re…
mubeda Oct 25, 2026
58922c9
style(web): format the repository-row picker
mubeda Oct 25, 2026
6ccbfa9
test(server): expect the provider reason on a failed OpenCode turn
mubeda Oct 25, 2026
c6e50e0
test(web): give the typography diff fixtures an Open with command
mubeda Oct 25, 2026
8921614
fix(web): finish a job log after an earlier read and cap forward reads
mubeda Oct 25, 2026
9277a64
test(server): gate Unix-only test helpers for the Windows build
mubeda Oct 26, 2026
a9c4b51
fix(server): give git a Windows-safe checkpoint index path
mubeda Oct 26, 2026
faaddda
fix(server): report a missing working folder as not found on Windows
mubeda Oct 26, 2026
8af9222
fix(server): spell panic sites with forward slashes on every OS
mubeda Oct 26, 2026
5a813df
fix(server): see entries a directory gains within one clock tick
mubeda Oct 26, 2026
adc4058
test(server): make the server suite pass on Windows
mubeda Oct 26, 2026
dbd2920
test(server): fail the refused-resume fixture after its message arrives
mubeda Oct 26, 2026
aaa9d3a
chore(release): prepare v0.12.0
mubeda Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
92 changes: 92 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,97 @@
# Changelog

## [v0.12.0] - 2026-10-26

BiBCode v0.12.0 adds a Pipelines module for GitLab pipelines and GitHub Actions runs, with a page for each pipeline and each job's log. Chats gain Thinking rows for Claude and Codex reasoning, Mermaid diagrams, find in thread, a History menu for past chats and Claude Code terminal sessions, and recovery from a full context window: BiBCode compacts the conversation and sends your message again. The Diff panel gains a side-by-side Compare view and Open with for your diff app, open files reload when an agent changes them on disk, the Device panel runs up to four devices at once, and a failed Source Control action now names the step that failed, with Git's reason. This release includes the changes since v0.11.0.

### Pipelines

- A new Pipelines module lists a repository's GitLab pipelines or GitHub Actions runs, with filters for status, branch or tag and, on GitHub, workflow. Open it from the Pipelines button next to Git Manager and Pull Requests, or from the repository row in the Repositories view.
- A pipeline's page shows its status, commit, branch and times, with its stages and jobs side by side on a wide panel and stacked on a narrow one. A job's page shows its log with colors, timestamps, collapsible sections and search, and a 100,000-line log stays responsive.
- Retry, Cancel and Run work for pipelines and jobs on both hosts. A merge request's Pipelines tab and merge box open a job or its pipeline in Pipelines, with a link to the host beside it.
- GitLab pipelines and running job logs update live. GitHub runs refresh while the page is open; a running GitHub job shows its steps, with its log on GitHub until the job finishes.
- A pipeline you can no longer view says so instead of showing an old copy.
- **Settings → Source Control → Pipelines** turns the module off.

### Pull requests

- A GitLab merge request's merge box and Pipelines tab show the pipeline it waits on as it runs: its status, commit, branch and a strip of stages. A pipeline that ran before the latest push is marked "Older commit". (#156)
- The merge box names the real reason a GitLab merge is blocked, instead of "GitLab is still computing mergeability". Under "Pipelines must succeed" it says when no pipeline is visible, when one waits for a manual job, or when it was skipped or canceled. (#156)
- **Disable auto-merge** on GitLab now fails when GitLab refuses it, instead of reporting success, and uses the newer endpoint on GitLab 19.5 and later. (#156)
- The Changes tab's file list can be resized by dragging its divider or with the arrow keys, so long paths are easier to tell apart. Double-click resets it. (#153)

### Sidebar

- In the Repositories view, the Pull Requests and Pipelines buttons sit on the repository row instead of on each environment row inside it. With several environments, BiBCode asks which one to read from. The Environments view keeps them on each row.
- Row action icons are always visible instead of appearing on hover. A chat row's Archive still appears on hover.

### Claude

- When a conversation fills the context window, BiBCode compacts it and sends your message again, so you no longer compact and resend by hand. A message that would start close to Claude's own compaction point is sent after a compaction. While a compaction runs, new messages wait in the queue and Stop is offered. (#160)
- A large tool result, such as a command that printed megabytes, is kept as a 16 KiB preview in the chat instead of being sent to every client that opens the thread. The full result stays in Claude's own transcript. (#148)

### Codex

- Codex retries show as warnings while they happen, a compaction shows as a step in the turn, and `/compact` compacts the conversation. A full context window now offers **Compact conversation** and recovers the same way as Claude. (#163)

### OpenCode

- OpenCode 2 chats have a context meter, `/compact`, a compaction step in the turn, and a warning when OpenCode retries an upstream error. (#164)

### Chat

- Claude thinking and Codex reasoning summaries show as collapsed "Thought" rows among the tool calls, "Thinking" while they stream. Click one to read the full trace. The working row shows the latest thought, and Claude's thinking no longer shows as a second answer or leaves a turn reading "(empty response)". (#173)
- Mermaid diagrams in replies, plans and rendered Markdown files are drawn once their fence is closed. **Show source** switches back to the source, Copy copies the fenced source, and drawing a diagram no longer moves the line you are reading. Links and images in diagrams are not drawn. (#171)
- **Find in thread** (Cmd+F or Ctrl+F in a chat, or from the command palette) searches a chat's messages, plans and tool commands, including folded turns and rows scrolled out of view, and opens what hides each match. (#175)
- **History** in the composer lists the thread's closed chats and the Claude Code sessions started in a terminal in the same folder. **Continue** picks one up in a chat panel. A session still open in a terminal is continued in a copy, so two programs never write one conversation. (#141)
- **Settings → General → Verbose chat** keeps finished turns and tool calls open. Turns and tool groups can still be folded, and your choice stays when a row scrolls away. Tool rows show their time on hover. (#142)
- The minimap has Previous turn and Next turn buttons, and PageUp and PageDown in the composer scroll the chat when the draft has no use for them. (#176)
- The `/` menu opens for a `/` typed mid-prompt, not only at the start of a line. Escape closes the `/`, `@`, `$` and `:` menus for the word being typed. (#152)
- The Activity button opens the Activity panel in one click, on the section that needs attention. **Always show Activity** (on by default) keeps the button on a chat before any activity, and the panel has Subagents and Background tasks tabs when both are running. (#143)
- Streaming replies with code are much lighter: a 15,600-character reply took 2.3 ms per update instead of 16.9 ms, and blocks keep their state, such as line wrap, while text arrives. Ported from upstream PRs 11193, 11196 and 11198. (#172)

### Diff

- A **Compare** view shows one file's previous and current versions side by side in full, beside a list of the changed files with name and status filters. **Changes only** shows changed lines with the context you choose, F7 and Shift+F7 move between changes, and a narrow panel shows the files as a picker. (#140)
- **Open with** opens a file, or the whole change, in a diff app Git knows, such as Beyond Compare, Meld or WinMerge. The app opens on the server's computer and stays open when BiBCode quits. (#140)
- The panel remembers Stacked or Split, and an unsent comment survives switching between Changes and Compare. (#140)
- A turn's changes show again; every turn read "No net changes". (#140)

### Files

- An open file that changes on disk, for example when an agent edits it, now reloads in place if you have no unsaved edits, and Undo brings back the old text. With unsaved edits, a bar offers **Reload from disk** or **Overwrite disk**, and no save writes over the newer file. Before, the next save overwrote the agent's work. (#180)
- A file deleted on disk shows "Deleted on disk", and a background tab with a conflict shows a dot.

### Git and worktrees

- A failed Source Control action is titled by its step, such as "Push failed" or "Commit failed", and shows Git's reason, instead of "failed during execution". The reason stays when the connection drops right after the failure. (#174)
- The dialog that commits, pushes and creates a pull or merge request names a failed branch or commit step, such as a rejecting pre-commit hook, instead of blaming the request. (#174)
- In **Create Worktree**, picking a branch fills the field and closes the list, a branch whose name is a number is created from that branch, and reopening the dialog for another project clears the field. (#151)

### Terminal

- New terminals no longer inherit tmux, screen or Zellij variables from the server, and fish 4.1 and later no longer waits at startup for a terminal reply. (#149)
- Reopening a terminal whose shell exited no longer leaves mouse tracking or bracketed paste on, which typed escape codes into the next shell. (#150)

### Device previews

- Up to four devices can run at once in an environment, in any mix of Android and iOS. Each thread shows its own device, the picker says which thread started each one, and deleting a thread stops its devices. Agents act only on their own thread's devices. (#170)
- **Refresh devices** finds a device created in Android Studio or Xcode without restarting BiBCode. It shows only on servers that support it. (#169)

### Providers

- **Settings → Providers → Update all** updates outdated providers on every connected environment, then installs a remote server's update where its host offers one. Every skipped environment is listed with its reason. (#147)

### Upgrade notes

- This version adds store migrations 55 and 56 for Thinking rows and compaction. They are one-way: once v0.12.0 has run, an older BiBCode cannot open the store. (#160, #173)

### Known limitations

- OpenCode conversations do not compact automatically, and the thread error does not offer **Compact conversation** for them; type `/compact` in an OpenCode 2 chat instead.
- GitHub pipelines refresh on a timer rather than live, and a running GitHub job's log is shown only on GitHub.
- Find in thread does not search tool output or drawn diagrams.

## [v0.11.0] - 2026-10-23

BiBCode v0.11.0 moves the desktop to Tauri 2.11.6, which closes a High-severity IPC advisory, moves the toolchain and every dependency line to current releases (Effect 4.0 stable, Vite+ 1.1, Vitest 5, Node 26.12.1, Rust 1.98.1), and fixes twelve bugs: Claude chats that stopped at a full context window or after `/compact`, Claude follow-up turns cut off by idle suspension, a webview that grew with every streamed tool input, Codex errors that were never classified, Push on a branch that tracks a differently named remote branch, dialogs that lost their input on an outside click, and memory figures on macOS that were about 3.5 times too high. This release includes the changes since v0.10.2.
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 16 additions & 90 deletions apps/desktop/e2e/specs/chat-activity-panel.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,18 +191,6 @@ async function openMaterializedFixtureChat(): Promise<{
);
}
await expect(browser.$('[data-testid="activity-dock"]')).toBeDisplayed();
const expandedSummary = browser.$(
`button[aria-label="${desktopActivityAccessibleNames.expandedSummary}"]`,
);
if (await expandedSummary.isExisting()) {
await focusDesktopUiElement(
`button[aria-label="${desktopActivityAccessibleNames.expandedSummary}"]`,
);
await sendFocusedKeyboardKey("Escape");
await browser
.$(`button[aria-label="${desktopActivityAccessibleNames.collapsedSummary}"]`)
.waitForExist();
}
return materialized;
}

Expand Down Expand Up @@ -317,9 +305,7 @@ async function assertActivityPresentation(width: 960 | 980 | 981 | 1_199 | 1_200
const dock = [
...document.querySelectorAll<HTMLElement>('[data-testid="activity-dock"]'),
].find((candidate) => candidate.closest("[data-provider-terminal-activity-host]") === null);
const summary = dock?.querySelector<HTMLButtonElement>(
'button[aria-label^="Expand activity summary"]',
);
const summary = dock?.querySelector<HTMLButtonElement>('button[aria-label^="Open Activity"]');
if (!dock || !summary) throw new Error("The chat activity summary is missing.");
return {
activeCounts: [...summary.querySelectorAll('[data-activity-count="active"]')].map(
Expand All @@ -329,31 +315,19 @@ async function assertActivityPresentation(width: 960 | 980 | 981 | 1_199 | 1_200
(element) => element.textContent?.trim() ?? "",
),
glyphCount: summary.querySelectorAll("[data-activity-provider-glyph]").length,
text: summary.textContent ?? "",
separatorCount: summary.querySelectorAll("[data-activity-count-separator]").length,
};
});
// The compact layout separates the counts with a dot; the wide one does not.
const expectedSeparators = width < 1_200 ? 1 : 0;
await browser.waitUntil(
async () => {
const candidate = await readPresentation();
return width < 1_200
? candidate.activeCounts.length === 1
: candidate.activeCounts.length === 0;
},
async () => (await readPresentation()).separatorCount === expectedSeparators,
{ timeoutMsg: `Activity dock presentation did not settle at ${width}px.` },
);
const presentation = await readPresentation();
expect(presentation.glyphCount).toBe(1);
if (width < 1_200) {
expect(presentation.activeCounts).toEqual(["Active 2"]);
expect(presentation.doneCounts).toEqual(["Done 0"]);
expect(presentation.text).toContain("Active 2");
expect(presentation.text).toContain("Done 0");
} else {
expect(presentation.activeCounts).toEqual([]);
expect(presentation.doneCounts).toEqual([]);
expect(presentation.text).toContain("Active 2");
expect(presentation.text).toContain("Done 0");
}
expect(presentation.activeCounts).toEqual(["Active 2"]);
expect(presentation.doneCounts).toEqual(["Done 0"]);
}

async function openCodexProviderTerminal(): Promise<string> {
Expand Down Expand Up @@ -497,27 +471,6 @@ async function expectMissing(selector: string): Promise<void> {
expect(await element.isExisting()).toBe(false);
}

async function readPersistedProjectDockExpanded(projectId: string): Promise<{
readonly expanded: boolean;
readonly projectKey: string;
}> {
return browser.execute((id: string) => {
const projectKey = `primary:${id}`;
const encoded = window.localStorage.getItem("bibcode:activity-dock-state:v1");
const persisted = encoded
? (JSON.parse(encoded) as {
readonly state?: {
readonly expandedByProject?: Readonly<Record<string, boolean>>;
};
})
: null;
return {
expanded: persisted?.state?.expandedByProject?.[projectKey] === true,
projectKey,
};
}, projectId);
}

async function tabTo(
matches: (element: DesktopUiFocusedElement) => boolean,
direction: "forward" | "backward" = "forward",
Expand All @@ -536,11 +489,11 @@ async function tabToDockSummary(): Promise<void> {
const startingFocus = await focusDesktopUiElement('button[aria-label="Toggle right panel"]');
expect(startingFocus.ariaLabel).toBe("Toggle right panel");
const arrived = await tabTo(
(element) => element.ariaLabel === desktopActivityAccessibleNames.collapsedSummary,
(element) => element.ariaLabel === desktopActivityAccessibleNames.dock,
);
expect(arrived).toEqual(
expect.objectContaining({
ariaLabel: desktopActivityAccessibleNames.collapsedSummary,
ariaLabel: desktopActivityAccessibleNames.dock,
tagName: "BUTTON",
}),
);
Expand All @@ -555,7 +508,7 @@ async function openSubagentsWithKeyboard(): Promise<{
}> {
await tabToDockSummary();
const enter = await sendFocusedKeyboardKey("Enter");
expect(enter.before.ariaLabel).toBe(desktopActivityAccessibleNames.collapsedSummary);
expect(enter.before.ariaLabel).toBe(desktopActivityAccessibleNames.dock);
const enterEvidence = enter.transport === "webdriver" ? enter.driver : enter.synthetic;
expect(enterEvidence).toEqual(
expect.objectContaining({
Expand All @@ -572,20 +525,9 @@ async function openSubagentsWithKeyboard(): Promise<{
keyup: 0,
});
}
await browser
.$(`button[aria-label="${desktopActivityAccessibleNames.expandedSummary}"]`)
.waitForExist();
const subagents = await sendFocusedKeyboardKey("Tab");
expect(subagents.after).toEqual(
expect.objectContaining({
activitySection: "subagents",
ariaLabel: desktopActivityAccessibleNames.subagents,
tagName: "BUTTON",
}),
);
const open = await sendFocusedKeyboardKey("Enter");
expect(open.before.activitySection).toBe("subagents");
// One press opens the panel on Subagents, the section with running work.
await browser.$("[data-activity-panel]").waitForExist();
await browser.$('section[aria-label="Subagents"]').waitForExist();
return {
enterEvidence: {
click: enterEvidence!.click,
Expand Down Expand Up @@ -977,17 +919,11 @@ describe("packaged responsive activity experience", () => {
await expect(browser.$("[data-activity-panel]")).toBeDisplayed();
await expect(browser.$('section[aria-label="Subagents"]')).toBeDisplayed();

await focusDesktopUiElement(
`button[aria-label="${desktopActivityAccessibleNames.collapsedSummary}"]`,
);
// A second press with the panel already open keeps it open on the same section.
await focusDesktopUiElement(`button[aria-label="${desktopActivityAccessibleNames.dock}"]`);
await sendFocusedKeyboardKey("Enter");
await browser
.$(`button[aria-label="${desktopActivityAccessibleNames.expandedSummary}"]`)
.waitForExist();
expect(await readPersistedProjectDockExpanded(materialized.projectId)).toEqual({
expanded: true,
projectKey: `primary:${materialized.projectId}`,
});
await expect(browser.$("[data-activity-panel]")).toBeDisplayed();
await expect(browser.$('section[aria-label="Subagents"]')).toBeDisplayed();
await setDesktopUiWindowSize(960, 720);
await expect(browser.$('[role="dialog"] [data-activity-panel]')).toBeDisplayed();
expect(
Expand All @@ -997,16 +933,6 @@ describe("packaged responsive activity experience", () => {
tagName: "BUTTON",
}),
);
const collapse = await sendFocusedKeyboardKey("Escape");
expect(collapse.before.tagName).toBe("BUTTON");
await expect(browser.$('[role="dialog"] [data-activity-panel]')).toBeDisplayed();
await browser
.$(`button[aria-label="${desktopActivityAccessibleNames.collapsedSummary}"]`)
.waitForExist();
expect(await readPersistedProjectDockExpanded(materialized.projectId)).toEqual({
expanded: false,
projectKey: `primary:${materialized.projectId}`,
});
expect(
await browser.execute(() => document.activeElement?.closest('[role="dialog"]') !== null),
).toBe(true);
Expand Down
Loading
Loading