fix(core): refine + duplicate create into the resolved intake lane, not the deleted triage column
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
7
.changeset/refine-duplicate-intake-lane.md
Normal file
7
.changeset/refine-duplicate-intake-lane.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Refined and duplicated tasks land in the workflow's Planning column instead of a deleted legacy column.
|
||||
category: fix
|
||||
dev: task_refine (update-task-deps.ts) and task_duplicate (project-store-ops.ts) hardcoded column "triage"; both now resolve resolveWorkflowIntakeFacts().intake with the literal as last resort. Symptom: amber PLANNING badge (badge color keys off raw column id) on cards in an undeclared column.
|
||||
@@ -43,7 +43,9 @@ pgDescribe("refineTask / duplicateTask backend mode (PostgreSQL)", () => {
|
||||
expect(refined.id).not.toBe(source.id);
|
||||
expect(refined.sourceType).toBe("task_refine");
|
||||
expect(refined.sourceParentTaskId).toBe(source.id);
|
||||
expect(refined.column).toBe("triage");
|
||||
// FNXC:MergedPlanningColumn 2026-07-31-22:40: refine resolves the workflow intake lane; the
|
||||
// default coding workflow's intake is the merged `todo` Planning column ("triage" is deleted).
|
||||
expect(refined.column).toBe("todo");
|
||||
expect(refined.dependencies).toEqual([source.id]);
|
||||
expect(refined.description).toContain("Please tighten the empty-state copy");
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
import {TaskStore, storeLog, WORKFLOW_COMPILED_STEP_TEMPLATE_PREFIX, WORKFLOW_MOVE_POLICY_TIMEOUT_MS} from "../store.js";
|
||||
import { resolveCapacityPoolId } from "../workflow-capacity.js";
|
||||
import {resolveWorkflowIntakeFacts} from "./task-creation.js";
|
||||
import {TransitionRejectionError} from "./errors.js";
|
||||
import * as schema from "../postgres/schema/index.js";
|
||||
import {and, eq, isNull, ne, or, sql} from "drizzle-orm";
|
||||
@@ -208,7 +209,12 @@ export async function duplicateTaskImpl(store: TaskStore, id: string): Promise<T
|
||||
title: normalizedTitle.title ?? undefined,
|
||||
description: `${sourceTask.description}\n\n(Duplicated from ${id})`,
|
||||
priority: normalizeTaskPriority(sourceTask.priority),
|
||||
column: "triage",
|
||||
/*
|
||||
FNXC:MergedPlanningColumn 2026-07-31-22:35 (missed creation surface — duplicate):
|
||||
Same fix as refine: resolve the default workflow's intake lane instead of the legacy
|
||||
`"triage"` literal, which the merged coding workflow no longer declares.
|
||||
*/
|
||||
column: ((await resolveWorkflowIntakeFacts(store)).intake ?? "triage") as Task["column"],
|
||||
modelPresetId: sourceTask.modelPresetId,
|
||||
sourceType: "task_duplicate",
|
||||
sourceParentTaskId: id,
|
||||
|
||||
@@ -100,7 +100,17 @@ directly and survives any rename or merge.
|
||||
Unresolvable workflow returns `{ manual: false }` with no intake, so callers keep their existing
|
||||
conservative behavior rather than acting on a guess.
|
||||
*/
|
||||
async function resolveWorkflowIntakeFacts(
|
||||
/*
|
||||
FNXC:MergedPlanningColumn 2026-07-31-22:30 (missed creation surfaces):
|
||||
Exported so refine (`update-task-deps.ts`) and duplicate (`project-store-ops.ts`) resolve the same
|
||||
intake lane as the main create. Both built Task rows directly inside `createTaskWithId` callbacks
|
||||
with a hardcoded `column: "triage"` — a column the merged coding workflow no longer declares — so a
|
||||
refined/duplicated card landed in an UNDECLARED column: rendered with the legacy amber badge,
|
||||
invisible to trait-driven sweeps until the undeclared-column re-home rescued it. #2589/#2603 fixed
|
||||
the main create; these two surfaces were the enumeration gap (found via a two-tone Planning badge on
|
||||
the live board).
|
||||
*/
|
||||
export async function resolveWorkflowIntakeFacts(
|
||||
store: TaskStore,
|
||||
workflowIdOverride?: string,
|
||||
): Promise<{ intake?: string; hold?: string; manual: boolean }> {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {resolveWorkflowIrForTask} from "../workflow-ir-resolver.js";
|
||||
import {buildRefinementSeedPrompt} from "../mesh-task-replication.js";
|
||||
import {SelfDefeatingDependencyError, detectSelfDefeatingDependency} from "./errors.js";
|
||||
import {resolveTaskLifecycleColumns} from "../workflow-lifecycle-traits.js";
|
||||
import {resolveWorkflowIntakeFacts} from "./task-creation.js";
|
||||
import type {WorkflowIr} from "../workflow-ir-types.js";
|
||||
import {mkdir, readFile, writeFile} from "node:fs/promises";
|
||||
import {join} from "node:path";
|
||||
@@ -111,6 +112,15 @@ export async function refineTaskImpl(store: TaskStore, id: string, feedback: str
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
FNXC:MergedPlanningColumn 2026-07-31-22:35 (missed creation surface — refine):
|
||||
Resolve the inherited workflow's intake lane instead of the legacy `"triage"` literal. The
|
||||
hardcoded id landed refinements in a column the merged coding workflow no longer declares —
|
||||
surfaced on the live board as an amber PLANNING badge (badge color keys off the raw column id)
|
||||
on a card invisible to trait-driven sweeps until the undeclared-column re-home. Literal survives
|
||||
only as the last resort for a store that cannot resolve any workflow, matching createTask.
|
||||
*/
|
||||
const refineIntakeColumn = (await resolveWorkflowIntakeFacts(store, pendingWorkflowSelection?.workflowId)).intake ?? "triage";
|
||||
const newTask = await store.createTaskWithDistributedReservation({ description: feedback.trim() }, {
|
||||
createTaskWithId: async (newId) => {
|
||||
// FN-5077: keep deterministic "Refinement" fallback when normalized refinement label is unusable (null).
|
||||
@@ -138,7 +148,7 @@ export async function refineTaskImpl(store: TaskStore, id: string, feedback: str
|
||||
title: normalizedTitle.title ?? "Refinement",
|
||||
description: `${feedback.trim()}\n\nRefines: ${id}`,
|
||||
priority: normalizeTaskPriority(sourceTask.priority),
|
||||
column: "triage",
|
||||
column: refineIntakeColumn as Task["column"],
|
||||
dependencies: [id],
|
||||
sourceType: "task_refine",
|
||||
sourceParentTaskId: id,
|
||||
|
||||
Reference in New Issue
Block a user