import { s as store_get, x as head, b as attr_class, c as escape_html, a as attr, e as ensure_array_like, d as attr_style, u as unsubscribe_stores, g as derived, f as stringify } from './dev-BNpEUZI3.js';
import 'node:module';
import { x as TASK_STATUSES } from './paths-2M_UxD_H.js';
import { p as page } from './stores-CdeEEU9O.js';
import './client-CW9E6S_J.js';
import { T as TaskSearchBox, F as FilterChipGroup, L as LabelsFilter, H as HierarchyTab, G as GraphTab, K as KanbanTab, E as EpicProgressCard, R as RecentActivityFeed, D as DetailDrawer } from './tasks2-DtLXCqqM.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:child_process';
import 'node:crypto';
import 'node:process';
import 'node:async_hooks';
import './internal-DYSVC9SL.js';
import '@sveltejs/kit/internal';
import './index-server-DocJvixA.js';
import './chunk-DDP5xfzh.js';
import '@sveltejs/kit/internal/server';
import './tasks-CnwUAUXf.js';
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 './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 './StatBlock-DHJMmOCx.js';
import './Tabs-DzG6Bn9a.js';
import './ui-DR8zOSpC.js';
import './no-face-up-DcejJLy-.js';
import 'd3';

//#region src/lib/stores/task-filters.svelte.ts
var DEFAULT_VIEW = "hierarchy";
var VALID_VIEWS = new Set([
	"hierarchy",
	"graph",
	"kanban"
]);
var VALID_PRIORITIES = new Set([
	"critical",
	"high",
	"medium",
	"low"
]);
var QUERY_DEBOUNCE_MS = 150;
var deferredWarningEmitted = false;
function parseCsv(raw, validate) {
	if (!raw) return [];
	const tokens = raw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
	const out = [];
	const seen = /* @__PURE__ */ new Set();
	for (const t of tokens) if (validate(t) && !seen.has(t)) {
		out.push(t);
		seen.add(t);
	}
	return out;
}
/** Type-guard for {@link TaskStatus}. */
function isTaskStatus(v) {
	return TASK_STATUSES.includes(v);
}
/** Type-guard for {@link TaskPriority}. */
function isTaskPriority(v) {
	return VALID_PRIORITIES.has(v);
}
/** Type-guard for {@link TaskView}. */
function isTaskView(v) {
	return VALID_VIEWS.has(v);
}
/** Pass-through validator for free-form label names (non-empty tokens). */
function isNonEmptyLabel(v) {
	return v.length > 0;
}
/**
* Read a {@link TaskFilterState} from a {@link URL}.
*
* Honours the legacy `?deferred=1` alias for `?cancelled=1` and emits a
* one-time `console.warn` the first time the alias is encountered.
*
* @param url - The URL to parse.
* @returns A fresh {@link TaskFilterState}.
*/
function readFromUrl(url) {
	const p = url.searchParams;
	const cancelledFlag = p.get("cancelled") === "1";
	const deferredFlag = p.get("deferred") === "1";
	if (deferredFlag && !deferredWarningEmitted) {
		deferredWarningEmitted = true;
		console.warn("[task-filters] ?deferred=1 is deprecated; use ?cancelled=1. Alias removal tracked by T958.");
	}
	const viewRaw = p.get("view");
	const view = viewRaw && isTaskView(viewRaw) ? viewRaw : DEFAULT_VIEW;
	return {
		query: p.get("q") ?? "",
		status: parseCsv(p.get("status"), isTaskStatus),
		priority: parseCsv(p.get("priority"), isTaskPriority),
		labels: parseCsv(p.get("labels"), isNonEmptyLabel),
		epic: p.get("epic"),
		selected: p.get("selected"),
		cancelled: cancelledFlag || deferredFlag,
		view
	};
}
/**
* Apply a {@link TaskFilterState} onto a fresh {@link URL} and return it.
*
* - Empty values, empty arrays, default view, and `cancelled:false` all
*   result in the corresponding param being deleted (minimal URL).
* - CSV arrays are serialized in source order — callers should ensure
*   stable ordering if they want idempotent round-trips (setters do).
*
* @param base - The URL to clone and mutate (typically `window.location`).
* @param state - The filter state to serialize.
* @returns A new {@link URL} instance with only the relevant params set.
*/
function writeToUrl(base, state) {
	const next = new URL(base.toString());
	const p = next.searchParams;
	p.delete("deferred");
	setOrDelete(p, "q", state.query || null);
	setOrDelete(p, "status", state.status.length ? state.status.join(",") : null);
	setOrDelete(p, "priority", state.priority.length ? state.priority.join(",") : null);
	setOrDelete(p, "labels", state.labels.length ? state.labels.join(",") : null);
	setOrDelete(p, "epic", state.epic);
	setOrDelete(p, "selected", state.selected);
	setOrDelete(p, "cancelled", state.cancelled ? "1" : null);
	setOrDelete(p, "view", state.view === DEFAULT_VIEW ? null : state.view);
	return next;
}
/** Write `value` to `params[key]` if non-null/non-empty, otherwise delete. */
function setOrDelete(params, key, value) {
	if (value === null || value === "") params.delete(key);
	else params.set(key, value);
}
/**
* Create a Task Explorer filter store bound to a URL.
*
* The initial state is parsed from `url`. Subsequent mutations both update
* the reactive state and write the new query string to `window.history` via
* `replaceState`. On `popstate` (browser back/forward), state is re-read from
* `window.location` so filters stay in sync with navigation.
*
* Server-side / test environments without `window` skip the browser-specific
* hookup but remain fully reactive in memory.
*
* @param url - The initial URL whose query string seeds the state.
* @returns A {@link TaskFilters} handle exposing reactive state plus setters.
*
* @example
* ```ts
* const filters = createTaskFilters($page.url);
* filters.setQuery('pomodoro');
* filters.toggleStatus('active');
* // URL is now /tasks?q=pomodoro&status=active
* ```
*/
function createTaskFilters(url) {
	const state = readFromUrl(url);
	let queryDebounceTimer = null;
	let popstateHandler = null;
	/**
	* Write the current state to `window.history`. Called after every mutation
	* (debounced for `setQuery`).
	*/
	function syncUrl() {
		if (typeof window === "undefined") return;
		const next = writeToUrl(new URL(window.location.href), state);
		if (next.search !== window.location.search) window.history.replaceState(window.history.state, "", next.toString());
	}
	/** Schedule or coalesce a debounced `syncUrl` call for query updates. */
	function scheduleQuerySync() {
		if (typeof window === "undefined") return;
		if (queryDebounceTimer !== null) clearTimeout(queryDebounceTimer);
		queryDebounceTimer = setTimeout(() => {
			queryDebounceTimer = null;
			syncUrl();
		}, QUERY_DEBOUNCE_MS);
	}
	/** Re-read state from `window.location` (popstate handler). */
	function readFromWindow() {
		if (typeof window === "undefined") return;
		const fresh = readFromUrl(new URL(window.location.href));
		state.query = fresh.query;
		state.status = fresh.status;
		state.priority = fresh.priority;
		state.labels = fresh.labels;
		state.epic = fresh.epic;
		state.selected = fresh.selected;
		state.cancelled = fresh.cancelled;
		state.view = fresh.view;
	}
	if (typeof window !== "undefined") {
		popstateHandler = readFromWindow;
		window.addEventListener("popstate", popstateHandler);
	}
	/** Toggle membership of `value` in `arr` (mutates in place; stable order). */
	function toggleIn(arr, value) {
		const idx = arr.indexOf(value);
		if (idx === -1) return [...arr, value];
		return [...arr.slice(0, idx), ...arr.slice(idx + 1)];
	}
	return {
		get state() {
			return state;
		},
		setQuery(q) {
			state.query = q;
			scheduleQuerySync();
		},
		toggleStatus(s) {
			state.status = toggleIn(state.status, s);
			syncUrl();
		},
		togglePriority(p) {
			state.priority = toggleIn(state.priority, p);
			syncUrl();
		},
		toggleLabel(l) {
			state.labels = toggleIn(state.labels, l);
			syncUrl();
		},
		setEpic(id) {
			state.epic = id;
			syncUrl();
		},
		setSelected(id) {
			state.selected = id;
			syncUrl();
		},
		setCancelled(v) {
			state.cancelled = v;
			syncUrl();
		},
		setView(v) {
			state.view = v;
			syncUrl();
		},
		clear() {
			state.query = "";
			state.status = [];
			state.priority = [];
			state.labels = [];
			state.epic = null;
			state.selected = null;
			state.cancelled = false;
			state.view = DEFAULT_VIEW;
			if (queryDebounceTimer !== null) {
				clearTimeout(queryDebounceTimer);
				queryDebounceTimer = null;
			}
			syncUrl();
		},
		dispose() {
			if (queryDebounceTimer !== null) {
				clearTimeout(queryDebounceTimer);
				queryDebounceTimer = null;
			}
			if (popstateHandler !== null && typeof window !== "undefined") {
				window.removeEventListener("popstate", popstateHandler);
				popstateHandler = null;
			}
		}
	};
}
//#endregion
//#region src/routes/tasks/+page.svelte
function _page($$renderer, $$props) {
	$$renderer.component(($$renderer) => {
		var $$store_subs;
		let { data } = $$props;
		const stats = derived(() => data.stats);
		const recentTasks = derived(() => data.recentTasks ?? []);
		const epicProgress = derived(() => data.epicProgress ?? []);
		const dashboardFilters = derived(() => data.filters ?? {
			showCancelled: false,
			showArchived: false
		});
		/**
		* Build a toggle URL that flips one dashboard filter flag while preserving
		* the other.
		*/
		function toggleUrl(flag) {
			const next = new URL(store_get($$store_subs ??= {}, "$page", page).url);
			if (next.searchParams.get(flag) === "1") next.searchParams.delete(flag);
			else next.searchParams.set(flag, "1");
			if (flag === "cancelled") next.searchParams.delete("deferred");
			return next.pathname + (next.search ? next.search : "");
		}
		let filters = createTaskFilters(new URL(store_get($$store_subs ??= {}, "$page", page).url));
		const explorerTasks = derived(() => data.explorer?.tasks ?? []);
		const explorerDeps = derived(() => data.explorer?.deps ?? []);
		const explorerLabels = derived(() => data.explorer?.labels ?? []);
		const explorerEpicProgressMap = derived(() => data.explorer?.epicProgress ?? {});
		const selectedTask = derived(() => (() => {
			if (!filters) return null;
			const id = filters.state.selected;
			if (!id) return null;
			return explorerTasks().find((t) => t.id === id) ?? null;
		})());
		const statusOptions = [
			{
				value: "pending",
				label: "Pending",
				tint: "var(--status-pending)"
			},
			{
				value: "active",
				label: "Active",
				tint: "var(--status-active)"
			},
			{
				value: "blocked",
				label: "Blocked",
				tint: "var(--status-blocked)"
			},
			{
				value: "done",
				label: "Done",
				tint: "var(--status-done)"
			},
			{
				value: "cancelled",
				label: "Cancelled",
				tint: "var(--status-cancelled)"
			}
		];
		const priorityOptions = [
			{
				value: "critical",
				label: "Critical",
				tint: "var(--priority-critical)"
			},
			{
				value: "high",
				label: "High",
				tint: "var(--priority-high)"
			},
			{
				value: "medium",
				label: "Medium",
				tint: "var(--priority-medium)"
			},
			{
				value: "low",
				label: "Low",
				tint: "var(--priority-low)"
			}
		];
		const labelOptions = derived(() => explorerLabels().map((label) => ({
			value: label,
			label
		})));
		function diffAndToggle(before, after, toggle) {
			const beforeSet = new Set(before);
			const afterSet = new Set(after);
			for (const v of beforeSet) if (!afterSet.has(v)) toggle(v);
			for (const v of afterSet) if (!beforeSet.has(v)) toggle(v);
		}
		let searchRaw = "";
		let searchLoading = false;
		function priorityClassLocal(p) {
			if (p === "critical") return "priority-critical";
			if (p === "high") return "priority-high";
			if (p === "medium") return "priority-medium";
			return "priority-low";
		}
		let liveConnected = false;
		head("1pluywh", $$renderer, ($$renderer) => {
			$$renderer.title(($$renderer) => {
				$$renderer.push(`<title>Tasks — CLEO Studio</title>`);
			});
		});
		$$renderer.push(`<div class="tasks-page svelte-1pluywh"><div class="page-header svelte-1pluywh"><div class="header-left svelte-1pluywh"><h1 class="page-title svelte-1pluywh">Tasks</h1> <nav class="tasks-nav svelte-1pluywh"><a href="/tasks" class="nav-tab active svelte-1pluywh">Dashboard</a> <a href="/tasks/pipeline" class="nav-tab svelte-1pluywh">Pipeline</a> <a href="/tasks/sessions" class="nav-tab svelte-1pluywh">Sessions</a></nav></div> <div${attr_class("live-indicator svelte-1pluywh", void 0, { "connected": liveConnected })}><span class="live-dot svelte-1pluywh"></span> <span class="live-label svelte-1pluywh">${escape_html("Connecting...")}</span> `);
		$$renderer.push("<!--[-1-->");
		$$renderer.push(`<!--]--></div></div> <div class="search-section svelte-1pluywh"><div${attr_class("search-box svelte-1pluywh", void 0, { "loading": searchLoading })}><span class="search-icon svelte-1pluywh" aria-hidden="true">⌕</span> <input class="search-input svelte-1pluywh" type="text" placeholder="Search by ID (T663, t663, 663) or title..."${attr("value", searchRaw)} autocomplete="off" spellcheck="false"/> `);
		$$renderer.push("<!--[-1-->");
		$$renderer.push(`<!--]--></div> `);
		$$renderer.push("<!--[-1-->");
		$$renderer.push(`<!--]--></div> `);
		$$renderer.push("<!--[-1-->");
		$$renderer.push(`<!--]--> `);
		if (filters) {
			$$renderer.push("<!--[0-->");
			$$renderer.push(`<div class="command-surface svelte-1pluywh"><section class="task-explorer svelte-1pluywh" aria-label="Task Explorer"><header class="explorer-header svelte-1pluywh"><div class="tabs svelte-1pluywh" role="tablist" aria-label="Task Explorer views"><button type="button"${attr_class("tab svelte-1pluywh", void 0, { "active": filters.state.view === "hierarchy" })} role="tab"${attr("aria-selected", filters.state.view === "hierarchy")}><span class="tab-key svelte-1pluywh" aria-hidden="true">1</span> Hierarchy</button> <button type="button"${attr_class("tab svelte-1pluywh", void 0, { "active": filters.state.view === "graph" })} role="tab"${attr("aria-selected", filters.state.view === "graph")}><span class="tab-key svelte-1pluywh" aria-hidden="true">2</span> Graph</button> <button type="button"${attr_class("tab svelte-1pluywh", void 0, { "active": filters.state.view === "kanban" })} role="tab"${attr("aria-selected", filters.state.view === "kanban")}><span class="tab-key svelte-1pluywh" aria-hidden="true">3</span> Kanban</button></div> <div class="toolbar svelte-1pluywh">`);
			TaskSearchBox($$renderer, {
				value: filters.state.query,
				onChange: (q) => filters?.setQuery(q),
				placeholder: "Filter explorer by id or title...",
				registerSlashShortcut: true
			});
			$$renderer.push(`<!----> `);
			FilterChipGroup($$renderer, {
				label: "Status",
				options: statusOptions,
				selected: filters.state.status,
				onChange: (next) => {
					if (!filters) return;
					diffAndToggle(filters.state.status, next, (v) => filters?.toggleStatus(v));
				}
			});
			$$renderer.push(`<!----> `);
			FilterChipGroup($$renderer, {
				label: "Priority",
				options: priorityOptions,
				selected: filters.state.priority,
				onChange: (next) => {
					if (!filters) return;
					diffAndToggle(filters.state.priority, next, (v) => filters?.togglePriority(v));
				}
			});
			$$renderer.push(`<!----> `);
			if (labelOptions().length > 0) {
				$$renderer.push("<!--[0-->");
				LabelsFilter($$renderer, {
					options: labelOptions(),
					selected: filters.state.labels});
			} else $$renderer.push("<!--[-1-->");
			$$renderer.push(`<!--]--></div></header> <div class="explorer-body svelte-1pluywh">`);
			if (filters.state.view === "hierarchy") {
				$$renderer.push("<!--[0-->");
				HierarchyTab($$renderer, {
					tasks: explorerTasks(),
					deps: explorerDeps(),
					epicProgress: explorerEpicProgressMap(),
					filters
				});
			} else if (filters.state.view === "graph") {
				$$renderer.push("<!--[1-->");
				GraphTab($$renderer, {
					tasks: explorerTasks(),
					deps: explorerDeps(),
					filters,
					labels: explorerLabels(),
					activeProjectId: store_get($$store_subs ??= {}, "$page", page).data.activeProjectId ?? null
				});
			} else {
				$$renderer.push("<!--[-1-->");
				KanbanTab($$renderer, {
					tasks: explorerTasks(),
					deps: explorerDeps(),
					filters
				});
			}
			$$renderer.push(`<!--]--></div></section> <aside class="side-rail svelte-1pluywh" aria-label="Dashboard summary">`);
			if (stats()) {
				$$renderer.push("<!--[0-->");
				$$renderer.push(`<section class="rail-card svelte-1pluywh" aria-label="Task counts"><header class="rail-head svelte-1pluywh"><span class="rail-eyebrow svelte-1pluywh">Overview</span> <span class="rail-total svelte-1pluywh">${escape_html(stats().total)} <span class="rail-total-lbl svelte-1pluywh">tasks</span></span></header> <div class="stat-grid svelte-1pluywh"><span class="stat-card status-active-card svelte-1pluywh"><span class="stat-num svelte-1pluywh">${escape_html(stats().active)}</span> <span class="stat-lbl svelte-1pluywh">Active</span></span> <span class="stat-card svelte-1pluywh"><span class="stat-num svelte-1pluywh">${escape_html(stats().pending)}</span> <span class="stat-lbl svelte-1pluywh">Pending</span></span> <span class="stat-card status-done-card svelte-1pluywh"><span class="stat-num svelte-1pluywh">${escape_html(stats().done)}</span> <span class="stat-lbl svelte-1pluywh">Done</span></span> <span class="stat-card status-cancelled-card svelte-1pluywh"><span class="stat-num svelte-1pluywh">${escape_html(stats().cancelled)}</span> <span class="stat-lbl svelte-1pluywh">Cancelled</span></span> <span class="stat-card muted svelte-1pluywh"><span class="stat-num svelte-1pluywh">${escape_html(stats().archived)}</span> <span class="stat-lbl svelte-1pluywh">Archived</span></span></div> <div class="priority-block svelte-1pluywh"><div class="section-label svelte-1pluywh">Priority</div> <div class="priority-bars svelte-1pluywh"><!--[-->`);
				const each_array_1 = ensure_array_like([
					["critical", stats().critical],
					["high", stats().high],
					["medium", stats().medium],
					["low", stats().low]
				]);
				for (let $$index_1 = 0, $$length = each_array_1.length; $$index_1 < $$length; $$index_1++) {
					let [label, count] = each_array_1[$$index_1];
					const total = stats().critical + stats().high + stats().medium + stats().low;
					const pct = total > 0 ? Math.round(Number(count) / total * 100) : 0;
					$$renderer.push(`<div class="priority-row svelte-1pluywh"><span${attr_class(`priority-label ${stringify(priorityClassLocal(String(label)))}`, "svelte-1pluywh")}>${escape_html(label)}</span> <div class="priority-bar-track svelte-1pluywh"><div${attr_class(`priority-bar-fill ${stringify(priorityClassLocal(String(label)))}`, "svelte-1pluywh")}${attr_style(`width:${stringify(pct)}%`)}></div></div> <span class="priority-count svelte-1pluywh">${escape_html(count)}</span></div>`);
				}
				$$renderer.push(`<!--]--></div></div> <div class="type-block svelte-1pluywh"><div class="section-label svelte-1pluywh">Type</div> <div class="type-chips svelte-1pluywh"><span class="type-chip svelte-1pluywh">Epics <strong class="svelte-1pluywh">${escape_html(stats().epics)}</strong></span> <span class="type-chip svelte-1pluywh">Tasks <strong class="svelte-1pluywh">${escape_html(stats().tasks)}</strong></span> <span class="type-chip svelte-1pluywh">Subtasks <strong class="svelte-1pluywh">${escape_html(stats().subtasks)}</strong></span></div></div> <div class="filter-bar svelte-1pluywh" aria-label="Dashboard filters"><a${attr("href", toggleUrl("cancelled"))}${attr_class("filter-chip svelte-1pluywh", void 0, { "active": dashboardFilters().showCancelled })} data-sveltekit-noscroll="" title="Include cancelled epics in the Epic Progress panel"><span class="chip-check svelte-1pluywh">${escape_html(dashboardFilters().showCancelled ? "✓" : " ")}</span> Cancelled epics</a> <a${attr("href", toggleUrl("archived"))}${attr_class("filter-chip svelte-1pluywh", void 0, { "active": dashboardFilters().showArchived })} data-sveltekit-noscroll="" title="Include archived tasks in Recent Activity"><span class="chip-check svelte-1pluywh">${escape_html(dashboardFilters().showArchived ? "✓" : " ")}</span> Archived</a></div></section>`);
			} else {
				$$renderer.push("<!--[-1-->");
				$$renderer.push(`<div class="no-db svelte-1pluywh">tasks.db not found — start CLEO in the project directory</div>`);
			}
			$$renderer.push(`<!--]--> `);
			if (epicProgress().length > 0) {
				$$renderer.push("<!--[0-->");
				EpicProgressCard($$renderer, {
					epics: epicProgress(),
					includingDeferred: dashboardFilters().showCancelled
				});
			} else $$renderer.push("<!--[-1-->");
			$$renderer.push(`<!--]--> `);
			if (recentTasks().length > 0) {
				$$renderer.push("<!--[0-->");
				RecentActivityFeed($$renderer, { tasks: recentTasks() });
			} else $$renderer.push("<!--[-1-->");
			$$renderer.push(`<!--]--></aside></div> `);
			DetailDrawer($$renderer, {
				task: selectedTask(),
				onClose: () => filters?.setSelected(null)
			});
			$$renderer.push(`<!---->`);
		} else $$renderer.push("<!--[-1-->");
		$$renderer.push(`<!--]--></div>`);
		if ($$store_subs) unsubscribe_stores($$store_subs);
	});
}

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