import { b as getLogger } from './paths-2M_UxD_H.js';
import { b as brainPageNodes, a as brainPageEdges } from './memory-schema-Bi7cChwo.js';
import { e as getBrainDb } from './sqlite-Dsbe0wec.js';
import { createHash } from 'node:crypto';

//#region ../core/dist/memory/graph-auto-populate.js
/**
* Graph auto-population helpers for CLEO BRAIN.
*
* Provides upsertGraphNode and addGraphEdge helpers that write to the
* brain_page_nodes and brain_page_edges tables whenever memory entries
* are created via the legitimate write paths (storeDecision, observeBrain,
* storePattern, storeLearning, and task completion).
*
* Design constraints:
* - All writes are BEST-EFFORT — never block or fail the primary operation.
* - All writes are gated on brain.autoCapture via isAutoCaptureEnabled.
* - Uses INSERT OR REPLACE (onConflictDoUpdate) for upsert semantics.
* - Edge inserts are idempotent via the composite PK (fromId, toId, edgeType).
*
* @task T537
* @epic T523
*/
var log = getLogger("brain-graph");
/**
* Return true when brain.autoCapture is enabled for the project.
* Delegates to the shared isAutoCaptureEnabled helper in handler-helpers.ts.
* Returns false on any error to keep graph writes safely disabled when the
* config or brain.db is unavailable.
*/
async function shouldAutoPopulateGraph(projectRoot) {
	try {
		const { isAutoCaptureEnabled } = await import('./handler-helpers-lxU55Ii9.js');
		return isAutoCaptureEnabled(projectRoot);
	} catch {
		return false;
	}
}
/**
* Upsert a graph node for a typed table entry.
*
* Uses INSERT OR REPLACE to handle both new and existing entries. If the
* node already exists (same id), its label, qualityScore, lastActivityAt,
* updatedAt, and metadataJson are refreshed while createdAt is preserved.
*
* The contentHash is derived from a SHA-256 prefix of the canonical content.
* External-reference nodes (task, session, epic) may pass an empty string for
* content; their hash will be null so duplicates are not rejected.
*
* This function is gated on brain.autoCapture. If the gate is disabled or any
* error occurs, it returns silently without throwing.
*
* @param projectRoot - Absolute path to the project root directory.
* @param nodeId - Stable composite ID in the form '<type>:<source-id>'.
* @param nodeType - Discriminated type from BRAIN_NODE_TYPES.
* @param label - Human-readable label (title, task ID, etc.).
* @param qualityScore - 0.0 (noise) to 1.0 (canonical).
* @param content - Canonical text used to derive the content hash.
* @param metadata - Optional type-specific metadata blob.
*
* @task T537
*/
async function upsertGraphNode(projectRoot, nodeId, nodeType, label, qualityScore, content, metadata) {
	try {
		if (!await shouldAutoPopulateGraph(projectRoot)) return;
		const db = await getBrainDb(projectRoot);
		const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
		const trimmed = content.trim().toLowerCase();
		const contentHash = trimmed ? createHash("sha256").update(trimmed).digest("hex").substring(0, 16) : null;
		await db.insert(brainPageNodes).values({
			id: nodeId,
			nodeType,
			label: label.substring(0, 200),
			qualityScore,
			contentHash,
			metadataJson: metadata ? JSON.stringify(metadata) : null,
			lastActivityAt: now,
			createdAt: now,
			updatedAt: now
		}).onConflictDoUpdate({
			target: brainPageNodes.id,
			set: {
				label: label.substring(0, 200),
				qualityScore,
				lastActivityAt: now,
				updatedAt: now,
				metadataJson: metadata ? JSON.stringify(metadata) : null
			}
		});
	} catch (err) {
		log.warn({ err }, "upsertGraphNode failed");
	}
}
/**
* Add a directed, typed edge between two graph nodes (idempotent).
*
* The composite primary key (fromId, toId, edgeType) prevents duplicate edges
* of the same type. Conflicting rows are ignored so this is safe to call
* multiple times with the same arguments.
*
* This function is gated on brain.autoCapture. If the gate is disabled or any
* error occurs, it returns silently without throwing.
*
* @param projectRoot - Absolute path to the project root directory.
* @param fromId - Source node ID (brain_page_nodes.id).
* @param toId - Target node ID (brain_page_nodes.id or external nexus ID).
* @param edgeType - Typed relationship from BRAIN_EDGE_TYPES.
* @param weight - Edge confidence/weight (0.0–1.0). Defaults to 1.0.
* @param provenance - Human-readable note on why this edge was emitted.
*
* @task T537
*/
async function addGraphEdge(projectRoot, fromId, toId, edgeType, weight = 1, provenance) {
	try {
		if (!await shouldAutoPopulateGraph(projectRoot)) return;
		const db = await getBrainDb(projectRoot);
		const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
		await db.insert(brainPageEdges).values({
			fromId,
			toId,
			edgeType,
			weight,
			provenance: provenance ?? null,
			createdAt: now
		}).onConflictDoNothing();
	} catch (err) {
		log.warn({ err }, "addGraphEdge failed");
	}
}
/**
* Upsert a `task:T###` graph node for a task at creation time (not completion).
*
* Prior to T945 Stage A, task nodes were only minted by `completeTask`, which
* meant brand-new tasks were invisible in the graph until they shipped. This
* hook fixes that gap by wiring `task:T###` nodes into `addTask` with a
* quality score of 0.7 (provisional, not yet verified by gate evidence).
*
* Best-effort: any failure is swallowed so graph writes never block the
* task-creation write path.
*
* @param projectRoot - Absolute path to the project root directory.
* @param taskId - CLEO task ID in `T###` format.
* @param title - Task title (used as node label).
* @param metadata - Optional type-specific metadata (priority, type, etc.).
*
* @task T945
*/
async function ensureTaskNode(projectRoot, taskId, title, metadata) {
	try {
		await upsertGraphNode(projectRoot, `task:${taskId}`, "task", `${taskId}: ${title}`.substring(0, 200), .7, title, metadata);
	} catch (err) {
		log.warn({ err }, "ensureTaskNode failed");
	}
}

export { addGraphEdge as a, ensureTaskNode as e, upsertGraphNode as u };
//# sourceMappingURL=graph-auto-populate2-DYsUNGSL.js.map
