//#region ../core/dist/intelligence/prediction.js
/**
* Quality Prediction module for the CLEO Intelligence dimension.
*
* Provides risk scoring for tasks based on complexity, historical patterns,
* and blocking analysis. Also predicts lifecycle gate validation outcomes
* using brain_patterns and brain_learnings data.
*
* Uses the existing BrainDataAccessor and DataAccessor — no new tables.
*
* @task Wave3A
* @epic T5149
*/
/** Risk factor weights — tuned to prioritize blocking risk and complexity. */
var RISK_WEIGHTS = {
	complexity: .25,
	historicalFailure: .25,
	blockingRisk: .3,
	dependencyDepth: .2
};
/** Thresholds for risk level recommendations. */
var RISK_THRESHOLDS = {
	low: .3,
	medium: .6,
	high: .8
};
/** Size-to-complexity mapping (0-1 scale). */
var SIZE_COMPLEXITY = {
	small: .2,
	medium: .5,
	large: .8
};
/**
* Calculate the risk score for a task based on multiple contributing factors.
*
* Factors considered:
* - Task complexity (size, dependency count, hierarchy depth)
* - Historical patterns (similar tasks' failure rates from brain_patterns)
* - Blocking risk (does this task block others?)
* - Dependency depth (how deep in the dependency chain)
*
* @param taskId - The task to assess
* @param taskAccessor - DataAccessor for tasks.db
* @param brainAccessor - BrainDataAccessor for brain.db
* @returns A complete risk assessment with score, confidence, factors, and recommendation
*/
async function calculateTaskRisk(taskId, taskAccessor, brainAccessor) {
	const task = await taskAccessor.loadSingleTask(taskId);
	if (!task) return {
		taskId,
		riskScore: 0,
		confidence: 0,
		factors: [],
		recommendation: `Task ${taskId} not found — cannot assess risk.`
	};
	const factors = [];
	let dataPoints = 0;
	const complexityFactor = await computeComplexityFactor(task, taskAccessor);
	factors.push(complexityFactor);
	dataPoints += 1;
	const historicalFactor = await computeHistoricalFailureFactor(task, brainAccessor);
	factors.push(historicalFactor);
	if (historicalFactor.value > 0) dataPoints += 1;
	const blockingFactor = await computeBlockingFactor(task, taskAccessor);
	factors.push(blockingFactor);
	dataPoints += 1;
	const depthFactor = await computeDependencyDepthFactor(task, taskAccessor);
	factors.push(depthFactor);
	dataPoints += 1;
	const riskScore = computeWeightedScore(factors);
	const confidence = Math.min(1, .25 + dataPoints / 4 * .75);
	const recommendation = generateRecommendation(riskScore, factors);
	return {
		taskId,
		riskScore: Math.round(riskScore * 1e3) / 1e3,
		confidence: Math.round(confidence * 1e3) / 1e3,
		factors,
		recommendation
	};
}
async function computeComplexityFactor(task, accessor) {
	const depCount = task.depends?.length ?? 0;
	let childCount = 0;
	try {
		childCount = await accessor.countChildren(task.id);
	} catch {}
	const sizeValue = SIZE_COMPLEXITY[task.size ?? "medium"] ?? .5;
	const depNormalized = Math.min(depCount / 10, 1);
	const childNormalized = Math.min(childCount / 20, 1);
	const value = sizeValue * .4 + depNormalized * .3 + childNormalized * .3;
	const parts = [];
	if (task.size) parts.push(`size=${task.size}`);
	if (depCount > 0) parts.push(`${depCount} dependencies`);
	if (childCount > 0) parts.push(`${childCount} children`);
	return {
		name: "complexity",
		weight: RISK_WEIGHTS.complexity,
		value: Math.round(value * 1e3) / 1e3,
		description: parts.length > 0 ? `Task complexity based on ${parts.join(", ")}` : "Default complexity (no size/deps/children data)"
	};
}
async function computeHistoricalFailureFactor(task, brainAccessor) {
	const failurePatterns = await brainAccessor.findPatterns({
		type: "failure",
		limit: 50
	});
	const blockerPatterns = await brainAccessor.findPatterns({
		type: "blocker",
		limit: 50
	});
	const allNegativePatterns = [...failurePatterns, ...blockerPatterns];
	if (allNegativePatterns.length === 0) return {
		name: "historical_failure",
		weight: RISK_WEIGHTS.historicalFailure,
		value: 0,
		description: "No historical failure patterns found in brain.db"
	};
	let matchCount = 0;
	let totalFailureRate = 0;
	const taskLabels = new Set((task.labels ?? []).map((l) => l.toLowerCase()));
	const taskTitle = task.title.toLowerCase();
	const taskDesc = (task.description ?? "").toLowerCase();
	for (const p of allNegativePatterns) {
		const patternText = p.pattern.toLowerCase();
		const contextText = p.context.toLowerCase();
		const hasLabelMatch = taskLabels.size > 0 && [...taskLabels].some((l) => patternText.includes(l) || contextText.includes(l));
		const hasTitleMatch = patternText.includes(taskTitle) || taskTitle.includes(patternText.slice(0, 20));
		const hasDescMatch = taskDesc.length > 10 && (patternText.includes(taskDesc.slice(0, 30)) || taskDesc.includes(patternText.slice(0, 30)));
		if (hasLabelMatch || hasTitleMatch || hasDescMatch) {
			matchCount++;
			const failureRate = p.successRate !== null ? 1 - p.successRate : .5;
			totalFailureRate += failureRate;
		}
	}
	if (matchCount === 0) return {
		name: "historical_failure",
		weight: RISK_WEIGHTS.historicalFailure,
		value: 0,
		description: "No matching historical failure patterns for this task"
	};
	const avgFailureRate = totalFailureRate / matchCount;
	return {
		name: "historical_failure",
		weight: RISK_WEIGHTS.historicalFailure,
		value: Math.round(avgFailureRate * 1e3) / 1e3,
		description: `${matchCount} matching failure/blocker pattern(s) with avg failure rate ${Math.round(avgFailureRate * 100)}%`
	};
}
async function computeBlockingFactor(task, accessor) {
	let blockedCount = 0;
	try {
		const { tasks: allTasks } = await accessor.queryTasks({ status: [
			"pending",
			"active",
			"blocked"
		] });
		for (const t of allTasks) if (t.depends?.includes(task.id)) blockedCount++;
	} catch {}
	const value = Math.min(blockedCount / 5, 1);
	return {
		name: "blocking_risk",
		weight: RISK_WEIGHTS.blockingRisk,
		value: Math.round(value * 1e3) / 1e3,
		description: blockedCount > 0 ? `This task blocks ${blockedCount} other task(s)` : "This task does not block any other tasks"
	};
}
async function computeDependencyDepthFactor(task, accessor) {
	let depth = 0;
	const visited = /* @__PURE__ */ new Set();
	let current = task;
	while (current.depends && current.depends.length > 0 && depth < 10) {
		const firstDep = current.depends[0];
		if (visited.has(firstDep)) break;
		visited.add(firstDep);
		const depTask = await accessor.loadSingleTask(firstDep);
		if (!depTask) break;
		depth++;
		current = depTask;
	}
	let hierarchyDepth = 0;
	let parentId = task.parentId;
	const visitedParents = /* @__PURE__ */ new Set();
	while (parentId && hierarchyDepth < 10) {
		if (visitedParents.has(parentId)) break;
		visitedParents.add(parentId);
		const parent = await accessor.loadSingleTask(parentId);
		if (!parent) break;
		hierarchyDepth++;
		parentId = parent.parentId;
	}
	const totalDepth = depth + hierarchyDepth;
	const value = Math.min(totalDepth / 8, 1);
	return {
		name: "dependency_depth",
		weight: RISK_WEIGHTS.dependencyDepth,
		value: Math.round(value * 1e3) / 1e3,
		description: `Dependency chain depth: ${depth}, hierarchy depth: ${hierarchyDepth}`
	};
}
function computeWeightedScore(factors) {
	let totalWeight = 0;
	let weightedSum = 0;
	for (const f of factors) {
		weightedSum += f.weight * f.value;
		totalWeight += f.weight;
	}
	return totalWeight > 0 ? weightedSum / totalWeight : 0;
}
function generateRecommendation(score, factors) {
	if (score <= RISK_THRESHOLDS.low) return "Low risk. Proceed with normal workflow.";
	if (score <= RISK_THRESHOLDS.medium) return `Moderate risk (${factors.filter((f) => f.value > .4).sort((a, b) => b.value * b.weight - a.value * a.weight).slice(0, 2).map((f) => f.name).join(", ")}). Consider extra review or decomposition.`;
	if (score <= RISK_THRESHOLDS.high) return "High risk. Recommend decomposition, additional testing, or pair review before proceeding.";
	return "Critical risk. Strongly recommend breaking this task into smaller units and addressing blockers first.";
}

export { calculateTaskRisk };
//# sourceMappingURL=prediction-D1lSGJ4c.js.map
