Skip to content

Stability Improvements, KPI/Filter/Search Fixes, and Column Reordering#11

Open
drkatz wants to merge 36 commits intow3dev33:masterfrom
drkatz:pr/stability-kpi-filter-search-improvements-upstream
Open

Stability Improvements, KPI/Filter/Search Fixes, and Column Reordering#11
drkatz wants to merge 36 commits intow3dev33:masterfrom
drkatz:pr/stability-kpi-filter-search-improvements-upstream

Conversation

@drkatz
Copy link
Copy Markdown

@drkatz drkatz commented Mar 7, 2026

Summary

This PR consolidates a broad set of improvements focused on application stability under heavy update churn, dashboard/KPI correctness, filter/search behavior consistency, and issues table usability.

The scope includes backend watcher and polling pipeline hardening, UI diagnostics and stress tooling, KPI/filter logic fixes, search behavior fixes, and table column reordering support.

What Was Fixed

  1. Fixed refresh pipeline contention by replacing debounce/isProcessing flow with a queue-based single-flight model in app/composables/useChangeDetection.ts.
  2. Fixed high-churn freeze risk by adding poll backpressure scheduling in app/composables/usePollScheduler.ts and integrating it in app/pages/index.vue.
  3. Fixed stale blocked indicators after blockers close by correcting blocked-state handling in app/composables/useIssues.ts and app/utils/issue-helpers.ts.
  4. Fixed blocked/open/workflow mismatch in KPI stats and filtering logic in app/utils/issue-helpers.ts, app/components/dashboard/DashboardContent.vue, and app/pages/index.vue.
  5. Fixed Open KPI filtering to exclude dependency-blocked issues when appropriate in app/utils/issue-helpers.ts.
  6. Fixed blockedBy mapping from dependencies in server transformation logic in server/utils/bd-transformers.ts.
  7. Fixed filter dropdown active-state rendering by switching to :model-value usage in filter dropdown components under app/components/issues/*FilterDropdown.vue.
  8. Fixed active filter chips visibility during search in app/components/issues/IssueListPanel.vue.
  9. Fixed search behavior so search respects active filters instead of bypassing them in app/utils/issue-helpers.ts.
  10. Fixed left-panel KPI card ring clipping, truncation, and responsive sizing issues in app/components/dashboard/KpiCard.vue, app/components/dashboard/DashboardContent.vue, and app/pages/index.vue.
  11. Fixed top-right header/window controls spacing/rendering behavior in app/components/layout/AppHeader.vue with related platform-side adjustments in src-tauri/src/lib.rs and src-tauri/tauri.conf.json.
  12. Removed obsolete deleted-status handling across filtering and display paths in app/components/issues/*, app/composables/*, app/utils/issue-helpers.ts, and src-tauri/src/lib.rs.

What Was Added

  1. Added watcher/poll diagnostics infrastructure via app/composables/usePipelineDiagnostics.ts.
  2. Added diagnostics UI in app/components/layout/DebugPanel.vue.
  3. Added churn stress test coverage in tests/composables/churn-stress.test.ts.
  4. Added scheduler diagnostics and behavior tests in tests/composables/usePollScheduler.test.ts and tests/composables/usePipelineDiagnostics.test.ts.
  5. Added queue/change-detection tests in tests/composables/useChangeDetection.test.ts.
  6. Added churn stress runbook and helper script in docs/churn-stress-runbook.md and scripts/churn-stress.sh.
  7. Added dashboard quick-list “Copy ID” action in app/components/dashboard/QuickList.vue.
  8. Added column drag-and-drop reordering in app/components/issues/ColumnConfig.vue with persistence support in app/composables/useColumnConfig.ts.
  9. Added “All” KPI interaction that applies all status filters in app/composables/useFilters.ts and app/pages/index.vue.

What Was Refined

  1. Refined KPI defaults and ordering, including workflow-first behavior and “Total” rename to “All” in app/components/dashboard/DashboardContent.vue and app/pages/index.vue.
  2. Refined blocked-by presentation by moving details into StatusBadge tooltip and removing redundant icon usage in issue table/details components.

Validation

  1. pnpm test passes.
  2. pnpm build passes.
  3. Branch history preserves commit granularity while being rebased onto current upstream master to enable clean PR comparison.

Devon and others added 30 commits March 7, 2026 16:04
…dler

Replaces the debounce + isProcessing pattern in both watcher and SSE
backends with a shared createQueuedHandler that guarantees:
- At most one onChanged() in flight at any time
- Exactly one follow-up rerun when events arrive during processing
- Bounded consecutive reruns (max 5) to prevent unbounded loops
- Self-write cooldown still respected

Closes beads-task-issue-tracker-mtu.2

Amp-Thread-ID: https://ampcode.com/threads/T-019cbff6-d495-705b-bcf7-1f2af08ac9e5
Co-authored-by: Amp <amp@ampcode.com>
…gh churn

Introduce usePollScheduler composable that gates all poll triggers (watcher,
adaptive timer) through a shared backpressure gate with configurable min
interval (default 2s). This prevents expensive pollForChanges() from running
in tight loops during sustained .beads file churn.

- requestPoll() enforces min interval, defers excess triggers
- requestImmediatePoll() bypasses gate for manual refresh
- Deduplicates rapid triggers (first defers, rest skip)
- Lightweight instrumentation via stats (executed/skipped/deferred counters)
- 6 unit tests covering all scheduler behaviors

Closes: beads-task-issue-tracker-mtu.3
Amp-Thread-ID: https://ampcode.com/threads/T-019cbff9-c082-734b-9377-29bcc2c5a2b2
Co-authored-by: Amp <amp@ampcode.com>
- Create usePipelineDiagnostics composable tracking watcher batches,
  emitted/suppressed events, poll start/finish/duration, deferred runs,
  mtime check hit rate, and self-write cooldown skips
- Instrument usePollScheduler, useChangeDetection, and pollForChanges
  with diagnostic recording calls
- Add Pipeline tab to DebugPanel with compact 4-column diagnostic view
  (Watcher, Scheduler, Poll execution, Mtime check) with color-coded
  values and auto-refresh
- Rate-limit console.debug logging to at most once per 5 seconds
- Add 11 unit tests for the diagnostics composable

Closes beads-task-issue-tracker-mtu.4

Amp-Thread-ID: https://ampcode.com/threads/T-019cbfff-8830-77cf-ac91-503d663048a1
Co-authored-by: Amp <amp@ampcode.com>
- Add vitest churn stress tests validating bounded pipeline behavior
  under sustained rapid triggers (500+ events over simulated time)
- Add shell script for manual/CI .beads write churn generation
- Add comprehensive runbook with reproduction steps, expected metrics,
  tuning guide, and rollback instructions

Amp-Thread-ID: https://ampcode.com/threads/T-019cc007-348f-77a7-9ec1-8892d5020d9d
Co-authored-by: Amp <amp@ampcode.com>
On non-macOS platforms, window manager controls (close/minimize/maximize)
are positioned top-right and overlap the app header's action buttons.
Detect platform and apply pr-20 + right-20 positioning on Linux/Windows
(mirroring the pl-20 used for macOS traffic lights on the left).

Fixes: beads-task-issue-tracker-xqu
Amp-Thread-ID: https://ampcode.com/threads/T-019cc00d-7739-767c-8980-9bcbb92470ad
Co-authored-by: Amp <amp@ampcode.com>
Replace 'truncate' with 'leading-tight' on KpiCard title so labels
like 'In Progress' display fully instead of being ellipsized.

Fixes: beads-task-issue-tracker-8rm
Amp-Thread-ID: https://ampcode.com/threads/T-019cc9ca-cb73-77f1-8ec6-29caee0e69c5
Co-authored-by: Amp <amp@ampcode.com>
Remove overflow-x-auto and add p-0.5/-m-0.5 padding/margin to KPI grid
containers so ring-2 box-shadow renders fully visible on all edges.
Applied to both desktop sidebar and mobile DashboardContent grids.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc9c6-c90e-730e-a74b-cb509cf49f78
Co-authored-by: Amp <amp@ampcode.com>
Switch from grid-cols-5 to flex-wrap so tiles have heterogeneous
widths. Use whitespace-nowrap instead of truncate so labels like
'In Progress' stay on one line. Remove w-full so tiles shrink-fit.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc9ca-cb73-77f1-8ec6-29caee0e69c5
Co-authored-by: Amp <amp@ampcode.com>
Use px-2.5 py-1.5 instead of uniform p-1.5 so tile content has
proper breathing room from the border on all sides.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc9ca-cb73-77f1-8ec6-29caee0e69c5
Co-authored-by: Amp <amp@ampcode.com>
Add shrink-0 to prevent flex from compressing wider tiles like
'IN PROGRESS', which was squeezing out horizontal padding.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc9ca-cb73-77f1-8ec6-29caee0e69c5
Co-authored-by: Amp <amp@ampcode.com>
- Switch grid layout to flex-wrap so tiles don't shrink below readable size
- Use outline instead of ring for active state to prevent clipping by overflow-hidden
- Add 75px minimum width to KPI tiles

Amp-Thread-ID: https://ampcode.com/threads/T-019cc9c6-d539-71c4-8f00-78fb367b19a4
Co-authored-by: Amp <amp@ampcode.com>
When clicking the Open KPI tile, issues with status='open' but with
active blockedBy dependencies were incorrectly shown. Now filterIssues
excludes dependency-blocked issues when 'blocked' is not in the status
filter.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc9fe-e76d-7158-94bc-b3b49d8afb57
Co-authored-by: Amp <amp@ampcode.com>
Instead of clearing all filters, the All tile now populates the
filter bar with all status filters as visible chips.

Amp-Thread-ID: https://ampcode.com/threads/T-019cca02-a2ae-739a-94bb-a8caaa440a94
Co-authored-by: Amp <amp@ampcode.com>
The bd CLI list output doesn't include a blocked_by field — it only
has a dependencies array with type: 'blocks' entries. The Tauri/Rust
backend already computed blockedBy from these, but the Nitro server
path passed through raw.blocked_by (always undefined), causing
dependency-blocked issues to appear as unblocked.

Also adds missing deferred/pinned/hooked to normalizeIssueStatus.

Amp-Thread-ID: https://ampcode.com/threads/T-019cca02-a2ae-739a-94bb-a8caaa440a94
Co-authored-by: Amp <amp@ampcode.com>
Devon and others added 6 commits March 7, 2026 16:04
Reka-ui's DropdownMenuCheckboxItem uses modelValue (not checked) to
control the checked state. The :checked prop was being ignored, causing
the checkmark indicator to never render for active filter selections.

Fixes: beads-task-issue-tracker-6fr
Amp-Thread-ID: https://ampcode.com/threads/T-019cca20-73d7-74f8-b334-e2f58130c2c4
Co-authored-by: Amp <amp@ampcode.com>
FilterChips were hidden via v-if="!isSearchActive" when search input
had text. Removed this condition so filters remain visible during search.
The FilterChips component already has its own v-if="hasFilters" guard.

Fixes: beads-task-issue-tracker-tt4
Amp-Thread-ID: https://ampcode.com/threads/T-019cca2b-0af9-753f-9029-0090cc87dc65
Co-authored-by: Amp <amp@ampcode.com>
Previously, entering a search term would return all matching issues
regardless of active status/type/priority/assignee/label filters.
Now search results are intersected with all active filters, so only
issues matching both the search term AND filter criteria are shown.

Amp-Thread-ID: https://ampcode.com/threads/T-019cca30-5031-73e9-83ae-5c3a7a8c859f
Co-authored-by: Amp <amp@ampcode.com>
- Add up/down arrow buttons to each column item for reordering
- Column order persisted per-project via useProjectStorage
- Add reorderColumns helper to useColumnConfig composable

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019cca40-3ed1-73ef-98d8-3c130e3b237f
@w3dev33
Copy link
Copy Markdown
Owner

w3dev33 commented Mar 7, 2026

Thanks for this substantial PR! Solid work overall — the pipeline architecture and KPI logic are well thought out. Here's what I found during review:

Bugs

  1. issue-helpers.tsstats.ready never computed. It's declared and initialized to 0 in computeStatsFromIssues but never populated. Either compute it or remove it from the interface.

  2. issue-helpers.ts:79 — leftover tombstone check in isIssueWorkflow(). The tombstone status was removed everywhere else but this reference remains.

  3. lib.rs:normalize_issue_status — tombstone silently becomes open. Old deleted issues could resurface as open with no indication. Consider filtering them out instead of mapping to open.

  4. QuickList.vue — uses console.error instead of logFrontend. Project convention requires using the native logger (logFrontend('error', ...)) so errors end up in the log file.

  5. AppHeader.vue — Linux/Windows padding fix was added then fully reverted. Commit 54f07db added platform-aware padding, but commit 084564e reverted it entirely. Net diff is zero — was this intentional?

Needs Manual Verification

  • tauri.conf.jsontitleBarStyle: "Overlay" was removed and "create": false was added. This changes macOS traffic light behavior. Please confirm the window controls still render correctly on macOS.

  • ColumnConfig.vue — The SortableJS onEnd handler manually reverts DOM mutations using container.children[evt.oldIndex], which can be off-by-one when oldIndex > newIndex. Worth testing with rapid reordering.

Dead Code / Cleanup

  • useColumnConfig.ts: reorderColumns() is exported but never called
  • tailwind.css: 6 lines of tombstone CSS variables/gradients remain
  • dashboard-stats.test.ts:91: still uses 'tombstone' as any
  • useChangeDetection.ts + usePipelineDiagnostics.ts: use console.warn/console.debug instead of logFrontend() (project convention)

UX Questions

  • clearFilters resets to Workflow view (not "show all") — is this the intended behavior?
  • hasActiveFilters is true in the default Workflow state, so filter chips are always visible even on first launch.
  • Column reordering is drag-only — no keyboard accessibility for users who can't use a mouse/trackpad.
  • QuickList.vue — the clickable area for issue selection shrunk when the outer element changed from <button> to <div>.

What Looks Good

  • Pipeline architecture (watcher → queue → backpressure → adaptive polling) is clean and well-scoped
  • KPI blocked/open/workflow partitioning is correct and consistent between stats and filtering
  • :model-value fix on filter dropdowns applied uniformly
  • blockedBy mapping from dependencies handles both bd formats correctly
  • Migration guards for persisted filters (tombstone removal) — good practice
  • 256 tests passing, new churn stress tests added

Nice contribution — looking forward to a v2 with the fixes above!

@w3dev33
Copy link
Copy Markdown
Owner

w3dev33 commented Mar 7, 2026

A note on the broader context:

Thanks again for the effort here — it's clear you've put real thought into this. Many of the changes (KPI tiles, always-visible filter chips, blocked quick-list, etc.) reflect personal workflow preferences, and that's totally valid. Different users have different needs — for instance, I prefer only showing filter chips when they're actively filtering, while you prefer them always visible. Neither approach is wrong, it's a matter of taste.

That said, I'm not actively developing this project further (especially around the bd integration), so I don't think it makes sense to merge a PR of this scope into the main repo. It would set expectations of maintenance and direction that I can't commit to.

The best path forward is probably to keep your fork as your own adapted version. If others in the community are interested, the discussion is open — but for now I'll leave the main repo as-is.

Appreciate the contribution and the ideas!

@drkatz
Copy link
Copy Markdown
Author

drkatz commented Mar 9, 2026

Thanks @w3dev33 for the review, good points and things to consider. I was working on these changes and pushed a few hours after the announcement for PaiR came out - Figured I'd PR just in case it was helpful. I will be continuing to maintain my fork as I encounter issues and find things to improve.

@w3dev33
Copy link
Copy Markdown
Owner

w3dev33 commented Mar 9, 2026

Thanks for the gracious response! Of course, feel free to keep evolving your fork of Beads however you see fit — it's great to see someone pushing it further.

If you're curious, you might also want to check out PaiR, the successor app. It already has quite a few improvements over this version. You're more than welcome to try it out and share any suggestions — present or future. Feedback is always appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants