//#region src/lib/components/tasks/lane-transition.ts
/**
* Lanes a card can be DROPPED into to directly set a `tasks.status`. These map
* 1:1 onto a {@link DraggableTargetStatus}:
*
*  - `backlog`   → `status: 'pending'`   — defer / un-start work.
*  - `running`   → `status: 'active'`    — mark as actively being worked.
*  - `blocked`   → `status: 'blocked'`   — explicitly park (operator blocker).
*  - `cancelled` → `status: 'cancelled'` — abandon.
*
* `ready`, `review`, and `done` are intentionally absent: `ready`/`review` are
* RESOLVED lanes (computed from deps/gates, not a settable status), and `done`
* is gate-protected (must go through the complete flow).
*/
var DRAGGABLE_TARGET_STATUS = {
	backlog: "pending",
	running: "active",
	blocked: "blocked",
	cancelled: "cancelled"
};
/**
* Source lanes a card can NEVER be dragged OUT of from the board — terminal
* success. A `done` task is past the lifecycle; reopening is an explicit,
* evidence-aware action, not a casual drag. (`cancelled` IS draggable out — a
* mis-cancel can be un-abandoned back to backlog/running.)
*/
var TERMINAL_LOCKED_SOURCE = new Set(["done"]);
/**
* Human-readable lane labels for transition summaries / toasts. Kept local so
* this pure module has no dependency on the Svelte-facing label map.
*/
var LANE_SHORT_LABEL = {
	backlog: "Backlog",
	ready: "Ready",
	running: "Running",
	review: "Review",
	blocked: "Blocked",
	done: "Done",
	cancelled: "Cancelled"
};
/**
* Plan (and validate) a drag of a card from one lifecycle lane to another.
*
* ## Validity ladder (first match wins)
*
* 1. **`same-lane`** — `fromLane === toLane`: a no-op, rejected so the board
*    does not issue a pointless mutation.
* 2. **`terminal-source`** — dragging OUT of `done`: rejected (reopen is not a
*    board gesture).
* 3. **`gate-protected-target`** — dropping into `done`: rejected (completion
*    must use the evidence-gated complete flow, never a raw status flip).
* 4. **`resolved-target`** — dropping into `ready` or `review`: rejected (these
*    lanes are COMPUTED from deps/gates, not a settable status).
* 5. Otherwise → an executable {@link LaneTransitionPlan} mapping the target
*    lane onto its {@link DraggableTargetStatus}.
*
* @param taskId - The task being moved.
* @param fromLane - The lane the card was dragged from.
* @param toLane - The lane the card was dropped into.
* @returns A {@link LaneTransitionResult} — `ok:true` with a plan, or `ok:false`
*   with a typed rejection + user-facing message.
*/
function planLaneTransition(taskId, fromLane, toLane) {
	if (fromLane === toLane) return {
		ok: false,
		reason: "same-lane",
		message: `${taskId} is already in ${LANE_SHORT_LABEL[toLane]}.`
	};
	if (TERMINAL_LOCKED_SOURCE.has(fromLane)) return {
		ok: false,
		reason: "terminal-source",
		message: `${taskId} is Done — reopen it from the task detail, not the board.`
	};
	if (toLane === "done") return {
		ok: false,
		reason: "gate-protected-target",
		message: `Can't drag ${taskId} to Done — completion runs through the verification gates, not a drag.`
	};
	const status = DRAGGABLE_TARGET_STATUS[toLane];
	if (status === void 0) return {
		ok: false,
		reason: "resolved-target",
		message: `${LANE_SHORT_LABEL[toLane]} is a computed lane — it's set by dependencies and gates, not by dragging.`
	};
	return {
		ok: true,
		plan: {
			taskId,
			fromLane,
			toLane,
			status,
			summary: `Moved ${taskId} ${LANE_SHORT_LABEL[fromLane]} → ${LANE_SHORT_LABEL[toLane]}`
		}
	};
}

export { planLaneTransition as p };
//# sourceMappingURL=lane-transition-lM2ngbbc.js.map
