Files
fusion/.changeset
gsxdsm dc363543a2 fix(cli): fn task retry now CRASHES on a renamed board — #2728 converted the classifier and left the target (#2752)
## This is a live regression on `main`, not a conversion

`#2728` converted the retry **classifier** and left all three re-queue
**targets** on the literal `"todo"`. That pairing is **strictly worse
than the bug it fixed**:

- **Before:** `fn task retry` silently did nothing on a renamed board.
- **After (main today):** it correctly decides to retry, then throws.

```
TransitionRejectionError: Invalid transition: 'checking' → 'todo'. Unknown column for this workflow.
```

`todo` is not a column that board declares. Reproduced against main's
exact code — reverting this fix fails **2 of 4** cases with that error.

I flagged this on #2728 before it landed; posting it as a fix rather
than a comment now that it is merged.

## Why the census did not catch it

The census counts **comparisons**. A move **target** contains no
comparison, so all three sites are invisible to it —
`packages/cli/src/commands/task.ts` reads **0 guards** on main while the
crash is live.

That is the clearest case in this program so far that **the census
measures conversion progress, not correctness**. A classifier and the
target it feeds have to move together, and no automated signal will say
so.

## The fix

The target resolves from the task's own workflow:

```ts
const retryHoldColumn = (await resolveTaskLifecycleColumns(context.store, id))?.hold ?? "todo";
```

Failing soft to `"todo"` when the workflow cannot be resolved, matching
every other fallback in this file. Three call sites, all three
converted.

## Revert proof

| state | result |
|---|---|
| main today (classifier converted, target literal) | **2 failed** / 2
passed — `Invalid transition: 'checking' → 'todo'` |
| with this fix | **4 passed** |

## The fixture is derived, not hand-built

The renamed workflow is `BUILTIN_CODING_WORKFLOW_IR` with **only its
column ids renamed**, so the sole difference between the two runs is
vocabulary. Hand-building a graph tested the fixture's shape as much as
the code — the IR validator rejects an undeclared back-edge, and once
declared as `kind: "rework"` the transition table still did not match
the default board's. The suite also asserts the rename landed
(`checking` present, `in-review` absent), so a surviving literal cannot
pass by accident.

Real store, real persisted workflow, driven through the real
`runTaskRetry` — not the predicate. A unit test of the classifier goes
green on the half-fix; only driving the whole command surfaces the
crash.

## Relationship to #2736

This replaces it. #2736's other contents (active-task count,
near-duplicate filter, archived-lineage label, node-override guards, the
missing-worktree classifier) are now redundant with #2728, so they are
dropped rather than re-litigated. What survives is this fix, its test,
and the **changeset for the published CLI** that #2728 did not include.

I will close #2736 once this is reviewed.

## Verification

- new PG suite **4 passed** · `task-retry.test.ts` **7 passed** across 2
files
- `pnpm test:gate` — **10 / 158 / 487 / 71** · `pnpm lint` clean · CLI
`tsc --noEmit` clean · `check:changesets` passes · `--strict` exits 0

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 06:51:25 -07:00
..
2026-07-26 18:11:47 -07:00

Changeset Format Guide

Each changeset file in this directory describes one user-facing change for release notes.

Required body format

---
"@runfusion/fusion": minor
---

summary: Add a Command Center productivity control for LOC backfills.
category: feature
dev: Uses the new `fn_backfill_loc` tool; settings key `commandCenter.locBackfill`.

Fields

Field Required Description
summary Yes One line, user-facing, max 120 chars. Describe what changed for the operator.
category Yes One of: feature, fix, breaking, security, performance, internal.
dev No Developer or migration detail. Preserved in per-package CHANGELOGs but excluded from distilled release notes.

Audience

The summary is the only content that appears in end-user release notes by default. Write for Fusion operators — describe behavior, fixes, and what changed. Avoid internal class names, file paths, and implementation detail.

Bump types

  • patch — bug fixes, internal changes
  • minor — new features, CLI additions, tools
  • major — breaking changes

Validation

Run pnpm check:changesets to validate. The linter runs in the PR-check gate and test:gate. Legacy freeform changesets pass with a warning during the transition period.