import { a as attr, e as ensure_array_like, b as attr_class, c as escape_html, g as derived, x as head } from './dev-BNpEUZI3.js';
import { E as resolveAgentLifecycleLane, B as AGENT_LIFECYCLE_LANES, F as AGENT_LIFECYCLE_LANE_HINTS, G as AGENT_LIFECYCLE_LANE_LABELS } from './tasks-CnwUAUXf.js';
import { p as planLaneTransition } from './lane-transition-lM2ngbbc.js';
import { H as HeroHeader } from './HeroHeader-v4Q9vaGr.js';
import { E as EmptyState, B as Button } from './ui-DR8zOSpC.js';
import { b as TaskCard, C as ConductorBar, W as WorkerStreamPanel, D as DetailDrawer } from './tasks2-DtLXCqqM.js';
import { B as Badge } from './Tabs-DzG6Bn9a.js';
import './paths-2M_UxD_H.js';
import 'node:fs';
import 'node:path';
import 'node:os';
import 'node:events';
import 'node:diagnostics_channel';
import 'fs';
import 'events';
import 'util';
import 'path';
import 'assert';
import 'worker_threads';
import 'module';
import 'node:url';
import 'url';
import 'buffer';
import 'node:module';
import 'node:child_process';
import 'node:crypto';
import 'node:process';
import 'node:async_hooks';
import './data-accessor-CVbz8X_7.js';
import './conduit-Ca_OFWR_.js';
import './indexes-aYlULWG3.js';
import './utils-BvHPJOVk.js';
import './unique-constraint-BM-Apx1H.js';
import './chunk-DDP5xfzh.js';
import './sqlite-Dsbe0wec.js';
import './dual-scope-db-ATrwq0LH.js';
import './memory-schema-Bi7cChwo.js';
import './agent-registry-BtE5uhMO.js';
import './nexus-sqlite2-DgTuv9BQ.js';
import './nexus-schema2-BEd-ol6e.js';
import './logger-ChCwlV5k.js';
import 'node:sqlite';
import './lock-BoHF25mx.js';
import './index-IVoIz4D5.js';
import 'constants';
import 'stream';
import 'node:fs/promises';
import 'jsonc-parser';
import '@cleocode/cant';
import 'node:util';
import 'node:buffer';
import 'child_process';
import './branch-lock-qP1EkZ7p.js';
import './src2-DK8DKufK.js';
import 'llmtxt/identity';
import './sessions-j73dkbCI.js';
import './registry2-BSyCTA3q.js';
import './index-Ca4C2M45.js';
import './mvi-helpers-BNsJ8ZpQ.js';
import './session-store-OwQWMSf_.js';
import './session-manifest-ZHrj54LR.js';
import './storage-B9UA3BHR.js';
import './config-B0nEjgSh.js';
import './json-DXl7iDYg.js';
import './data-safety-central-vmfu_Y4J.js';
import './sqlite-data-accessor-C59wZ0zp.js';
import './cross-db-cleanup-C_FLyd-6.js';
import './index-server-DocJvixA.js';
import './StatBlock-DHJMmOCx.js';
import './no-face-up-DcejJLy-.js';
import 'd3';

//#region src/lib/components/board/board-types.ts
/**
* Bucket a flat card list into lane columns using a `laneResolver`.
*
* Pure + stable: every lane in `lanes` yields a column (even empty ones, so
* the board shape stays fixed), and cards preserve input order within each
* lane. Cards whose resolved lane id is not in `lanes` are dropped (defensive
* against taxonomy drift) — the same contract `bucketKanbanTasks` uses for
* unknown statuses.
*
* @param cards - Flat card list.
* @param lanes - Ordered lane definitions.
* @param laneResolver - Maps a card to exactly one lane id.
* @returns One {@link BoardLaneColumn} per lane, in `lanes` order.
*/
function bucketBoardCards(cards, lanes, laneResolver) {
	const byLane = /* @__PURE__ */ new Map();
	for (const lane of lanes) byLane.set(lane.id, []);
	for (const card of cards) {
		const laneId = laneResolver(card);
		const bucket = byLane.get(laneId);
		if (bucket) bucket.push(card);
	}
	return lanes.map((lane) => {
		const laneCards = byLane.get(lane.id) ?? [];
		return {
			lane,
			cards: laneCards,
			count: laneCards.length
		};
	});
}
//#endregion
//#region src/lib/components/board/Board.svelte
function Board($$renderer, $$props) {
	$$renderer.component(($$renderer) => {
		/** Ordered lane (column) definitions. */
		/** Flat card list — bucketed into lanes via {@link laneResolver}. */
		/** Routes a card to exactly one `lanes[i].id`. The OCP seam (T11927 AC1). */
		/** Called when a card is clicked / activated via keyboard. */
		/**
		* Called when a card is DRAGGED from one lane to another (T11928). When
		* omitted the board stays read-only (no drag affordance). The handler owns
		* the optimistic move + persistence + revert; the board only reports the
		* gesture (`cardId`, `fromLane`, `toLane`).
		*/
		let { lanes, cards, laneResolver, onSelect, onMove } = $$props;
		/** Whether drag→transition is wired (enables the draggable affordance). */
		const dragEnabled = derived(() => onMove !== void 0);
		/** The card id currently being dragged, or null. */
		let draggingId = null;
		/** The lane id currently hovered as a drop target, or null. */
		let dragOverLane = null;
		/** Bucket cards into lane columns (pure helper) whenever inputs change. */
		const columns = derived(() => bucketBoardCards(cards, lanes, laneResolver));
		/** Total cards across every lane — surfaced for the header summary. */
		const totalCards = derived(() => columns().reduce((sum, c) => sum + c.count, 0));
		let focusedCol = 0;
		let focusedRow = 0;
		/**
		* Project a {@link BoardCard} onto the minimal `Task` shape TaskCard needs.
		* The board only ever renders presentational fields, so this is a thin,
		* loss-free widening — no fabricated data beyond the required `description`
		* (TaskCard never displays it in compact mode).
		*/
		function toTaskCard(card) {
			return {
				id: card.id,
				title: card.title,
				description: card.title,
				status: card.status,
				priority: card.priority,
				size: card.size ?? void 0,
				createdAt: ""
			};
		}
		function activate(cardId) {
			onSelect?.(cardId);
		}
		$$renderer.push(`<div class="board-scroll svelte-vm5i0v" role="grid"${attr("aria-label", `Kanban board — ${totalCards()} tasks across ${columns().length} lanes. Use arrow keys to navigate, Enter to inspect.`)} tabindex="0"><div class="board svelte-vm5i0v"><!--[-->`);
		const each_array = ensure_array_like(columns());
		for (let ci = 0, $$length = each_array.length; ci < $$length; ci++) {
			let column = each_array[ci];
			$$renderer.push(`<div${attr_class("lane svelte-vm5i0v", void 0, {
				"is-focused": ci === focusedCol,
				"is-drop-target": dragOverLane === column.lane.id
			})}${attr("data-lane", column.lane.id)} role="row"${attr("tabindex", -1)}${attr("aria-label", `${column.lane.label} — ${column.count} tasks`)}><header class="lane-head svelte-vm5i0v"><span class="head-label svelte-vm5i0v">${escape_html(column.lane.label)}</span> `);
			Badge($$renderer, {
				tone: column.count > 0 ? "accent" : "neutral",
				size: "sm",
				children: ($$renderer) => {
					$$renderer.push(`<!---->${escape_html(column.count)}`);
				}});
			$$renderer.push(`<!----></header> <div class="lane-body svelte-vm5i0v">`);
			if (column.cards.length === 0) {
				$$renderer.push("<!--[0-->");
				$$renderer.push(`<div class="lane-empty svelte-vm5i0v">`);
				EmptyState($$renderer, {
					title: "Empty",
					subtitle: column.lane.hint ?? ""
				});
				$$renderer.push(`<!----></div>`);
			} else {
				$$renderer.push("<!--[-1-->");
				$$renderer.push(`<!--[-->`);
				const each_array_1 = ensure_array_like(column.cards);
				for (let ri = 0, $$length = each_array_1.length; ri < $$length; ri++) {
					let card = each_array_1[ri];
					$$renderer.push(`<div${attr_class("card-wrap svelte-vm5i0v", void 0, {
						"worker-active": card.workerActive,
						"is-focused": ci === focusedCol && ri === focusedRow,
						"is-dragging": draggingId === card.id,
						"draggable": dragEnabled()
					})} role="gridcell"${attr("tabindex", -1)}${attr("draggable", dragEnabled())}>`);
					if (card.workerActive) {
						$$renderer.push("<!--[0-->");
						$$renderer.push(`<span class="worker-dot svelte-vm5i0v" aria-label="Worker active" title="Worker active"></span>`);
					} else $$renderer.push("<!--[-1-->");
					$$renderer.push(`<!--]--> `);
					TaskCard($$renderer, {
						task: toTaskCard(card),
						compact: true,
						verificationJson: card.verificationJson ?? null,
						focused: ci === focusedCol && ri === focusedRow,
						onClick: () => activate(card.id)
					});
					$$renderer.push(`<!----></div>`);
				}
				$$renderer.push(`<!--]-->`);
			}
			$$renderer.push(`<!--]--></div></div>`);
		}
		$$renderer.push(`<!--]--></div></div>`);
	});
}
//#endregion
//#region src/lib/stores/saga-board-client.ts
/**
* Parse a Studio `/api/tasks/*` LAFS envelope from a `fetch` Response into a
* {@link CommandResult}. Never throws — a non-JSON / non-2xx response becomes a
* tagged failure with the best message available.
*
* @typeParam T - The expected success `/data` shape.
* @param res - The fetch response.
* @returns The narrowed command result.
*/
async function readCommandEnvelope(res) {
	let body;
	try {
		body = await res.json();
	} catch {
		return {
			ok: false,
			code: "E_BAD_RESPONSE",
			message: `Request failed (${res.status})`
		};
	}
	if (res.ok && body.success !== false) return {
		ok: true,
		data: body.data ?? {}
	};
	return {
		ok: false,
		code: body.error?.code ?? `E_HTTP_${res.status}`,
		message: body.error?.message ?? `Request failed (${res.status})`
	};
}
/**
* POST a JSON body to a Studio route and narrow the envelope. The shared
* transport for every {@link httpBoardCommandClient} method.
*
* @param fetchImpl - The `fetch` to use (injectable for SSR / tests).
* @param path - The Studio route path (e.g. `/api/tasks`).
* @param method - The HTTP method.
* @param payload - The JSON request body, or `undefined` for none.
* @returns The narrowed command result.
*/
async function postJson(fetchImpl, path, method, payload) {
	try {
		return await readCommandEnvelope(await fetchImpl(path, {
			method,
			headers: { "content-type": "application/json" },
			...payload !== void 0 ? { body: JSON.stringify(payload) } : {}
		}));
	} catch (e) {
		return {
			ok: false,
			code: "E_NETWORK",
			message: e instanceof Error ? e.message : "Network request failed"
		};
	}
}
/**
* Build the default {@link BoardCommandClient}: every method POSTs / PATCHes /
* DELETEs the Studio `/api/tasks/*` routes, which forward to the `/v1` gateway
* SDK client. No direct core import, no DB handle, no secret in the browser.
*
* @param fetchImpl - The `fetch` implementation (defaults to the global; pass
*   SvelteKit's `fetch` in a load, or a fake in a test).
* @returns A command client bound to that `fetch`.
*/
function httpBoardCommandClient(fetchImpl = fetch) {
	return {
		move(cmd) {
			return postJson(fetchImpl, `/api/tasks/${cmd.taskId}/transition`, "POST", {
				fromLane: cmd.fromLane,
				toLane: cmd.toLane
			});
		},
		dispatch(cmd) {
			return postJson(fetchImpl, `/api/tasks/${cmd.taskId}/dispatch`, "POST", { tier: cmd.tier });
		},
		create(cmd) {
			return postJson(fetchImpl, "/api/tasks", "POST", cmd);
		},
		patch(cmd) {
			const { taskId, ...fields } = cmd;
			return postJson(fetchImpl, `/api/tasks/${taskId}`, "PATCH", fields);
		},
		remove(taskId) {
			return postJson(fetchImpl, `/api/tasks/${taskId}`, "DELETE");
		}
	};
}
/**
* The Studio delegate path that forwards the gateway `tasks.subscribe` SSE. The
* store opens exactly ONE `EventSource` here — the single live channel that
* replaces the legacy poll.
*/
var TASKS_SUBSCRIBE_PATH = "/api/tasks/subscribe";
/**
* Build the default {@link BoardSubscriptionFactory} over a SINGLE
* `EventSource` pointed at the `tasks.subscribe` delegate.
*
* The gateway emits canonical `GatewayStreamEvent` frames (`data:`-only records
* whose JSON is `{ kind, seq, data, error, requestId }`). This factory decodes
* each `message`, surfaces `kind:'data'` frames as {@link BoardEvent}s (the
* `data` payload is the board lifecycle event), and maps open / error / `done`
* to the connection-state callback. Only browser-side: guarded so SSR is a
* no-op handle.
*
* @param root - Optional saga/parent scope appended as `?root=`.
* @returns A subscription factory the store opens once.
*/
function eventSourceBoardSubscriptionFactory(root) {
	return (handlers) => {
		if (typeof EventSource === "undefined") return { close() {} };
		const url = root ? `${TASKS_SUBSCRIBE_PATH}?root=${encodeURIComponent(root)}` : TASKS_SUBSCRIBE_PATH;
		const src = new EventSource(url);
		src.onopen = () => handlers.onConnectionChange?.(true);
		src.onmessage = (msg) => {
			let frame;
			try {
				frame = JSON.parse(msg.data);
			} catch {
				return;
			}
			if (frame.kind === "data") {
				const payload = frame.data !== null && typeof frame.data === "object" ? frame.data : {};
				handlers.onEvent({
					...payload,
					seq: frame.seq
				});
			} else if (frame.kind === "done") handlers.onConnectionChange?.(false);
		};
		src.onerror = () => handlers.onConnectionChange?.(false);
		return { close() {
			src.close();
			handlers.onConnectionChange?.(false);
		} };
	};
}
/** Map a `/api/tasks` legacy row to the board snapshot shape. */
function toSnapshotRow(row) {
	return {
		id: row.id,
		title: row.title,
		status: row.status,
		priority: row.priority,
		size: row.size,
		parentId: row.parent_id,
		verificationJson: row.verification_json
	};
}
/**
* Build the default {@link BoardHydrator}: GETs `/api/tasks` (which reads the
* gateway data layer) and projects the rows + the `views` `nextAction` signal
* into the board snapshot. A `running`-stage view (`nextAction` set + active
* session) is surfaced as an active-worker id so the board's Running affordance
* lights up without a second request.
*
* @param fetchImpl - The `fetch` to use (SvelteKit's in a load, global on the client).
* @returns A hydrator bound to that `fetch`.
*/
function httpBoardHydrator(fetchImpl = fetch) {
	return { async hydrate() {
		const res = await fetchImpl("/api/tasks?limit=1000");
		if (!res.ok) throw new Error(`Failed to hydrate board snapshot (${res.status})`);
		const body = await res.json();
		return {
			rows: body.tasks.map(toSnapshotRow),
			activeWorkerIds: body.views.filter((v) => v.status === "active").map((v) => v.id)
		};
	} };
}
//#endregion
//#region src/lib/stores/saga-board.svelte.ts
function buildLanes() {
	return AGENT_LIFECYCLE_LANES.map((id) => ({
		id,
		label: AGENT_LIFECYCLE_LANE_LABELS[id],
		hint: AGENT_LIFECYCLE_LANE_HINTS[id]
	}));
}
/**
* Project a board snapshot row + the active-worker set onto the framework-free
* {@link AgentLifecycleSignal} the shared resolver consumes.
*
* The lightweight `/api/tasks` snapshot does not carry gate/dep detail, so the
* signal is derived from status + worker activity — the same conservative
* mapping `+page.server.ts` uses for the read-only board. The resolver's
* precedence ladder (`cancelled > done > blocked > review > running > ready >
* backlog`) does the rest.
*
* @param row - The board snapshot row.
* @param workerActive - Whether an active session claims this task.
* @returns The normalised signal.
*/
function toSignal(row, workerActive) {
	return {
		status: row.status,
		blockedBy: null,
		depends: [],
		unmetDependsCount: 0,
		gates: null,
		readyToComplete: false,
		prAwaiting: false,
		hitlPending: false,
		workerActive
	};
}
/** Project a board snapshot row onto a presentational {@link BoardCard}. */
function toCard(row, workerActive) {
	return {
		id: row.id,
		title: row.title,
		status: row.status,
		priority: row.priority,
		size: row.size,
		verificationJson: row.verificationJson,
		workerActive
	};
}
/**
* The reactive saga-board store. Construct via {@link createSagaBoard}.
*
* Holds the raw snapshot rows + the active-worker set + optimistic lane
* overrides as `$state`, and exposes `cards` / `columns` / `lanes` as `$derived`
* getters so a component re-renders automatically on any mutation, optimistic
* override, or live event re-hydration.
*/
var SagaBoardStore = class {
	/** Lane definitions in board order (static taxonomy). */
	lanes = buildLanes();
	/** Raw board snapshot rows from the last hydration. */
	#rows = [];
	/** Task ids currently claimed by an active worker. */
	#activeWorkerIds = /* @__PURE__ */ new Set();
	/** Optimistic lane overrides, keyed by task id → lane (cleared on re-hydrate). */
	#laneOverride = {};
	/** Whether the live subscription is connected (drives the `live` indicator). */
	#connected = false;
	/** Whether a hydration is currently in flight. */
	#loading = false;
	/** The most recent hydration error message, or null. */
	#error = null;
	#deps;
	#root;
	#subscription = null;
	/**
	* @param deps - Injectable seam dependencies (all default to the HTTP/gateway impls).
	*/
	constructor(deps = {}) {
		this.#deps = {
			hydrator: deps.hydrator ?? httpBoardHydrator(),
			commands: deps.commands ?? httpBoardCommandClient(),
			subscriptionFactory: deps.subscriptionFactory ?? eventSourceBoardSubscriptionFactory(deps.root)
		};
		this.#root = deps.root;
	}
	/** Whether the live subscription is currently connected. */
	get connected() {
		return this.#connected;
	}
	/** Whether a hydration is in flight. */
	get loading() {
		return this.#loading;
	}
	/** The last hydration error, or null. */
	get error() {
		return this.#error;
	}
	/** The scope root this board is bound to, if any. */
	get root() {
		return this.#root;
	}
	#cards = derived(
		/** Flat card list with each card's resolved (override-aware) lane stamped on. */
		() => {
			return this.#rows.filter((row) => row.status !== "archived" && row.status !== "proposed").map((row) => {
				const workerActive = this.#activeWorkerIds.has(row.id);
				const card = toCard(row, workerActive);
				const resolved = resolveAgentLifecycleLane(toSignal(row, workerActive));
				const lane = this.#laneOverride[row.id] ?? resolved;
				return {
					...card,
					lane
				};
			});
		}
	);
	get cards() {
		return this.#cards();
	}
	set cards($$value) {
		return this.#cards($$value);
	}
	#columns = derived(() => {
		const byLane = /* @__PURE__ */ new Map();
		for (const lane of AGENT_LIFECYCLE_LANES) byLane.set(lane, []);
		for (const card of this.cards) byLane.get(card.lane)?.push(card);
		return this.lanes.map((lane) => {
			const cards = byLane.get(lane.id) ?? [];
			return {
				lane,
				cards,
				count: cards.length
			};
		});
	});
	get columns() {
		return this.#columns();
	}
	set columns($$value) {
		return this.#columns($$value);
	}
	#total = derived(() => this.cards.length);
	get total() {
		return this.#total();
	}
	set total($$value) {
		return this.#total($$value);
	}
	#runningCount = derived(() => this.cards.filter((c) => c.workerActive).length);
	get runningCount() {
		return this.#runningCount();
	}
	set runningCount($$value) {
		return this.#runningCount($$value);
	}
	async hydrate() {
		this.#loading = true;
		try {
			const { rows, activeWorkerIds } = await this.#deps.hydrator.hydrate();
			this.#rows = rows;
			this.#activeWorkerIds = new Set(activeWorkerIds);
			this.#laneOverride = {};
			this.#error = null;
		} catch (e) {
			this.#error = e instanceof Error ? e.message : "Failed to load the board";
		} finally {
			this.#loading = false;
		}
	}
	/**
	* Open the SINGLE live subscription. Every board lifecycle event triggers a
	* re-hydration (debounced by the in-flight `loading` guard) — this is the one
	* channel that replaces polling. Idempotent: a second call closes the prior
	* subscription first.
	*/
	connect() {
		this.disconnect();
		this.#subscription = this.#deps.subscriptionFactory({
			onEvent: (event) => this.#onLiveEvent(event),
			onConnectionChange: (connected) => {
				this.#connected = connected;
			}
		});
	}
	/** Tear the live subscription down (idempotent). */
	disconnect() {
		this.#subscription?.close();
		this.#subscription = null;
		this.#connected = false;
	}
	/** React to a live board event: re-hydrate unless one is already in flight. */
	#onLiveEvent(_event) {
		if (this.#loading) return;
		this.hydrate();
	}
	/**
	* Move a card to a new lane (drag→transition). Applies the move OPTIMISTICALLY,
	* then persists via the command client; on failure the optimistic override is
	* reverted. A live event (or the success) reconciles against the gateway.
	*
	* @param taskId - The card moved.
	* @param fromLane - The lane it came from.
	* @param toLane - The lane it was dropped into.
	* @returns The command result (so the caller can toast).
	*/
	async move(taskId, fromLane, toLane) {
		this.#laneOverride = {
			...this.#laneOverride,
			[taskId]: toLane
		};
		const result = await this.#deps.commands.move({
			taskId,
			fromLane,
			toLane
		});
		if (!result.ok) {
			const next = { ...this.#laneOverride };
			delete next[taskId];
			this.#laneOverride = next;
		}
		return result;
	}
	/**
	* Dispatch a worker for a card (Conductor). On success the card is
	* optimistically moved to the Running lane; the live worker stream attaches.
	*
	* @param taskId - The card to spawn a worker for.
	* @param tier - The spawn tier.
	* @returns The command result.
	*/
	async dispatch(taskId, tier) {
		const result = await this.#deps.commands.dispatch({
			taskId,
			tier
		});
		if (result.ok) this.#laneOverride = {
			...this.#laneOverride,
			[taskId]: "running"
		};
		return result;
	}
	/**
	* Create a new task (Conductor add). On success the board re-hydrates so the
	* new card appears in its resolved lane.
	*
	* @param cmd - The create command.
	* @returns The command result.
	*/
	async create(cmd) {
		const result = await this.#deps.commands.create(cmd);
		if (result.ok) await this.hydrate();
		return result;
	}
	/**
	* Patch fields on a task (status / priority / assignee / title). Re-hydrates
	* on success so the change is reflected authoritatively.
	*
	* @param taskId - The task to patch.
	* @param fields - The fields to change.
	* @returns The command result.
	*/
	async patch(taskId, fields) {
		const result = await this.#deps.commands.patch({
			taskId,
			...fields
		});
		if (result.ok) await this.hydrate();
		return result;
	}
	/**
	* Delete a task. Re-hydrates on success.
	*
	* @param taskId - The task to delete.
	* @returns The command result.
	*/
	async remove(taskId) {
		const result = await this.#deps.commands.remove(taskId);
		if (result.ok) await this.hydrate();
		return result;
	}
};
/**
* Create a {@link SagaBoardStore}. The ergonomic entry point a route uses.
*
* @param deps - Optional injectable seam deps (default to the HTTP/gateway impls).
* @returns A fresh reactive saga-board store.
*
* @example
* ```ts
* // in a +page.svelte $effect:
* const board = createSagaBoard();
* $effect(() => {
*   void board.hydrate();
*   board.connect();
*   return () => board.disconnect();
* });
* ```
*/
function createSagaBoard(deps) {
	return new SagaBoardStore(deps);
}

//#region src/lib/components/tasks/KanbanView.svelte
function KanbanView($$renderer, $$props) {
	$$renderer.component(($$renderer) => {
		/** A lane column as produced by the server load. */
		/** Lane columns from `+page.server.ts` (the SSR first paint). */
		/** Total tasks across all lanes (SSR). */
		/** Set when the project's tasks.db could not be read. */
		let { columns, total, error } = $$props;
		const board = createSagaBoard();
		/** True once the store has completed its first hydration (takes over from SSR). */
		let hydrated = false;
		/**
		* SSR columns mapped to the store's `SagaBoardCard` shape for the first paint,
		* so the board renders instantly before the client store hydrates.
		*/
		const ssrColumns = derived(() => columns.map((col) => ({
			lane: col.lane,
			count: col.count,
			cards: col.cards.map((card) => ({
				...card,
				lane: col.lane.id
			}))
		})));
		/** The authoritative columns: the live store once hydrated, else the SSR paint. */
		const boardColumns = derived(() => ssrColumns());
		/** Lane definitions in board order. */
		const lanes = derived(() => boardColumns().map((c) => c.lane));
		/** Flat card list with each card's resolved lane stamped on (`__lane`). */
		const flatCards = derived(() => boardColumns().flatMap((col) => col.cards.map((card) => ({
			...card,
			__lane: card.lane
		}))));
		/** Identity resolver — reads the resolved lane id off each card. */
		function laneResolver(card) {
			return card.__lane ?? "backlog";
		}
		/** Live counts — the store's once hydrated, else the SSR snapshot. */
		const liveTotal = derived(() => total);
		const runningCount = derived(() => flatCards().filter((c) => c.workerActive).length);
		let selectedId = null;
		const selectedCard = derived(() => selectedId ? flatCards().find((c) => c.id === selectedId) ?? null : null);
		/** The lifecycle lane of the selected card (override-aware). */
		const selectedLane = derived(() => selectedCard() ? selectedCard().__lane : null);
		/** Show the ConductorBar dispatch surface for Backlog/Ready cards (T11930). */
		const showConductor = derived(() => selectedCard() !== null && (selectedLane() === "backlog" || selectedLane() === "ready"));
		/** Show the live worker stream for a Running card (T11929). */
		const showStream = derived(() => selectedCard() !== null && selectedLane() === "running");
		/** Widen the selected presentational card to the minimal Task DetailDrawer needs. */
		const drawerTask = derived(() => selectedCard() ? {
			id: selectedCard().id,
			title: selectedCard().title,
			description: selectedCard().title,
			status: selectedCard().status,
			priority: selectedCard().priority,
			size: selectedCard().size ?? void 0,
			createdAt: (/* @__PURE__ */ new Date()).toISOString()
		} : null);
		function handleSelect(cardId) {
			selectedId = cardId;
		}
		function closeDrawer() {
			selectedId = null;
		}
		let toast = null;
		let toastTimer = null;
		function showToast(kind, message) {
			toast = {
				kind,
				message
			};
			if (toastTimer) clearTimeout(toastTimer);
			toastTimer = setTimeout(() => {
				toast = null;
			}, 4200);
		}
		let dispatchBusy = false;
		/**
		* Drag a card to a new lane. The client-side {@link planLaneTransition} gate
		* rejects invalid moves before any request; the store owns the optimistic
		* override + the gateway persist + the revert-on-failure.
		*/
		async function handleMove(cardId, fromLaneRaw, toLaneRaw) {
			const fromLane = fromLaneRaw;
			const toLane = toLaneRaw;
			const planned = planLaneTransition(cardId, fromLane, toLane);
			if (!planned.ok) {
				showToast("err", planned.message);
				return;
			}
			const result = await board.move(cardId, fromLane, toLane);
			if (!result.ok) {
				showToast("err", result.message);
				return;
			}
			showToast("ok", planned.plan.summary);
		}
		async function handleDispatch(tier) {
			if (!selectedCard()) return;
			const cardId = selectedCard().id;
			dispatchBusy = true;
			try {
				const result = await board.dispatch(cardId, tier);
				if (!result.ok) {
					showToast("err", result.message);
					return;
				}
				showToast("ok", `Dispatched ${cardId} → worker spawning`);
			} finally {
				dispatchBusy = false;
			}
		}
		const liveConnected = derived(() => hydrated);
		const metaLine = derived(() => `${liveTotal()} tasks · ${lanes().length} lanes${runningCount() > 0 ? ` · ${runningCount()} running` : ""}${liveConnected() ? " · live" : ""}`);
		head("exy7zz", $$renderer, ($$renderer) => {
			$$renderer.title(($$renderer) => {
				$$renderer.push(`<title>Dispatcher Board — CLEO Studio</title>`);
			});
		});
		$$renderer.push(`<div class="kanban-view svelte-exy7zz">`);
		{
			function actions($$renderer) {
				Button($$renderer, {
					variant: "ghost",
					size: "sm",
					href: "/tasks",
					children: ($$renderer) => {
						$$renderer.push(`<!---->← Tasks`);
					}});
				$$renderer.push(`<!----> `);
				Button($$renderer, {
					variant: "ghost",
					size: "sm",
					href: "/tasks/pipeline",
					children: ($$renderer) => {
						$$renderer.push(`<!---->Pipeline`);
					}});
				$$renderer.push(`<!---->`);
			}
			HeroHeader($$renderer, {
				eyebrow: "DISPATCHER",
				title: "Agent Lifecycle Board",
				subtitle: "Drag cards between lanes to transition · Dispatch Backlog/Ready cards to spawn a worker · watch Running cards live.",
				meta: metaLine(),
				liveIndicator: liveConnected(),
				actions});
		}
		$$renderer.push(`<!----> `);
		if (error) {
			$$renderer.push("<!--[0-->");
			$$renderer.push(`<div class="board-error svelte-exy7zz" role="alert"><p>Could not load the board: ${escape_html(error)}</p></div>`);
		} else {
			$$renderer.push("<!--[-1-->");
			$$renderer.push(`<div class="board-host svelte-exy7zz">`);
			Board($$renderer, {
				lanes: lanes(),
				cards: flatCards(),
				laneResolver,
				onSelect: handleSelect,
				onMove: handleMove
			});
			$$renderer.push(`<!----></div>`);
		}
		$$renderer.push(`<!--]--> <footer class="kanban-foot svelte-exy7zz"><span class="hint svelte-exy7zz">Drag to transition · Enter inspects · Dispatch spawns a worker (server-side)</span></footer></div> `);
		if (toast) {
			$$renderer.push("<!--[0-->");
			$$renderer.push(`<div${attr_class("toast svelte-exy7zz", void 0, { "err": toast.kind === "err" })} role="status" aria-live="polite">${escape_html(toast.message)}</div>`);
		} else $$renderer.push("<!--[-1-->");
		$$renderer.push(`<!--]--> `);
		if (showConductor() && selectedCard() && selectedLane()) {
			$$renderer.push("<!--[0-->");
			$$renderer.push(`<div class="dispatch-overlay svelte-exy7zz">`);
			ConductorBar($$renderer, {
				taskId: selectedCard().id,
				title: selectedCard().title,
				lane: selectedLane(),
				busy: dispatchBusy,
				onDispatch: handleDispatch,
				onClose: closeDrawer
			});
			$$renderer.push(`<!----></div>`);
		} else if (showStream() && selectedCard()) {
			$$renderer.push("<!--[1-->");
			$$renderer.push(`<div class="dispatch-overlay svelte-exy7zz">`);
			WorkerStreamPanel($$renderer, { taskId: selectedCard().id });
			$$renderer.push(`<!----> <div class="overlay-actions svelte-exy7zz">`);
			Button($$renderer, {
				variant: "ghost",
				size: "sm",
				onclick: closeDrawer,
				children: ($$renderer) => {
					$$renderer.push(`<!---->Close stream`);
				}});
			$$renderer.push(`<!----></div></div>`);
		} else if (drawerTask()) {
			$$renderer.push("<!--[2-->");
			DetailDrawer($$renderer, {
				task: drawerTask(),
				onClose: closeDrawer
			});
		} else $$renderer.push("<!--[-1-->");
		$$renderer.push(`<!--]-->`);
	});
}
//#endregion
//#region src/routes/tasks/kanban/+page.svelte
function _page($$renderer, $$props) {
	$$renderer.component(($$renderer) => {
		let { data } = $$props;
		KanbanView($$renderer, {
			columns: data.columns,
			total: data.total,
			error: data.error
		});
	});
}

export { _page as default };
//# sourceMappingURL=_page.svelte-BIx0Fiak.js.map
