diff --git a/.changeset/linear-import-intake-lane.md b/.changeset/linear-import-intake-lane.md new file mode 100644 index 0000000000..80853e5516 --- /dev/null +++ b/.changeset/linear-import-intake-lane.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Linear imports now land on the board instead of a lane that no longer exists. +category: fix +dev: `buildLinearTaskCreateInput` passed `column: "triage"`, a column U11 deleted, and an explicit column overrides `createTask`'s own intake resolution — so every imported issue was written into a lane no workflow declares. It now omits `column`. Same defect and same fix as the GitLab importer (#2843); the two tests that pinned `"triage"` now assert the column is absent. diff --git a/plugins/fusion-plugin-linear-import/src/__tests__/import-linear.test.ts b/plugins/fusion-plugin-linear-import/src/__tests__/import-linear.test.ts index 714aa8a4ca..2ca5fec776 100644 --- a/plugins/fusion-plugin-linear-import/src/__tests__/import-linear.test.ts +++ b/plugins/fusion-plugin-linear-import/src/__tests__/import-linear.test.ts @@ -50,7 +50,20 @@ describe("Linear import normalization", () => { it("builds triage task create input with durable metadata", () => { const input = buildLinearTaskCreateInput(issue); - expect(input.column).toBe("triage"); + /* + FNXC:WorkflowLifecycleColumns 2026-07-30-16:35: + The import names NO column, so `createTask` resolves the workflow's intake lane. + + This assertion used to demand `"triage"` — a column U11 DELETED — which is how the defect + survived: the test pinned the bug. An explicit `column` overrides `createTask`'s own intake + resolution, so every Linear import landed in a lane no workflow declares, with a 200 and a task + id and no card on the board. + + Absence is asserted rather than a resolved id, because absence is precisely the property that + hands the decision to `createTask`. It is also what fails on revert. + */ + expect(input.column).toBeUndefined(); + expect(Object.keys(input)).not.toContain("column"); expect(input.source?.sourceType).toBe("api"); expect(input.source?.sourceMetadata).toEqual(expect.objectContaining({ provider: "linear", issueId: "lin-issue-1" })); }); diff --git a/plugins/fusion-plugin-linear-import/src/__tests__/routes.test.ts b/plugins/fusion-plugin-linear-import/src/__tests__/routes.test.ts index 7353e6f3eb..e51d72d8bc 100644 --- a/plugins/fusion-plugin-linear-import/src/__tests__/routes.test.ts +++ b/plugins/fusion-plugin-linear-import/src/__tests__/routes.test.ts @@ -63,7 +63,9 @@ describe("linear plugin routes", () => { const context = ctx(); const result = await importSingleLinearIssue({ body: { issueId: "ENG-1" } }, context); expect(result).toMatchObject({ status: 201, body: { imported: true, duplicate: false, taskId: "FN-9" } }); - expect((context.taskStore as any).createTask).toHaveBeenCalledWith(expect.objectContaining({ column: "triage" })); + /* FNXC:WorkflowLifecycleColumns 2026-07-30-16:35: the route must not name a column either — + `createTask` resolves the workflow's intake lane. Pinned `"triage"` before, a column U11 deleted. */ + expect((context.taskStore as any).createTask).toHaveBeenCalledWith(expect.not.objectContaining({ column: expect.anything() })); }); it("returns duplicate task id for existing imported issue", async () => { diff --git a/plugins/fusion-plugin-linear-import/src/import-linear.ts b/plugins/fusion-plugin-linear-import/src/import-linear.ts index c5531c6c46..f2b27777f7 100644 --- a/plugins/fusion-plugin-linear-import/src/import-linear.ts +++ b/plugins/fusion-plugin-linear-import/src/import-linear.ts @@ -118,12 +118,25 @@ export async function findExistingLinearTask(taskStore: { listTasks?: (options?: return tasks.find((task) => taskMatchesLinearIssue(task, issue)) ?? null; } +/* +FNXC:WorkflowLifecycleColumns 2026-07-30-16:35: +NO explicit `column`. An imported Linear issue enters INTAKE, and `createTask` resolves which column +that is from the workflow it selects (`resolvedEntryColumn`); an explicit `column` OVERRIDES that +resolution, which is exactly how this import kept naming `triage` after the column stopped existing. + +`triage` was DELETED by U11 — the default board's lanes are `todo | in-progress | in-review | done | +archived` — so every Linear import wrote its card into a lane no workflow declares. Nothing rejects +it and nothing logs it: the route reports success with a task id, and the card is not on the board. + +Identical shape and identical fix to the GitLab importer (#2843). Worth stating that this one is the +reason to distrust "we fixed the import path": the two importers were written from the same template +and only one of them was found by looking at the forge everybody uses. +*/ export function buildLinearTaskCreateInput(issue: LinearIssue): TaskCreateInput { const preview = buildLinearImportPreview(issue); return { title: preview.title, description: preview.description, - column: "triage", sourceIssue: preview.sourceIssue, source: { sourceType: "api",