import { x as TASK_STATUSES } from './paths-2M_UxD_H.js';
import { g as getTaskAccessor } from './data-accessor-CVbz8X_7.js';
import { l as listTasks } from './list-DfOyEStk.js';
import { c as computeTaskRollups } from './rollup-DNaP6j6l.js';
import { g as getTasksDb } from './connections2-D22b0xbS.js';
import { l as loadExplorerBundle } from './explorer-loader-B_Iv2bTD.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 './storage-B9UA3BHR.js';
import './mvi-helpers-BNsJ8ZpQ.js';
import './sqlite-Dsbe0wec.js';
import './chunk-DDP5xfzh.js';
import './dual-scope-db-ATrwq0LH.js';
import './indexes-aYlULWG3.js';
import './utils-BvHPJOVk.js';
import './conduit-Ca_OFWR_.js';
import './unique-constraint-BM-Apx1H.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 './dist4-CiQ5cizO.js';
import './adapters-D2gEs_5L.js';
import './registry2-BSyCTA3q.js';
import './tasks-CnwUAUXf.js';
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 './index-Ca4C2M45.js';
import './session-store-OwQWMSf_.js';
import './session-manifest-ZHrj54LR.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 './query-ops-BDMaTdYw.js';
import 'node:net';
import './src3-CMSGYxDI.js';
import './local-model-fit2-J1xCIhC_.js';
import './credential-pool-B04qO8at.js';
import './catalog-model-resolver2-Cexk2TN0.js';
import './role-resolver-DF9BQ_U6.js';
import './identity2-DeAB5RXE.js';
import './role-executor-C4-3bmgC.js';
import 'node:stream';
import 'crypto';
import 'os';
import 'node:http2';
import 'fs/promises';
import './models-catalog-DG3aPok8.js';
import './catalog-resolver2-c0qfF34B.js';
import './providers-CmIcBfg-.js';
import './brain-maintenance-bSR6GwAG.js';
import './graph-auto-populate2-DYsUNGSL.js';
import './temporal-supersession-BZ46j30w.js';
import './typed-query-l1D_QElt.js';
import './llm-backend-resolver-BPbvttS4.js';
import '@ai-sdk/provider-utils';
import './observer-reflector2-D8nxuglX.js';
import './learnings2-2m2p7lzT.js';
import './memory-accessor2-BzlgmY-Z.js';
import './quality-scoring-CCPuRQmJ.js';
import './patterns2-DYKfsbwN.js';
import './graph-memory-bridge2-C7Y32Mk4.js';
import './sigil2-DftKm7Um.js';
import './services-Dlf3Gefq.js';
import './audit4-S87oN-BC.js';
import 'process';
import './cleo-home-BCqJ5rg1.js';

//#region src/routes/tasks/+page.server.ts
/**
* Set of all valid {@link TaskStatus} values, used for O(1) narrowing at
* the server boundary. Sourced from the canonical {@link TASK_STATUSES}
* registry so any future status addition is picked up for free.
*/
var TASK_STATUS_SET = new Set(TASK_STATUSES);
/**
* Set of canonical {@link TaskPriority} values. Mirrors the union in
* `@cleocode/contracts` — the contracts package does not (yet) export a
* runtime constant tuple for it, so we declare the narrow literal tuple
* here and let TypeScript enforce exhaustiveness via the
* `TaskPriority[]` type annotation.
*/
var TASK_PRIORITY_SET = new Set([
	"critical",
	"high",
	"medium",
	"low"
]);
/**
* Narrow a raw `status` string from the SQL layer to {@link TaskStatus}.
*
* The dashboard SELECT filters rows to `('active', 'pending', 'done'[,
* 'archived'])`, but the DB column is declared as `TEXT` — so at the TS
* layer we still need to prove the narrowing to satisfy the strict
* {@link RecentTaskRow} union. Unknown values fall back to `'cancelled'`
* (a terminal bucket that cannot ship an unrelated render path) and log
* a one-line warning so a schema drift bug gets noticed.
*/
function narrowStatus(raw, taskId) {
	if (TASK_STATUS_SET.has(raw)) return raw;
	console.warn(`[tasks/+page.server] unexpected status "${raw}" for ${taskId}; coerced to "cancelled".`);
	return "cancelled";
}
/**
* Narrow a raw `priority` string from the SQL layer to {@link TaskPriority}.
*
* Same rationale as {@link narrowStatus} — the DB column is loose. Unknown
* values fall back to `'low'` and warn once per row.
*/
function narrowPriority(raw, taskId) {
	if (TASK_PRIORITY_SET.has(raw)) return raw;
	console.warn(`[tasks/+page.server] unexpected priority "${raw}" for ${taskId}; coerced to "low".`);
	return "low";
}
/**
* Resolve the canonical "include cancelled epics" flag from a possibly-legacy
* options bag, preferring {@link DeprecatedEpicProgressOptions.includeCancelled}
* over the deprecated `includeDeferred`.
*/
function resolveIncludeCancelled(options) {
	if (typeof options.includeCancelled === "boolean") return options.includeCancelled;
	if (typeof options.includeDeferred === "boolean") return options.includeDeferred;
	return false;
}
/**
* Compute dashboard epic-progress rows using a direct-children basis.
*
* @deprecated T948: production `load()` now uses
* {@link _computeEpicProgressViaRollup} which routes through
* `cleo.lifecycle.computeRollupsBatch` so Studio, the CLI, and
* `/tasks/pipeline` all see the same projection. This pure SQL helper is
* retained only so the T874/T878 test suites (which pass an in-memory
* `node:sqlite` db) keep working without a wholesale rewrite.
*
* Pure function so it can be unit-tested against an in-memory SQLite DB
* without spinning up the full SvelteKit load context.
*
* T958: `options.includeDeferred` renamed to `options.includeCancelled`
* since "deferred" was only ever a UI label for `status='cancelled'` on
* epics — not a real DB field. The legacy option name is still accepted
* for one release via {@link DeprecatedEpicProgressOptions}.
*
* @param db - SQLite DB handle (better-sqlite3-compatible).
* @param options.includeCancelled - When true, include cancelled epics too.
* @param options.includeDeferred - Deprecated alias for `includeCancelled`.
* @returns One {@link EpicProgress} row per epic (filtered by `includeCancelled`).
*
* @task T874 | T878 | T948 | T958
* @epic T876 | T949
*/
function _computeEpicProgress(db, options = {}) {
	const epicFilter = resolveIncludeCancelled(options) ? `status != 'archived'` : `status NOT IN ('archived','cancelled')`;
	return db.prepare(`SELECT id, title, status FROM tasks WHERE type = 'epic' AND ${epicFilter} ORDER BY id`).all().map((epic) => {
		const children = db.prepare(`SELECT status, COUNT(*) as cnt
           FROM tasks
          WHERE parent_id = ?
            AND status != 'archived'
          GROUP BY status`).all(epic.id);
		const childMap = Object.fromEntries(children.map((r) => [r.status, r.cnt]));
		const total = Object.values(childMap).reduce((a, b) => a + b, 0);
		return {
			id: epic.id,
			title: epic.title,
			status: epic.status,
			total,
			done: childMap["done"] ?? 0,
			active: childMap["active"] ?? 0,
			pending: childMap["pending"] ?? 0,
			cancelled: childMap["cancelled"] ?? 0
		};
	});
}
/**
* Build an {@link EpicProgress} row from a parent epic + its child rollups.
*
* Pure transformation, no I/O. Child rollups arrive already filtered to the
* epic's direct, non-archived children — this function only tallies
* `execStatus` into dashboard buckets.
*
* Exported for tests (T948).
*/
function _epicRowFromRollups(parent, children) {
	let done = 0;
	let active = 0;
	let pending = 0;
	let cancelled = 0;
	for (const child of children) switch (child.execStatus) {
		case "done":
			done += 1;
			break;
		case "active":
			active += 1;
			break;
		case "pending":
			pending += 1;
			break;
		case "cancelled":
			cancelled += 1;
			break;
	}
	return {
		id: parent.id,
		title: parent.title,
		status: parent.status,
		total: children.length,
		done,
		active,
		pending,
		cancelled
	};
}
/**
* Compute epic-progress rows via the canonical task-rollup facade.
*
* T948: this is the production path. For every non-archived epic we issue a
* single `computeRollup` call to get the parent's exec status plus a
* `computeRollupsBatch` for its direct children, then delegate to
* {@link _epicRowFromRollups} for the tally.
*
* T958: `options.includeDeferred` renamed to `options.includeCancelled`. The
* deprecated key is still accepted for one release.
*
* @param projectPath - Absolute path to the active project (from
*                      `locals.projectCtx.projectPath`). Passed straight to
*                      `Cleo.forProject` so the DataAccessor opens against
*                      the right tasks.db.
* @param options.includeCancelled - Include `status='cancelled'` epics.
* @param options.includeDeferred - Deprecated alias for `includeCancelled`.
* @returns Epic progress rows in deterministic (sorted-id) order.
*/
async function _computeEpicProgressViaRollup(projectPath, options = {}) {
	const includeCancelled = resolveIncludeCancelled(options);
	const accessor = await getTaskAccessor(projectPath);
	const epics = (await listTasks({
		type: "epic",
		excludeArchived: true,
		sortByPriority: false,
		limit: 1e3
	}, projectPath, accessor)).tasks.filter((e) => includeCancelled || e.status !== "cancelled").sort((a, b) => a.id.localeCompare(b.id));
	const rows = [];
	for (const epic of epics) {
		const childRollups = await computeTaskRollups((await listTasks({
			parentId: epic.id,
			excludeArchived: true,
			sortByPriority: false,
			limit: 1e3
		}, projectPath, accessor)).tasks.map((c) => c.id), accessor);
		rows.push(_epicRowFromRollups({
			id: epic.id,
			title: epic.title,
			status: epic.status
		}, childRollups));
	}
	return rows;
}
/**
* One-time guard so the server only warns about a legacy `?deferred=1` URL
* once per process lifetime, regardless of how many `/tasks` page loads see
* the param. Mirrors the client-side guard in
* `packages/studio/src/lib/stores/task-filters.svelte.ts`.
*/
var legacyDeferredWarningEmitted = false;
/**
* Emit a one-time `console.warn` flagging `?deferred=1` as deprecated.
*
* @internal
*/
function warnLegacyDeferredParamOnce() {
	if (legacyDeferredWarningEmitted) return;
	legacyDeferredWarningEmitted = true;
	console.warn("[tasks/+page.server] ?deferred=1 is deprecated; use ?cancelled=1. Alias removal tracked as a follow-up to T958.");
}
/**
* @internal
* Test-only hook to reset the one-time `?deferred=1` warning guard so
* repeated test cases can observe the warning firing exactly once per
* scenario.
*/
function __resetLegacyDeferredParamWarningForTests() {
	legacyDeferredWarningEmitted = false;
}
/**
* Empty explorer-bundle stub returned whenever the shared loader cannot
* produce a payload (missing tasks.db, half-initialised project, or the
* loader threw). The hybrid `/tasks` page can still render the dashboard
* panel and show an "Explorer empty" message without crashing.
*/
function emptyExplorerBundle() {
	return {
		tasks: [],
		deps: [],
		epicProgress: {},
		labels: [],
		loadedAt: (/* @__PURE__ */ new Date()).toISOString()
	};
}
/**
* Load the shared Task Explorer payload side-by-side with the dashboard.
*
* Extracted as its own helper so the try/catch around the explorer loader
* stays surgical — an Explorer failure must NOT blank the dashboard panel.
*
* @param ctx - Active project context (from `locals.projectCtx`).
* @param includeArchived - Pass through the dashboard archived toggle.
* @returns The explorer bundle, or an empty stub on any failure.
*
* @internal
*/
async function loadExplorerSafe(ctx, includeArchived) {
	try {
		return await loadExplorerBundle({
			projectCtx: ctx,
			includeArchived
		});
	} catch {
		return emptyExplorerBundle();
	}
}
var load = async ({ locals, url }) => {
	const db = getTasksDb(locals.projectCtx);
	const cancelledParam = url.searchParams.get("cancelled") === "1";
	const legacyDeferredParam = url.searchParams.get("deferred") === "1";
	if (legacyDeferredParam) warnLegacyDeferredParamOnce();
	const showCancelled = cancelledParam || legacyDeferredParam;
	const showArchived = url.searchParams.get("archived") === "1";
	const filters = {
		showCancelled,
		showArchived
	};
	const explorerPromise = loadExplorerSafe(locals.projectCtx, showArchived);
	if (!db) return {
		stats: null,
		recentTasks: [],
		epicProgress: [],
		filters,
		explorer: await explorerPromise
	};
	try {
		const countByStatus = db.prepare("SELECT status, COUNT(*) as cnt FROM tasks GROUP BY status").all();
		const countByPriority = db.prepare(`SELECT priority, COUNT(*) as cnt FROM tasks WHERE status != 'archived' GROUP BY priority`).all();
		const countByType = db.prepare(`SELECT type, COUNT(*) as cnt FROM tasks WHERE status != 'archived' GROUP BY type`).all();
		const statusMap = Object.fromEntries(countByStatus.map((r) => [r.status, r.cnt]));
		const priorityMap = Object.fromEntries(countByPriority.map((r) => [r.priority, r.cnt]));
		const typeMap = Object.fromEntries(countByType.map((r) => [r.type, r.cnt]));
		const stats = {
			total: (statusMap["pending"] ?? 0) + (statusMap["active"] ?? 0) + (statusMap["done"] ?? 0) + (statusMap["cancelled"] ?? 0),
			pending: statusMap["pending"] ?? 0,
			active: statusMap["active"] ?? 0,
			done: statusMap["done"] ?? 0,
			cancelled: statusMap["cancelled"] ?? 0,
			archived: statusMap["archived"] ?? 0,
			critical: priorityMap["critical"] ?? 0,
			high: priorityMap["high"] ?? 0,
			medium: priorityMap["medium"] ?? 0,
			low: priorityMap["low"] ?? 0,
			epics: typeMap["epic"] ?? 0,
			tasks: typeMap["task"] ?? 0,
			subtasks: typeMap["subtask"] ?? 0
		};
		const recentStatusFilter = showArchived ? `status IN ('active', 'pending', 'done', 'archived')` : `status IN ('active', 'pending', 'done')`;
		const recentTasks = db.prepare(`SELECT id, title, status, priority, type, pipeline_stage, updated_at
         FROM tasks
         WHERE ${recentStatusFilter}
         ORDER BY updated_at DESC
         LIMIT 20`).all().map((row) => ({
			id: row.id,
			title: row.title,
			status: narrowStatus(row.status, row.id),
			priority: narrowPriority(row.priority, row.id),
			type: row.type,
			pipeline_stage: row.pipeline_stage,
			updated_at: row.updated_at
		}));
		let epicProgress = [];
		try {
			epicProgress = await _computeEpicProgressViaRollup(locals.projectCtx.projectPath, { includeCancelled: showCancelled });
		} catch {
			epicProgress = _computeEpicProgress(db, { includeCancelled: showCancelled });
		}
		const explorer = await explorerPromise;
		return {
			stats,
			recentTasks,
			epicProgress,
			filters,
			explorer
		};
	} catch {
		return {
			stats: null,
			recentTasks: [],
			epicProgress: [],
			filters,
			explorer: await explorerPromise
		};
	}
};

var _page_server_ts = /*#__PURE__*/Object.freeze({
	__proto__: null,
	__resetLegacyDeferredParamWarningForTests: __resetLegacyDeferredParamWarningForTests,
	_computeEpicProgress: _computeEpicProgress,
	_computeEpicProgressViaRollup: _computeEpicProgressViaRollup,
	_epicRowFromRollups: _epicRowFromRollups,
	load: load
});

const index = 25;
let component_cache;
const component = async () => component_cache ??= (await import('./_page.svelte-DUp53mgZ.js')).default;
const server_id = "src/routes/tasks/+page.server.ts";
const imports = ["_app/immutable/nodes/25.C0ejG1e1.js","_app/immutable/chunks/CQQRJ2Hr.js","_app/immutable/chunks/DyGQ_VXC.js","_app/immutable/chunks/DrKWWDpL.js","_app/immutable/chunks/DKX-2-1g.js","_app/immutable/chunks/CorFgzUk.js","_app/immutable/chunks/BgPpRtmk.js","_app/immutable/chunks/BrUKpZTl.js","_app/immutable/chunks/DsQIgu-4.js","_app/immutable/chunks/Bcuvp8aL.js","_app/immutable/chunks/DnOaYask.js","_app/immutable/chunks/Cjus22ap.js","_app/immutable/chunks/DOqzs8kl2.js","_app/immutable/chunks/DTkg6Mnx.js","_app/immutable/chunks/DIQmuJJZ.js","_app/immutable/chunks/D7w7HllH.js","_app/immutable/chunks/DB5ifLM-.js","_app/immutable/chunks/CxlOpib82.js","_app/immutable/chunks/BKc98lKx.js","_app/immutable/chunks/DsanjglN.js","_app/immutable/chunks/CbGRcr-D.js","_app/immutable/chunks/CX8DOZuw2.js","_app/immutable/chunks/djL6V-tr.js","_app/immutable/chunks/CQCxd1p9.js","_app/immutable/chunks/JPJd4fEI.js","_app/immutable/chunks/RptFUp2P.js","_app/immutable/chunks/CEqOYim7.js","_app/immutable/chunks/CqF5Lomf.js"];
const stylesheets = ["_app/immutable/assets/StatBlock.DX6OXz7z.css","_app/immutable/assets/no-face-up.BlswZ73M.css","_app/immutable/assets/Tabs.CU9_rsWl.css","_app/immutable/assets/ui.CH-9N9-0.css","_app/immutable/assets/tasks.BZWJL4jq.css","_app/immutable/assets/25.BtvG5YXz.css"];
const fonts = [];

export { component, fonts, imports, index, _page_server_ts as server, server_id, stylesheets };
//# sourceMappingURL=25-Zyx-RzC4.js.map
