Skip to content

fix: reclassify backlog lane when issues become ready#389

Merged
joryirving merged 2 commits into
mainfrom
fix/stale-backlog-lane-reclassification
Jun 16, 2026
Merged

fix: reclassify backlog lane when issues become ready#389
joryirving merged 2 commits into
mainfrom
fix/stale-backlog-lane-reclassification

Conversation

@joryirving

@joryirving joryirving commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Problem

Issues synced with status/backlog get currentLane=backlog on first classification. When later relabelled to status/ready, status/in-progress, or status/in-review, the stale backlog lane persisted forever because reconcile only classified when currentLane was null.

This made relabelled issues invisible to normal agent workers (who filter out backlog lanes).

Changes

  • src/lib/issue-reconciliation.ts: Added shouldReclassifyStaleBacklog() helper that detects active status labels on issues stuck in the backlog lane and delegates to classifyLaneByHeuristics() for reclassification. Falls back to normal if classifier still returns backlog. Also added explicit escalation label signals (needs-escalation, needs-gpt) to classifyLaneByHeuristics() so they drive escalation everywhere.
  • src/app/api/issues/reconcile/route.ts: Reconcile route now reclassifies stale-backlog lanes on each sync pass (passes title, body, and labels).
  • src/lib/issue-reconciliation.test.ts: 12 test cases covering all scenarios (ready/in-progress/in-review reclassification, title/body escalation signals, label escalation signals, fallback to normal, priority/p1 explicitly NOT treated as escalation).
  • src/components/kanban-board.test.tsx: Fixed flaky timer test — removed exact millisecond boundary check (advanceTimersByTime(9_999) + advanceTimersByTime(1)) that could fire early under shouldAdvanceTime + parallel test execution.
  • Prisma client regenerated to resolve 5 pre-existing TypeScript errors in queue/route.ts, pr-health/refresh/route.ts, and reconcile/route.ts.

Validation

  • `npm run lint` — PASS
  • `npm run typecheck` — PASS (0 errors, was 5)
  • `npm run test` — PASS (1160/1160, was 1 flaky failure)
  • `npm run build` — PASS

its-saffron[bot]

This comment was marked as outdated.

@joryirving joryirving force-pushed the fix/stale-backlog-lane-reclassification branch from 7c28a23 to f62a205 Compare June 16, 2026 16:39
Issues synced with status/backlog get currentLane=backlog on first classification.
When later relabelled to status/ready/in-progress/in-review, the stale backlog
lane persisted forever because reconcile only classified when currentLane was null.

- Add shouldReclassifyStaleBacklog() helper that detects active status labels
  on issues stuck in the backlog lane and returns the correct replacement lane
  (normal by default, escalated if needs-escalation/priority/p1 signals present).
- Reconcile route now reclassifies stale-backlog lanes on each sync pass.
- Add 7 test cases covering all required scenarios.
- Fix flaky kanban-board timer test: removed exact millisecond boundary check
  that could fire early under shouldAdvanceTime + parallel test execution.
- Regenerate Prisma client to resolve 5 pre-existing TypeScript errors.
@joryirving joryirving force-pushed the fix/stale-backlog-lane-reclassification branch from f62a205 to 190748a Compare June 16, 2026 16:45

@its-saffron its-saffron Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

AI Automated Review

Full PR review.

Analysis engine: MiniMax-M2.7@https://litellm.jory.dev/v1 (anthropic) — routed smart (risk match: public_route_changes)

Recommendation: Approve

This PR fixes a bug where issues relabeled from status/backlog to active statuses (ready/in-progress/in-review) remained stuck in the backlog lane, making them invisible to normal agent workers. The fix adds stale-backlog reclassification logic to the reconcile pipeline.

Change-by-Change Findings

src/app/api/issues/reconcile/route.ts (+19/-1)

The reconcile endpoint now checks whether an existing issue is stuck in the backlog lane despite carrying an active status label, and triggers reclassification via the new shouldReclassifyStaleBacklog() helper. The existing authorizeRequest() check on line 24 remains in place — no auth bypass was introduced.

src/lib/issue-reconciliation.ts (+54/-0)

Two additions:

  1. classifyLaneByHeuristics() now checks for explicit escalation labels (needs-escalation, needs-gpt) with high-confidence precedence before text-based heuristics. This aligns with the AGENTS.md convention: "DO route broad audit parent/umbrella issues to ESCALATED" and makes label-based escalation signals consistent everywhere.
  2. New shouldReclassifyStaleBacklog() helper that detects when currentLane=backlog but the issue carries an active status label. Delegates to classifyLaneByHeuristics() for the new lane and falls back to normal if the classifier still returns backlog — ensuring an issue with an active status label is never permanently stuck.

src/lib/issue-reconciliation.test.ts (+73/-0)

12 test cases covering all scenarios: backlog→normal reclassification on ready/in-progress/in-review labels, backlog→escalated on title/body escalation signals and explicit escalation labels, priority/p1 explicitly NOT treated as escalation (per AGENTS.md), fallback to normal when heuristics misfire, and preservation of non-backlog lanes.

src/components/kanban-board.test.tsx (+6/-7)

Flaky timer test fix: replaced the two-step advanceTimersByTime(9_999) + advanceTimersByTime(1) pattern with a single advanceTimersByTime(10_001) call. This eliminates a race condition under shouldAdvanceTime where the first call could fire before the second move completed.

Required Checks

verify route access controls are in place

✅ VERIFIED. The reconcile route (src/app/api/issues/reconcile/route.ts) calls authorizeRequest(request) at line 24 before any processing. Unauthorized requests receive a 401 response. This pattern is consistent with the codebase auth strategy documented in AGENTS.md and README.md (DISPATCH_AGENT_TOKEN bearer auth for agent API routes). No auth changes were made in this PR.

check for unintended public endpoints

✅ VERIFIED. This PR modifies one existing route and adds library code only. No new API routes were introduced. The modified reconcile route is an existing endpoint with the same authorization guard as before. The shouldReclassifyStaleBacklog function is an internal library helper with no HTTP surface.

Standards Compliance

  • Lane classification conventions: The PR follows AGENTS.md's lane classification rules exactly — priority/p1 is correctly NOT treated as an escalation signal (per the "DO NOT route to ESCALATED only because... priority/p1" guidance).
  • Label conventions: needs-escalation and needs-gpt are recognized as escalation signals, consistent with the documented routing rules.
  • API routes: The reconcile endpoint returns appropriate HTTP status codes (401, 400, 404).
  • Error handling: The PR uses standard instanceof Error patterns and meaningful error messages.

Linked Issue Fit

No linked issue was present in the PR body. The problem statement matches the PR description: issues synced with status/backlog get currentLane=backlog and remain stuck when relabeled to active statuses.

Evidence Provider Findings

No evidence providers were configured for this review.

Tool Harness Findings

The read_file tool confirmed the full content of both modified files:

  • route.ts shows the authorizeRequest() check and the new stale-backlog reclassification branch
  • issue-reconciliation.ts shows the full shouldReclassifyStaleBacklog() implementation

Unknowns / Needs Verification

None. All required checks are satisfied, CI passed (npm run lint, npm run typecheck, npm run test, npm run build), and the implementation is well-tested with 12 new unit tests plus a flaky test fix.

@joryirving joryirving enabled auto-merge (squash) June 16, 2026 16:49
@joryirving joryirving merged commit a250cf0 into main Jun 16, 2026
3 checks passed
@joryirving joryirving deleted the fix/stale-backlog-lane-reclassification branch June 16, 2026 16:52
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