2 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.8 4fa4ce1bac release v2.3.2
Patch release: the real fix for the ticket/decision sidebars failing on
first load — IPC-server swaps are now serialized so the repo workspace
bind always wins over the boot launch-CWD bind (T-352). Supersedes the
partial 2.3.1 re-fetch-on-open, which is kept for mid-session switches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 08:45:17 +02:00
jpmschweitzerandClaude Opus 4.8 7d951a247f main: serialize IPC-server swaps so the repo bind wins (T-352)
The 2.3.1 fix (re-fetch the pql sidebars on ProjectOpened) only helped
the picker-first path, where the project opens after the window is up.
With sticky-startup the project opens during boot, before the panes
mount and subscribe, so they never received the event — the sidebars
stayed broken.

Root cause is a race in the IPC-server lifecycle. The boot factory fires
swapIpcServer(launchCwd) with unawaited(); the project-open flow then
fires swapIpcServer(repo). Each swap stops the live server, binds a new
one, and reconnects the daemon client. Unserialized, the two interleave
and the late-finishing boot swap can clobber the repo bind, reconnecting
the client to the launch-CWD (HOME) socket. The daemon's PqlClient (and
git/files) then run against the wrong workspace, so the first
pql.tickets.list hits a stale/global pql.db and errors
("ticket_deps.blocker_record_id missing — pql.db is from an earlier
schema"). A manual refresh worked because by then things had settled.

Chain every swap on a serialization Future so they apply in call order;
the repo swap is issued last and therefore wins. Kept the pane re-fetch
from 2.3.1 — it still covers genuine mid-session project switches.

Verified app boot is unaffected (test/app_test.dart green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 08:44:17 +02:00
4 changed files with 37 additions and 3 deletions
+14
View File
@@ -16,6 +16,20 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit.
## [Unreleased]
## [2.3.2] — 2026-06-11
### Fixed
- **Ticket and decision sidebars reliably load on first open (real fix).** The
2.3.1 re-fetch-on-open helped only when a project is picked *after* the window
is up; with sticky-startup the project opens during boot, before the panes
mount, so they never saw the event. The underlying cause was a race: the boot
IPC-server swap (to the launch CWD) and the project-open swap (to the repo)
ran concurrently, and the late-finishing boot swap could clobber the repo
bind — leaving the daemon's pql/git/files pointed at the launch directory
(HOME) and the sidebars erroring on a stale/global pql.db. Swaps are now
serialized so the repo bind always wins. (T-352)
## [2.3.1] — 2026-06-10
### Fixed
+1 -1
View File
@@ -39,7 +39,7 @@ self:
# Auto-synced from pubspec.yaml `version:` by `make gen-build-info`
# (runs implicitly on every build/run/test). Don't hand-edit; bump
# pubspec instead.
version: "2.3.1"
version: "2.3.2"
homepage: https://github.com/postmeridiem/clide
license: MIT
license_file: assets/LICENSE
+21 -1
View File
@@ -116,7 +116,11 @@ Future<void> main() async {
McpServer? mcpServer;
final ipcLog = Logger();
Future<void> swapIpcServer(DaemonDispatcher dispatcher, Directory workRoot) async {
// IPC-server swaps must run one-at-a-time — see the swapIpcServer wrapper
// below doSwapIpcServer for why. (T-352)
Future<void> swapChain = Future<void>.value();
Future<void> doSwapIpcServer(DaemonDispatcher dispatcher, Directory workRoot) async {
if (kIsWeb) return;
// Already serving this exact workspace? Reuse the live server.
// The startup factory binds the launch CWD, then the project-open
@@ -173,6 +177,22 @@ Future<void> main() async {
}
}
// Serialize IPC-server swaps. The boot factory fires a swap to the launch
// CWD with unawaited(); the project-open flow then fires another to the
// real repo. Unserialized, the two interleave and the late-finishing boot
// swap can clobber the repo bind — reconnecting the daemon client to the
// launch-CWD (HOME) socket, so pql/git/files run against the wrong
// workspace. That surfaced as the ticket/decision sidebars failing on first
// load (stale/global pql.db) yet working after a manual refresh. Chaining
// every swap makes them apply in call order; the repo swap is issued last
// and therefore wins. (T-352)
Future<void> swapIpcServer(DaemonDispatcher dispatcher, Directory workRoot) {
final next = swapChain.then((_) => doSwapIpcServer(dispatcher, workRoot));
// A failed swap must not break the chain for the next one.
swapChain = next.catchError((Object _) {});
return next;
}
DaemonDispatcher buildDispatcher(
DaemonBus events,
Toolchain tc,
+1 -1
View File
@@ -13,7 +13,7 @@ description: >-
subsystem handlers (pane, files, editor, git, pql), and the
extension framework.
publish_to: none
version: 2.3.1
version: 2.3.2
repository: https://github.com/postmeridiem/clide
# Short user-facing tagline (the welcome subtitle, web meta
# description, etc.). Baked into lib/src/build_info.g.dart by