FN-5826: centralize branch assignment derivation

Centralize working-branch vs merge-target derivation and reuse it across branch-selection flows.

- add a shared core helper to derive working branch, merge target, and default branch assignment
- export the new helper from @fusion/core and add focused unit coverage for branch-assignment behavior
- update dashboard branch-selection route to consume the shared helper instead of duplicating derivation logic
- extend dashboard branch-selection tests to verify helper-driven branch/merge-target precedence

Files changed:
 .../core/src/__tests__/branch-assignment.test.ts   | 99 ++++++++++++++++++++++
 packages/core/src/branch-assignment.ts             | 76 +++++++++++++++++
 packages/core/src/index.ts                         | 11 +++
 .../src/__tests__/branch-selection.test.ts         | 12 +++
 packages/dashboard/src/routes/branch-selection.ts  | 39 +++++----
 5 files changed, 222 insertions(+), 15 deletions(-)

Fusion-Task-Id: FN-5826

Fusion-Task-Lineage: ad7c5487-5266-4281-abd6-33784dd7e488
This commit is contained in:
gsxdsm
2026-06-01 01:39:59 -07:00
parent 327f0a9a4f
commit 9ba3a8e453
5 changed files with 222 additions and 15 deletions

View File

@@ -0,0 +1,99 @@
import { describe, expect, it } from "vitest";
import {
deriveAutoTaskBranchName,
derivePerTaskBranchName,
resolveEntryPointBranchAssignment,
sanitizeBranchSegment,
} from "../branch-assignment.js";
describe("branch-assignment", () => {
it("sanitizes branch segments", () => {
expect(sanitizeBranchSegment(" FN-123 add parser!!! ")).toBe("fn-123-add-parser");
});
it("derives per-task branches", () => {
expect(derivePerTaskBranchName("feature/planning", "FN-123 add parser")).toBe("feature/planning/fn-123-add-parser");
expect(derivePerTaskBranchName(undefined, "FN-123")).toBeUndefined();
expect(derivePerTaskBranchName("feature/planning", " ")).toBe("feature/planning");
});
it("derives auto task branches", () => {
expect(deriveAutoTaskBranchName("FN-5671", "Branch Strategy Dropdown")).toBe("fusion/fn-5671-branch-strategy-dropdown");
expect(deriveAutoTaskBranchName("FN-5671", " ")).toBe("fusion/fn-5671");
});
it("resolves shared mode with per-task working branch and shared merge target", () => {
const resolvedBranch = "feature/planning";
const assignment = resolveEntryPointBranchAssignment({
assignmentMode: "shared",
resolvedBranch,
taskSegment: "FN-123 add parser",
});
expect(assignment).toEqual({
workingBranch: "feature/planning/fn-123-add-parser",
mergeTargetBranch: "feature/planning",
});
expect(assignment.workingBranch).not.toBe(resolvedBranch);
});
it("resolves shared mode with empty segment fallback", () => {
expect(resolveEntryPointBranchAssignment({
assignmentMode: "shared",
resolvedBranch: "feature/planning",
taskSegment: " ",
})).toEqual({
workingBranch: "feature/planning",
mergeTargetBranch: "feature/planning",
});
});
it("resolves shared mode with undefined resolved branch", () => {
expect(resolveEntryPointBranchAssignment({
assignmentMode: "shared",
resolvedBranch: undefined,
taskSegment: "FN-123",
})).toEqual({
workingBranch: undefined,
mergeTargetBranch: undefined,
});
});
it("resolves per-task-derived mode", () => {
expect(resolveEntryPointBranchAssignment({
assignmentMode: "per-task-derived",
resolvedBranch: "feature/planning",
taskSegment: "FN-123 add parser",
})).toEqual({
workingBranch: "feature/planning/fn-123-add-parser",
mergeTargetBranch: undefined,
});
});
it("resolves project-default mode", () => {
expect(resolveEntryPointBranchAssignment({
assignmentMode: "project-default",
resolvedBranch: "feature/planning",
taskSegment: "FN-123 add parser",
})).toEqual({
workingBranch: undefined,
mergeTargetBranch: undefined,
});
});
it("resolves existing and custom-new modes", () => {
expect(resolveEntryPointBranchAssignment({
assignmentMode: "existing",
resolvedBranch: "feature/existing",
})).toEqual({
workingBranch: "feature/existing",
mergeTargetBranch: undefined,
});
expect(resolveEntryPointBranchAssignment({
assignmentMode: "custom-new",
resolvedBranch: "feature/custom",
})).toEqual({
workingBranch: "feature/custom",
mergeTargetBranch: undefined,
});
});
});