Skip to content

fix(task-board): advance repo-less cards using the board's own review lane - #6849

Open
pedrofrxncx wants to merge 1 commit into
mainfrom
fix/advance-review-org-board-lanes-w2
Open

fix(task-board): advance repo-less cards using the board's own review lane#6849
pedrofrxncx wants to merge 1 commit into
mainfrom
fix/advance-review-org-board-lanes-w2

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Source: a real bug found auditing apps/api/src/storage/task-board.ts after the recent board-column-handling PRs (#6828, #6835, #6845 and the org_board_columns feature).

The bug: advanceToReviewIfInProgress hardcoded status = 'in_progress' in its WHERE clause and wrote status = 'in_review', ignoring the lanes its own caller (advanceLinkedTasksToReviewOnThreadFinish / advanceTasksToReviewOnThreadFinish) had already resolved from the org's board. Its sibling openReviewCycleIfInProgress (a few lines above, same file) correctly takes and uses lanes.progress/lanes.review.

Failure scenario: an org with org_board_columns enabled names its progress/review columns something other than the literals "in_progress"/"in_review". When a repo-less task's linked thread finishes, the thread-finish backstop (advanceTasksToReviewOnThreadFinish) is supposed to move the card to review — but the WHERE status = 'in_progress' matches no row on that board, so the advance is a silent no-op. The card is stuck In Progress forever with no error, no retry, nothing — exactly the failure mode listItemsStuckAfterFailure's doc comment describes for the failed-run case, but here it's a successful run that never gets flagged as done.

Fix: advanceToReviewIfInProgress now takes the same lanes param as openReviewCycleIfInProgress and reads/writes those instead of the hardcoded literals. Defaults to Studio's own lanes ({ progress: "in_progress", review: "in_review" }) so every existing caller and the real-Postgres integration tests (task-board-advance-review.integration.test.ts, task-board-advance-dismissed.integration.test.ts, quota-refund.integration.test.ts) keep compiling and passing unchanged. The one production caller, advanceTasksToReviewOnThreadFinish in run-reactions.ts, already resolves the org's real board lanes and now threads them one level deeper instead of relying on the default. Also fixed the accompanying activity-log write, which hardcoded to: "in_review" — now records the lane actually written (advanced.status).

Verify: cd apps/api && bunx tsc --noEmit (green — confirms the new required-shaped param is threaded correctly everywhere) and bunx oxlint src/storage/task-board.ts (0 warnings/errors). No unit test added: the only tests exercising this path are the real-Postgres integration suite, which this sandbox has no Postgres to run — full CI covers it. A reviewer can confirm behavior by running bun test apps/api/src/storage/task-board-advance-review.integration.test.ts against a real Postgres.

Checks run locally: bun run fmt, bunx tsc --noEmit (apps/api workspace), bunx oxlint on the changed file. Full CI (including the integration suite) validates the rest.


Summary by cubic

Fixes advanceToReviewIfInProgress so repo-less cards move to the board's own review lane instead of hardcoded in_review.

The function used status = 'in_progress' and 'in_review' literals, ignoring the lanes resolved from the org board. On boards with org_board_columns enabled and custom column names, the WHERE clause matched nothing and the card stayed In Progress silently. It now uses the lanes passed by advanceTasksToReviewOnThreadFinish, defaulting to Studio's in_progress/in_review for existing callers. The activity log entry also records the lane actually written.

Written for commit 586a14c. Summary will update on new commits.

Review in cubic

… lane

advanceToReviewIfInProgress hardcoded status = 'in_progress'/'in_review',
ignoring the lanes resolved from the org's own board. On an org-owned
board (org_board_columns flag) those literals name no column, so the
WHERE matched nothing and a repo-less card's thread-finish backstop
silently never advanced it to review.

Mirrors the sibling openReviewCycleIfInProgress, which already takes
lanes. Defaults to Studio's literal lanes to keep existing callers/tests
unchanged; the one production caller (advanceTasksToReviewOnThreadFinish)
now threads its resolved board lanes through instead of relying on the
default.

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/api/src/storage/task-board.ts">

<violation number="1" location="apps/api/src/storage/task-board.ts:1443">
P1: On an org-owned board whose progress key is not `in_progress`, this call never reaches the lane-aware update because `shouldAdvanceToReview` rejects the item first. Make the eligibility check compare the card status with `lanes.progress` while preserving its existing thread and PR checks.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

taskId,
organizationId,
item.updatedBy,
lanes,

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: On an org-owned board whose progress key is not in_progress, this call never reaches the lane-aware update because shouldAdvanceToReview rejects the item first. Make the eligibility check compare the card status with lanes.progress while preserving its existing thread and PR checks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/storage/task-board.ts, line 1443:

<comment>On an org-owned board whose progress key is not `in_progress`, this call never reaches the lane-aware update because `shouldAdvanceToReview` rejects the item first. Make the eligibility check compare the card status with `lanes.progress` while preserving its existing thread and PR checks.</comment>

<file context>
@@ -1440,6 +1440,7 @@ export class TaskBoardStorage {
         taskId,
         organizationId,
         item.updatedBy,
+        lanes,
       );
       if (!advanced) continue;
</file context>

pedrofrxncx added a commit that referenced this pull request Sep 2, 2026
…tion (#6854)

reactToFailedTaskRun already takes this org's board lanes as a parameter,
but its retry/return-to-todo gate still compared item.status against the
literal string "in_progress" instead of lanes.progress. On an org-owned
board (org_board_columns) whose in-progress column is named anything else,
this comparison never matches, so a failed run's card is silently never
retried and never sent back to To Do — it just sits in progress forever
with no failure reaction.

Same class of bug as #6849 (advanceToReviewIfInProgress hardcoded
in_progress/in_review).
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.

1 participant