import { c as getProjectRoot } from './paths-2M_UxD_H.js';
import { e as getBrainDb, d as getBrainNativeDb } from './sqlite-Dsbe0wec.js';
import { t as truncateString } from './sessions-j73dkbCI.js';
import './memory-schema-Bi7cChwo.js';
import './index-IVoIz4D5.js';
import 'node:fs';
import 'node:path';
import 'node:crypto';
import 'node:fs/promises';
import './index-Ca4C2M45.js';
import { t as typedAll } from './typed-query-l1D_QElt.js';
import './conduit-Ca_OFWR_.js';
import './sqlite-data-accessor-C59wZ0zp.js';
import './brain-maintenance-bSR6GwAG.js';
import './graph-auto-populate2-DYsUNGSL.js';
import { a as searchDecisions, l as listDecisions } from './decisions-CuNeBqZW.js';
import './dist4-CiQ5cizO.js';
import { a as searchLearnings } from './learnings2-2m2p7lzT.js';
import { a as searchPatterns } from './patterns2-DYKfsbwN.js';
import './observer-reflector2-D8nxuglX.js';

//#region ../core/dist/memory/graph-queries.js
/**
* Brain graph traversal queries using recursive CTEs and native SQLite.
*
* Implements BFS traversal, typed neighbor lookup, 360-degree context view,
* and aggregate statistics for the brain_page_nodes / brain_page_edges graph
* populated by T528 + T530.
*
* Uses getBrainNativeDb() (DatabaseSync) for recursive CTEs that Drizzle's
* ORM layer cannot express directly.
*
* @task T535
* @epic T523
*/
/**
* Return aggregate counts for brain_page_nodes and brain_page_edges by type.
*
* @param projectRoot - Absolute path to the project root
* @returns Counts by node type and edge type, plus totals
*
* @example
* ```typescript
* const stats = await graphStats('/project');
* console.log(stats.totalNodes, stats.totalEdges);
* ```
*/
async function graphStats(projectRoot) {
	await getBrainDb(projectRoot);
	const nativeDb = getBrainNativeDb();
	if (!nativeDb) return {
		nodesByType: [],
		edgesByType: [],
		totalNodes: 0,
		totalEdges: 0
	};
	const nodeRows = typedAll(nativeDb.prepare(`SELECT node_type, COUNT(*) AS count
       FROM brain_page_nodes GROUP BY node_type ORDER BY count DESC`));
	const edgeRows = typedAll(nativeDb.prepare(`SELECT edge_type, COUNT(*) AS count
       FROM brain_page_edges GROUP BY edge_type ORDER BY count DESC`));
	const totalNodes = nodeRows.reduce((s, r) => s + r.count, 0);
	const totalEdges = edgeRows.reduce((s, r) => s + r.count, 0);
	return {
		nodesByType: nodeRows.map((r) => ({
			nodeType: r.node_type,
			count: r.count
		})),
		edgesByType: edgeRows.map((r) => ({
			edgeType: r.edge_type,
			count: r.count
		})),
		totalNodes,
		totalEdges
	};
}
//#endregion
//#region ../core/dist/memory/public-api.js
/**
* Public API for the memory domain — promoted from internal to public barrel.
*
* These functions are consumed by CLI commands (`packages/cleo`) and Studio
* routes (`packages/studio`) and are therefore part of the stable public
* surface of `@cleocode/core/memory`.
*
* None of these functions issue raw SQL; they compose over the existing
* BRAIN retrieval, quality-feedback, decisions, patterns, and learnings
* modules which own their respective schemas.
*
* @packageDocumentation
* @task T9615
* @epic T9592
*/
/** Default preview length (chars) for memory-search hit narratives. */
var PREVIEW_LEN = 160;
/**
* Cross-table LIKE search across all four brain tables.
*
* @param opts - Search options including query text, table filter, and limit
* @returns Flat list of matching entries sorted by citation count descending
*
* @remarks
* Uses LIKE-based scans. For heavy workloads, prefer the dispatch-layer
* `memory.find` operation which uses the full RRF fusion pipeline.
*
* @example
* ```typescript
* const result = await findMemoryEntries({ query: 'authentication', limit: 10 });
* console.log(`Found ${result.total} matches`);
* ```
*
* @task T9615
*/
async function findMemoryEntries(opts) {
	const { query, tables, limit = 25 } = opts;
	const db = getBrainNativeDb();
	const ALLOWED = [
		"observations",
		"decisions",
		"patterns",
		"learnings"
	];
	const requestedTables = tables && tables.length > 0 ? tables.filter((t) => ALLOWED.includes(t)) : [...ALLOWED];
	const cap = Math.max(1, Math.min(100, limit));
	if (!query.trim()) return {
		query,
		hits: [],
		total: 0
	};
	if (!db) return {
		query,
		hits: [],
		total: 0
	};
	const like = `%${query.replace(/[%_]/g, (c) => `\\${c}`)}%`;
	const hits = [];
	if (requestedTables.includes("observations")) try {
		const rows = db.prepare(`SELECT id, title, narrative, quality_score, memory_tier, verified,
                  citation_count, created_at
           FROM brain_observations
           WHERE (title LIKE ? ESCAPE '\\' OR narrative LIKE ? ESCAPE '\\')
             AND invalid_at IS NULL
           ORDER BY citation_count DESC, created_at DESC
           LIMIT ?`).all(like, like, cap);
		for (const r of rows) hits.push({
			id: r.id,
			table: "observations",
			title: r.title ?? "(untitled)",
			preview: truncateString(r.narrative, PREVIEW_LEN),
			createdAt: r.created_at,
			quality: r.quality_score,
			tier: r.memory_tier,
			verified: r.verified,
			citations: r.citation_count
		});
	} catch {}
	if (requestedTables.includes("decisions")) try {
		const rows = db.prepare(`SELECT id, decision, rationale, quality_score, memory_tier, verified,
                  created_at
           FROM brain_decisions
           WHERE (decision LIKE ? ESCAPE '\\' OR rationale LIKE ? ESCAPE '\\')
             AND invalid_at IS NULL
           ORDER BY created_at DESC
           LIMIT ?`).all(like, like, cap);
		for (const r of rows) hits.push({
			id: r.id,
			table: "decisions",
			title: truncateString(r.decision, 100),
			preview: truncateString(r.rationale, PREVIEW_LEN),
			createdAt: r.created_at,
			quality: r.quality_score,
			tier: r.memory_tier,
			verified: r.verified,
			citations: 0
		});
	} catch {}
	if (requestedTables.includes("patterns")) try {
		const rows = db.prepare(`SELECT id, pattern, context, quality_score, memory_tier, verified,
                  citation_count, extracted_at
           FROM brain_patterns
           WHERE (pattern LIKE ? ESCAPE '\\' OR context LIKE ? ESCAPE '\\')
             AND invalid_at IS NULL
           ORDER BY citation_count DESC, extracted_at DESC
           LIMIT ?`).all(like, like, cap);
		for (const r of rows) hits.push({
			id: r.id,
			table: "patterns",
			title: truncateString(r.pattern, 100),
			preview: truncateString(r.context, PREVIEW_LEN),
			createdAt: r.extracted_at,
			quality: r.quality_score,
			tier: r.memory_tier,
			verified: r.verified,
			citations: r.citation_count
		});
	} catch {}
	if (requestedTables.includes("learnings")) try {
		const rows = db.prepare(`SELECT id, insight, source, quality_score, memory_tier, verified,
                  citation_count, created_at
           FROM brain_learnings
           WHERE (insight LIKE ? ESCAPE '\\' OR source LIKE ? ESCAPE '\\')
             AND invalid_at IS NULL
           ORDER BY citation_count DESC, created_at DESC
           LIMIT ?`).all(like, like, cap);
		for (const r of rows) hits.push({
			id: r.id,
			table: "learnings",
			title: truncateString(r.insight, 100),
			preview: truncateString(r.source, PREVIEW_LEN),
			createdAt: r.created_at,
			quality: r.quality_score,
			tier: r.memory_tier,
			verified: r.verified,
			citations: r.citation_count
		});
	} catch {}
	return {
		query,
		hits,
		total: hits.length
	};
}
/**
* List brain observations with optional filter by tier, type, and quality.
*
* @param opts - Optional filter and pagination options
* @returns Paginated observation list plus total row count
*
* @example
* ```typescript
* const result = await getObservations({ tier: 'long', minQuality: 0.7 });
* console.log(`${result.filtered} high-quality long-tier observations`);
* ```
*
* @task T9615
*/
async function getObservations(opts = {}) {
	const { tier, type, minQuality, limit = 200 } = opts;
	const db = getBrainNativeDb();
	const cap = Math.max(1, Math.min(500, limit));
	if (!db) return {
		observations: [],
		total: 0,
		filtered: 0
	};
	try {
		const totalRow = db.prepare("SELECT COUNT(*) as cnt FROM brain_observations").get();
		const conditions = [];
		const params = [];
		if (tier) {
			conditions.push("memory_tier = ?");
			params.push(tier);
		}
		if (type) {
			conditions.push("memory_type = ?");
			params.push(type);
		}
		if (minQuality !== void 0) {
			conditions.push("(quality_score IS NULL OR quality_score >= ?)");
			params.push(minQuality);
		}
		const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
		const observations = db.prepare(`SELECT id, type, title, subtitle, narrative, project,
                quality_score, memory_tier, memory_type, verified,
                valid_at, invalid_at, source_confidence, citation_count,
                prune_candidate, created_at
         FROM brain_observations
         ${whereClause}
         ORDER BY created_at DESC
         LIMIT ?`).all(...params, cap).map((r) => ({
			id: r.id,
			type: r.type,
			title: r.title,
			subtitle: r.subtitle,
			narrative: r.narrative,
			project: r.project,
			qualityScore: r.quality_score,
			memoryTier: r.memory_tier,
			memoryType: r.memory_type,
			verified: r.verified,
			validAt: r.valid_at,
			invalidAt: r.invalid_at,
			sourceConfidence: r.source_confidence,
			citationCount: r.citation_count,
			pruneCandidate: r.prune_candidate,
			createdAt: r.created_at
		}));
		return {
			observations,
			total: totalRow.cnt,
			filtered: observations.length
		};
	} catch {
		return {
			observations: [],
			total: 0,
			filtered: 0
		};
	}
}
/**
* Retrieve decision records from brain.db, optionally filtered by text query.
*
* @param opts - Query, project path, and limit options
* @returns Array of decision records
*
* @example
* ```typescript
* const { decisions } = await getDecisions({ query: 'database architecture', limit: 20 });
* ```
*
* @task T9615
*/
async function getDecisions(opts = {}) {
	const { query = "", projectPath, limit = 50 } = opts;
	const root = projectPath ?? getProjectRoot();
	if (query.trim()) return { decisions: (await searchDecisions(root, {
		query,
		limit
	})).map((d) => ({
		id: d.id,
		decision: d.decision,
		rationale: d.rationale ?? null,
		outcome: d.outcome ?? null,
		createdAt: d.createdAt,
		memoryTier: d.memoryTier ?? null,
		verified: d.verified ? 1 : 0
	})) };
	const { decisions: resultList } = await listDecisions(root, { limit });
	return { decisions: resultList.map((d) => ({
		id: d.id,
		decision: d.decision,
		rationale: d.rationale ?? null,
		outcome: d.outcome ?? null,
		createdAt: d.createdAt,
		memoryTier: d.memoryTier ?? null,
		verified: d.verified ? 1 : 0
	})) };
}
/**
* Retrieve pattern records from brain.db, optionally filtered by text query.
*
* @param opts - Query, project path, and limit options
* @returns Array of pattern records
*
* @example
* ```typescript
* const { patterns } = await getPatterns({ query: 'authentication', patternType: 'success' });
* ```
*
* @task T9615
*/
async function getPatterns(opts = {}) {
	const { query = "", patternType, projectPath, limit = 50 } = opts;
	return { patterns: (await searchPatterns(projectPath ?? getProjectRoot(), {
		query: query || void 0,
		type: patternType,
		limit
	})).map((p) => ({
		id: p.id,
		pattern: p.pattern,
		context: p.context ?? null,
		patternType: p.type ?? null,
		impact: p.impact ?? null,
		extractedAt: p.extractedAt,
		memoryTier: p.memoryTier ?? null,
		citationCount: p.citationCount ?? p.frequency ?? 0
	})) };
}
/**
* Retrieve learning records from brain.db, optionally filtered by text query.
*
* @param opts - Query, project path, and limit options
* @returns Array of learning records
*
* @example
* ```typescript
* const { learnings } = await getLearnings({ query: 'cache invalidation' });
* ```
*
* @task T9615
*/
async function getLearnings(opts = {}) {
	const { query = "", projectPath, limit = 50 } = opts;
	return { learnings: (await searchLearnings(projectPath ?? getProjectRoot(), {
		query: query || void 0,
		limit
	})).map((l) => ({
		id: l.id,
		insight: l.insight,
		source: l.source ?? null,
		learningType: l.memoryType ?? null,
		createdAt: l.createdAt,
		memoryTier: l.memoryTier ?? null,
		citationCount: l.citationCount ?? 0
	})) };
}
/**
* Return aggregate statistics for the BRAIN memory graph.
*
* @param opts - Optional project path
* @returns Aggregate graph statistics (node count, edge count, type distribution)
*
* @example
* ```typescript
* const stats = await getMemoryGraph({ projectPath: '/my/project' });
* console.log(`Graph: ${stats.nodeCount} nodes, ${stats.edgeCount} edges`);
* ```
*
* @task T9615
*/
async function getMemoryGraph(opts = {}) {
	const raw = await graphStats(opts.projectPath ?? getProjectRoot());
	const edgeTypeDistribution = {};
	for (const e of raw.edgesByType) edgeTypeDistribution[e.edgeType] = e.count;
	return {
		nodeCount: raw.totalNodes,
		edgeCount: raw.totalEdges,
		edgeTypeDistribution,
		averageEdgesPerNode: raw.totalNodes > 0 ? raw.totalEdges / raw.totalNodes : 0
	};
}
/**
* Return tier distribution and upcoming long-tier promotions.
*
* @param projectPath - Optional project root path
* @returns Per-table tier counts and top-5 upcoming promotions
*
* @example
* ```typescript
* const stats = await getTierStats('/my/project');
* console.log(`Short: ${stats.tables[0]?.short}, Long: ${stats.tables[0]?.long}`);
* ```
*
* @task T9615
*/
async function getTierStats(_projectPath) {
	const db = getBrainNativeDb();
	if (!db) return {
		tables: [],
		upcomingLongPromotions: []
	};
	const brainTables = [
		{
			name: "brain_observations",
			dateCol: "created_at"
		},
		{
			name: "brain_learnings",
			dateCol: "created_at"
		},
		{
			name: "brain_patterns",
			dateCol: "extracted_at"
		},
		{
			name: "brain_decisions",
			dateCol: "created_at"
		}
	];
	const tables = [];
	for (const { name: tblName } of brainTables) try {
		const rows = db.prepare(`SELECT COALESCE(memory_tier, 'short') as tier, COUNT(*) as cnt
           FROM ${tblName}
           WHERE invalid_at IS NULL
           GROUP BY memory_tier`).all();
		const counts = {
			table: tblName,
			short: 0,
			medium: 0,
			long: 0
		};
		for (const r of rows) if (r.tier === "short") counts.short = r.cnt;
		else if (r.tier === "medium") counts.medium = r.cnt;
		else if (r.tier === "long") counts.long = r.cnt;
		tables.push(counts);
	} catch {
		tables.push({
			table: tblName,
			short: 0,
			medium: 0,
			long: 0
		});
	}
	const age7dMs = 10080 * 60 * 1e3;
	const nowMs = Date.now();
	const upcoming = [];
	for (const { name: tblName, dateCol } of brainTables) try {
		const rows = db.prepare(`SELECT id, ${dateCol} as created_at, citation_count, verified
           FROM ${tblName}
           WHERE memory_tier = 'medium'
             AND invalid_at IS NULL
             AND (citation_count >= 5 OR verified = 1)
           ORDER BY ${dateCol} ASC
           LIMIT 20`).all();
		for (const r of rows) {
			const promotionMs = (/* @__PURE__ */ new Date(r.created_at.replace(" ", "T") + "Z")).getTime() + age7dMs;
			const daysUntil = Math.max(0, (promotionMs - nowMs) / (1440 * 60 * 1e3));
			const track = r.citation_count >= 5 ? `citation (${r.citation_count})` : "verified";
			upcoming.push({
				id: r.id,
				table: tblName,
				daysUntil,
				track
			});
		}
	} catch {}
	upcoming.sort((a, b) => a.daysUntil - b.daysUntil);
	return {
		tables,
		upcomingLongPromotions: upcoming.slice(0, 5)
	};
}
var PENDING_VERIFY_TABLES = [
	{
		table: "observations",
		sql: `SELECT id, title, source_confidence AS sourceConfidence,
                 citation_count AS citationCount, memory_tier AS memoryTier,
                 created_at AS createdAt
          FROM brain_observations
          WHERE verified = 0
            AND invalid_at IS NULL
            AND citation_count >= ?
          ORDER BY citation_count DESC, created_at DESC
          LIMIT ?`
	},
	{
		table: "decisions",
		sql: `SELECT id, decision AS title, NULL AS sourceConfidence,
                 COALESCE(citation_count, 0) AS citationCount,
                 memory_tier AS memoryTier,
                 created_at AS createdAt
          FROM brain_decisions
          WHERE verified = 0
            AND invalid_at IS NULL
            AND COALESCE(citation_count, 0) >= ?
          ORDER BY citation_count DESC, created_at DESC
          LIMIT ?`
	},
	{
		table: "patterns",
		sql: `SELECT id, pattern AS title, NULL AS sourceConfidence,
                 citation_count AS citationCount, memory_tier AS memoryTier,
                 extracted_at AS createdAt
          FROM brain_patterns
          WHERE verified = 0
            AND invalid_at IS NULL
            AND citation_count >= ?
          ORDER BY citation_count DESC, extracted_at DESC
          LIMIT ?`
	},
	{
		table: "learnings",
		sql: `SELECT id, insight AS title, NULL AS sourceConfidence,
                 citation_count AS citationCount, memory_tier AS memoryTier,
                 created_at AS createdAt
          FROM brain_learnings
          WHERE verified = 0
            AND invalid_at IS NULL
            AND citation_count >= ?
          ORDER BY citation_count DESC, created_at DESC
          LIMIT ?`
	}
];
/**
* Return unverified but highly-cited brain entries across all four tables.
*
* These are entries that the system keeps retrieving but the owner has not
* promoted to ground-truth status. Exposing them surfaces the highest-leverage
* candidates for `cleo memory verify`.
*
* @param projectPath - Optional project root path
* @param opts - Minimum citation count and result limit
* @returns Ranked list of pending-verify entries plus a hint
*
* @example
* ```typescript
* const result = await getPendingVerify('/my/project', { minCitations: 3 });
* console.log(`${result.count} entries awaiting verification`);
* ```
*
* @task T9615
*/
async function getPendingVerify(_projectPath, opts = {}) {
	const { minCitations = 5, limit = 50 } = opts;
	const db = getBrainNativeDb();
	const cap = Math.max(1, Math.min(200, limit));
	if (!db) return {
		count: 0,
		minCitations,
		items: [],
		hint: "brain.db not available; start a session to populate memory."
	};
	const items = [];
	for (const spec of PENDING_VERIFY_TABLES) try {
		const rows = db.prepare(spec.sql).all(minCitations, cap);
		for (const r of rows) items.push({
			id: r.id,
			title: r.title,
			sourceConfidence: r.sourceConfidence,
			citationCount: r.citationCount,
			memoryTier: r.memoryTier,
			createdAt: r.createdAt,
			table: spec.table
		});
	} catch {}
	items.sort((a, b) => b.citationCount - a.citationCount);
	const top = items.slice(0, cap);
	const hint = top.length === 0 ? `No entries with >= ${minCitations} citations. Lower the threshold or wait for more retrievals.` : `Promote entries the system keeps citing — use 'cleo memory verify <id>' to lock them to ground truth.`;
	return {
		count: top.length,
		minCitations,
		items: top,
		hint
	};
}

export { getMemoryGraph as a, getLearnings as b, getObservations as c, getPatterns as d, getPendingVerify as e, findMemoryEntries as f, getDecisions as g, getTierStats as h };
//# sourceMappingURL=memory-bIw5xh1c.js.map
