pql: refetch ticket + decision sidebars when the workspace opens (T-352)
On a desktop launch the daemon's PqlClient boots with workDir set to the launch CWD (e.g. HOME), not the repo — swapIpcServer only rewires it once the project opens. The tickets and decisions panes fire their first pql fetch before that swap, so pql runs in the wrong directory against a stale/global pql.db and the pane errors (observed: "ticket_deps.blocker_record_id missing — pql.db is from an earlier schema"). A manual refresh worked because by then the workspace was open. This is a wrong-workDir timing issue, not db-busy, so the T-350 retry doesn't catch it. Both panes now re-fetch on ProjectOpened, which fires after the IPC server swaps to the project workRoot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ class _DecisionsViewState extends State<DecisionsView> {
|
||||
StreamSubscription<Message>? _focusSub;
|
||||
StreamSubscription<DaemonEvent>? _fileSub;
|
||||
StreamSubscription<SchedulerTick>? _schedulerSub;
|
||||
StreamSubscription<ProjectOpened>? _projectSub;
|
||||
bool _refreshing = false;
|
||||
bool _pendingRefresh = false;
|
||||
|
||||
@@ -37,6 +38,12 @@ class _DecisionsViewState extends State<DecisionsView> {
|
||||
.where((e) => e.subsystem == 'files' && e.kind == 'files.changed' && _isDecisionPath(e.data['path'] as String? ?? ''))
|
||||
.listen((_) => _refresh());
|
||||
_schedulerSub = kernel.events.on<SchedulerTick>().where((e) => e.tier == SchedulerTier.oneMinute).listen((_) => _refresh());
|
||||
// The first load can fire before the project's workspace is wired into
|
||||
// the daemon (the boot workDir is the launch CWD, not the repo), so pql
|
||||
// runs against the wrong/old DB and the list errors. Re-fetch once the
|
||||
// workspace is actually open — ProjectOpened fires after the IPC server
|
||||
// swaps to the project workRoot. (T-352)
|
||||
_projectSub = kernel.events.on<ProjectOpened>().listen((_) => _refresh());
|
||||
}
|
||||
if (!_loading || _decisions.isNotEmpty) return;
|
||||
unawaited(_load());
|
||||
@@ -88,6 +95,7 @@ class _DecisionsViewState extends State<DecisionsView> {
|
||||
_focusSub?.cancel();
|
||||
_fileSub?.cancel();
|
||||
_schedulerSub?.cancel();
|
||||
_projectSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ class _TicketsViewState extends State<TicketsView> {
|
||||
StreamSubscription<Message>? _focusSub;
|
||||
StreamSubscription<SchedulerTick>? _schedulerSub;
|
||||
StreamSubscription<Message>? _changedSub;
|
||||
StreamSubscription<ProjectOpened>? _projectSub;
|
||||
bool _refreshing = false;
|
||||
bool _pendingRefresh = false;
|
||||
|
||||
@@ -111,6 +112,12 @@ class _TicketsViewState extends State<TicketsView> {
|
||||
}));
|
||||
});
|
||||
_schedulerSub = kernel.events.on<SchedulerTick>().where((e) => e.tier == SchedulerTier.oneMinute).listen((_) => _refresh());
|
||||
// The first load can fire before the project's workspace is wired into
|
||||
// the daemon (the boot workDir is the launch CWD, not the repo), so pql
|
||||
// runs against the wrong/old DB and the list errors. Re-fetch once the
|
||||
// workspace is actually open — the daemon's pql workDir is correct by
|
||||
// then (ProjectOpened fires after the IPC server swaps). (T-352)
|
||||
_projectSub = kernel.events.on<ProjectOpened>().listen((_) => _refresh());
|
||||
}
|
||||
if (!_loading || _tickets.isNotEmpty) return;
|
||||
unawaited(_load());
|
||||
@@ -121,6 +128,7 @@ class _TicketsViewState extends State<TicketsView> {
|
||||
_focusSub?.cancel();
|
||||
_changedSub?.cancel();
|
||||
_schedulerSub?.cancel();
|
||||
_projectSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user