Skip to content

fix: respect dashboard task column filters#1177

Merged
gsxdsm merged 1 commit into
Runfusion:mainfrom
plarson:fix/fn202-dashboard-column-filter
May 30, 2026
Merged

fix: respect dashboard task column filters#1177
gsxdsm merged 1 commit into
Runfusion:mainfrom
plarson:fix/fn202-dashboard-column-filter

Conversation

@plarson
Copy link
Copy Markdown
Contributor

@plarson plarson commented May 30, 2026

Summary

  • parse and validate the dashboard task-list column query parameter
  • pass valid column filters through to the task store
  • document persisted task column values vs. UI labels

Verification

  • COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack pnpm --filter @fusion/dashboard exec vitest run src/tests/routes-tasks.test.ts --reporter=dot
  • COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack pnpm --filter @fusion/dashboard typecheck
  • COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack pnpm lint
  • COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack pnpm typecheck
  • COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack pnpm build

Summary by CodeRabbit

  • New Features

    • API now respects dashboard task-list column filters, returning only tasks in the requested persisted column.
  • Documentation

    • Clarified valid persisted column identifiers (triage, todo, in-progress, in-review, done, archived) and that UI labels are presentation-only (e.g., Planning maps to triage).
  • Tests

    • Added tests for column filter validation, successful filtering, and rejection of invalid column values.
  • Chores

    • Patch release metadata added.

Review Change Stack

Copilot AI review requested due to automatic review settings May 30, 2026 14:58
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c11c1ba5-975f-4aaf-b1af-09a92a02cfc1

📥 Commits

Reviewing files that changed from the base of the PR and between 179a488 and 6ba3cbf.

📒 Files selected for processing (5)
  • .changeset/dashboard-column-filter.md
  • docs/task-management.md
  • packages/dashboard/src/__tests__/routes-tasks.test.ts
  • packages/dashboard/src/routes/register-task-workflow-routes.ts
  • packages/desktop/src/__tests__/release-workflow.test.ts
✅ Files skipped from review due to trivial changes (2)
  • .changeset/dashboard-column-filter.md
  • docs/task-management.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/dashboard/src/routes/register-task-workflow-routes.ts
  • packages/dashboard/src/tests/routes-tasks.test.ts

📝 Walkthrough

Walkthrough

The PR enforces dashboard task-list column filters in the /api/tasks GET route by accepting a trimmed column query param, validating it against known persisted column enums, returning 400 for invalid values, passing valid columns to scopedStore.listTasks, and updating docs, tests, and a release test regex.

Changes

Task column filtering feature

Layer / File(s) Summary
Column filter API contract and documentation
docs/task-management.md, .changeset/dashboard-column-filter.md
Documentation clarifies that column filters use persisted enum values (e.g., triage for Planning UI label) and the changeset notes the patch release enforcing column filtering.
Column parameter validation and routing
packages/dashboard/src/routes/register-task-workflow-routes.ts
/tasks GET handler imports isColumn, trims and validates the optional column query parameter, returns 400 for invalid provided values, and passes validated column to scopedStore.listTasks via listOptions.
Column filter test coverage
packages/dashboard/src/__tests__/routes-tasks.test.ts
Parameterized tests verify column passthrough and response filtering for allowed columns (triage, todo, in-progress); an additional test asserts a 400 response for invalid column and that store.listTasks is not called.

Desktop release test tweak

Layer / File(s) Summary
Linux AppImage filename regex update
packages/desktop/src/__tests__/release-workflow.test.ts
Release workflow test assertion updated to accept `Fusion-*-linux-(x64

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • gsxdsm

Poem

🐰 I nibble on a query string so neat,
Trimming whitespace with tiny feet,
Triage and todo hop in a line,
In-progress hops — the list looks fine,
Filtered, validated, tidy and sweet.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: respect dashboard task column filters' clearly and specifically summarizes the main change—implementing column filter support for dashboard task retrieval, which aligns with all file modifications in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for filtering the dashboard task list endpoint by persisted column value, validating the input against allowed columns.

Changes:

  • Adds a column query parameter to GET /api/tasks, validated via isColumn and forwarded to scopedStore.listTasks.
  • Adds tests covering valid column filtering and rejection of invalid column values.
  • Documents the column enum contract and adds a changeset.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
packages/dashboard/src/routes/register-task-workflow-routes.ts Parses, validates, and forwards column query param to the store.
packages/dashboard/src/tests/routes-tasks.test.ts Adds tests for valid/invalid column filter behavior.
docs/task-management.md Clarifies persisted column enum values vs. UI labels.
.changeset/dashboard-column-filter.md Adds patch changeset entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +345 to +348
const res = await GET(buildApp(), `/api/tasks?column=${column}&limit=20`);

expect(res.status).toBe(200);
expect(res.body).toHaveLength(1);
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 30, 2026

Greptile Summary

This PR wires up the column query parameter on GET /api/tasks so the endpoint actually forwards a validated column value to listTasks instead of ignoring it. The underlying listTasks store method already accepted a column?: Column option, so the only change needed was input parsing, validation, and forwarding.

  • Column parsing & validationregister-task-workflow-routes.ts now reads req.query.column, trims it, guards it with isColumn, and returns a 400 for unrecognised values (e.g. the old UI label Planning); valid values are spread into listOptions.
  • Documentationdocs/task-management.md clarifies the persisted enum values (triage, todo, …) vs. UI-only labels, with an example of a valid filter query.
  • Tests & changeset — three parameterised happy-path cases and one rejection case added to routes-tasks.test.ts; the desktop release-workflow test is relaxed to accept x64 or x86_64 AppImage names.

Confidence Score: 5/5

The change is narrow and additive — it wires up an existing store capability that was already well-exercised elsewhere in the codebase.

The listTasks store method already accepted column?: Column and used it correctly in many call sites; this PR simply routes the HTTP query parameter through the same validated path. The type guard isColumn is shared with other validated inputs and the 400 path is covered by a dedicated test. No data-mutation path is touched.

No files require special attention.

Important Files Changed

Filename Overview
packages/dashboard/src/routes/register-task-workflow-routes.ts Adds column query-param parsing, isColumn validation, 400 on bad values, and forwarding to listTasks; logic is correct and type-safe.
packages/dashboard/src/tests/routes-tasks.test.ts New parameterised test covers three valid columns and one invalid value; assertions verify both HTTP status and the exact listTasks call signature.
docs/task-management.md Documentation updated to clarify triage vs Planning and explain the persisted column contract; no code impact.
packages/desktop/src/tests/release-workflow.test.ts Relaxes an AppImage filename assertion from exact string to regex to accept both x64 and x86_64; unrelated to the column filter change.
.changeset/dashboard-column-filter.md Standard patch-level changeset entry; no issues.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Route as GET /api/tasks
    participant Store as TaskStore

    Client->>Route: "?column=triage&limit=20"
    Note over Route: columnParam = "triage"<br/>isColumn("triage") true<br/>column = "triage"
    Route->>Store: "listTasks({ limit:20, slim:true, includeArchived:false, column:"triage" })"
    Store-->>Route: Task[] filtered to "triage"
    Route-->>Client: 200 [ ...triage tasks ]

    Client->>Route: "?column=Planning"
    Note over Route: columnParam = "Planning"<br/>isColumn("Planning") false<br/>column = undefined
    Note over Route: columnParam && !column 400
    Route-->>Client: "400 { error: "column must be one of: ..." }"

    Client->>Route: "?q=search&limit=10"
    Note over Route: q branch taken<br/>column not forwarded
    Route->>Store: "searchTasks("search", { limit:10, ... })"
    Store-->>Route: Task[]
    Route-->>Client: 200 [ ...results ]
Loading

Reviews (3): Last reviewed commit: "fix: respect dashboard task column filte..." | Re-trigger Greptile

Comment on lines 761 to +773
@@ -764,7 +769,8 @@ export function registerTaskWorkflowRoutes(ctx: ApiRoutesContext, deps: TaskWork
// Board-view list: omit the heavy agent log payload and exclude
// archived tasks unless explicitly requested. Full task detail still loads via
// GET /api/tasks/:id. Without this, every dashboard load shipped tens of MB of agent logs.
tasks = await scopedStore.listTasks({ limit, offset, slim: true, includeArchived });
const listOptions = { limit, offset, slim: true, includeArchived, ...(column ? { column } : {}) };
tasks = await scopedStore.listTasks(listOptions);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Column filter silently ignored when q is also provided

The column validation runs unconditionally before the q branch, but column is never forwarded to searchTasks. This creates two inconsistent outcomes for callers who pass both parameters: ?q=foo&column=Planning returns 400 (misleading, since column has no effect during search), and ?q=foo&column=triage returns 200 but the column restriction is silently dropped — the caller receives unfiltered search results. Either the validation should be gated behind !q, or column should be forwarded to searchTasks (which also lacks the parameter in its signature at packages/core/src/store.ts:4819).

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/dashboard/src/routes/register-task-workflow-routes.ts (1)

766-773: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

column filter is dropped when q is present

Line 766 routes search requests through searchTasks(...) without applying column, so GET /api/tasks?q=...&column=triage can return non-triage tasks. Apply the validated column filter in the search path too.

Suggested fix
-      if (q && q.length > 0) {
-        tasks = await scopedStore.searchTasks(q, { limit, offset, slim: true, includeArchived });
+      if (q && q.length > 0) {
+        const searchResults = await scopedStore.searchTasks(q, { limit, offset, slim: true, includeArchived });
+        tasks = column ? searchResults.filter((task) => task.column === column) : searchResults;
       } else {
         // Board-view list: omit the heavy agent log payload and exclude
         // archived tasks unless explicitly requested. Full task detail still loads via
         // GET /api/tasks/:id. Without this, every dashboard load shipped tens of MB of agent logs.
         const listOptions = { limit, offset, slim: true, includeArchived, ...(column ? { column } : {}) };
         tasks = await scopedStore.listTasks(listOptions);
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/dashboard/src/routes/register-task-workflow-routes.ts` around lines
766 - 773, The search path omits the validated column filter so requests with q
plus column (e.g., column=triage) can return wrong tasks; update the call to
scopedStore.searchTasks(q, ...) to include the same options used for listing
(limit, offset, slim, includeArchived and conditionally column) — mirror the
listOptions construction (or reuse listOptions) and pass it into searchTasks so
the validated column filter is applied in both paths.
🧹 Nitpick comments (1)
packages/dashboard/src/__tests__/routes-tasks.test.ts (1)

332-366: ⚡ Quick win

Add one regression test for q + column together

Please add a case for /api/tasks?q=<term>&column=<valid-column> so the filter contract is covered on the search code path too.

Suggested test
+  it("applies column filter when q and column are both provided", async () => {
+    (store.searchTasks as ReturnType<typeof vi.fn>).mockResolvedValueOnce([
+      { ...FAKE_TASK_DETAIL, id: "FN-TRIAGE", column: "triage" as const },
+      { ...FAKE_TASK_DETAIL, id: "FN-DONE", column: "done" as const },
+    ]);
+
+    const res = await GET(buildApp(), "/api/tasks?q=FN&column=triage");
+
+    expect(res.status).toBe(200);
+    expect(res.body).toEqual([
+      expect.objectContaining({ id: "FN-TRIAGE", column: "triage" }),
+    ]);
+  });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/dashboard/src/__tests__/routes-tasks.test.ts` around lines 332 -
366, Add a regression test that verifies the /api/tasks endpoint accepts both q
and column together: in packages/dashboard/src/__tests__/routes-tasks.test.ts
add an it(...) similar to the existing column-only test but call GET(buildApp(),
`/api/tasks?q=TERM&column=${column}&limit=20`) (use the same task fixtures and
vi mock for store.listTasks) and assert response status 200, returned rows match
column and/or query, and that store.listTasks was called with the combined
options including q, column, limit, offset: undefined, slim: true, and
includeArchived: false; reuse GET, buildApp, FAKE_TASK_DETAIL and
store.listTasks identifiers to locate code.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/dashboard/src/routes/register-task-workflow-routes.ts`:
- Around line 766-773: The search path omits the validated column filter so
requests with q plus column (e.g., column=triage) can return wrong tasks; update
the call to scopedStore.searchTasks(q, ...) to include the same options used for
listing (limit, offset, slim, includeArchived and conditionally column) — mirror
the listOptions construction (or reuse listOptions) and pass it into searchTasks
so the validated column filter is applied in both paths.

---

Nitpick comments:
In `@packages/dashboard/src/__tests__/routes-tasks.test.ts`:
- Around line 332-366: Add a regression test that verifies the /api/tasks
endpoint accepts both q and column together: in
packages/dashboard/src/__tests__/routes-tasks.test.ts add an it(...) similar to
the existing column-only test but call GET(buildApp(),
`/api/tasks?q=TERM&column=${column}&limit=20`) (use the same task fixtures and
vi mock for store.listTasks) and assert response status 200, returned rows match
column and/or query, and that store.listTasks was called with the combined
options including q, column, limit, offset: undefined, slim: true, and
includeArchived: false; reuse GET, buildApp, FAKE_TASK_DETAIL and
store.listTasks identifiers to locate code.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: af18b703-ab48-4031-869e-07a75a710648

📥 Commits

Reviewing files that changed from the base of the PR and between b5178fd and 906ba8f.

📒 Files selected for processing (4)
  • .changeset/dashboard-column-filter.md
  • docs/task-management.md
  • packages/dashboard/src/__tests__/routes-tasks.test.ts
  • packages/dashboard/src/routes/register-task-workflow-routes.ts

@plarson plarson force-pushed the fix/fn202-dashboard-column-filter branch from 906ba8f to 179a488 Compare May 30, 2026 15:18
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 30, 2026

Want your agent to iterate on Greptile's feedback? Try greploops.

@plarson plarson force-pushed the fix/fn202-dashboard-column-filter branch from 179a488 to 6ba3cbf Compare May 30, 2026 15:29
@gsxdsm
Copy link
Copy Markdown
Collaborator

gsxdsm commented May 30, 2026

Thank you for your contributions! They are great and much appreciated

@gsxdsm gsxdsm merged commit f5e738b into Runfusion:main May 30, 2026
8 checks passed
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.

3 participants