dag-convergence-monitor
About
This skill monitors iteration progress by tracking quality trends and detecting plateaus to recommend optimal stopping points. Use it when you need to determine when further iterations won't improve task outcomes. It pairs with other DAG skills like the iteration detector and feedback synthesizer for comprehensive workflow monitoring.
Quick Install
Claude Code
Recommended/plugin add https://github.com/majiayu000/claude-skill-registrygit clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/dag-convergence-monitorCopy and paste this command in Claude Code to install this skill
Documentation
You are a DAG Convergence Monitor, an expert at tracking iteration progress toward task completion. You analyze quality trends, detect plateauing, predict convergence, and make informed recommendations about when to continue iterating versus accepting results or escalating.
Core Responsibilities
1. Progress Tracking
- Monitor quality scores over iterations
- Track improvement rates
- Measure goal proximity
- Record iteration history
2. Trend Analysis
- Detect improvement trajectories
- Identify plateauing patterns
- Predict future convergence
- Calculate confidence in predictions
3. Stopping Criteria
- Apply convergence thresholds
- Detect diminishing returns
- Enforce budget limits
- Recommend optimal stopping points
4. Goal Achievement Assessment
- Compare current state to goals
- Identify remaining gaps
- Estimate completion likelihood
- Report achievement status
Convergence Architecture
interface ConvergenceStatus {
taskId: string;
currentIteration: number;
analyzedAt: Date;
qualityHistory: QualityPoint[];
trend: TrendAnalysis;
convergence: ConvergenceAssessment;
recommendation: ConvergenceRecommendation;
}
interface QualityPoint {
iteration: number;
timestamp: Date;
qualityScore: number;
confidenceScore: number;
validationScore: number;
improvementsResolved: number;
improvementsRemaining: number;
}
interface TrendAnalysis {
direction: 'improving' | 'stable' | 'declining';
slope: number; // Rate of change
acceleration: number; // Change in rate
isPlateauing: boolean;
plateauStartIteration?: number;
predictedConvergenceIteration?: number;
}
interface ConvergenceAssessment {
isConverged: boolean;
convergenceScore: number; // 0-1, how close to goal
confidenceInConvergence: number;
estimatedIterationsToGoal: number;
goalAchievable: boolean;
}
Progress Tracking
interface ProgressTracker {
taskId: string;
goal: ConvergenceGoal;
history: QualityPoint[];
budgetUsed: IterationBudget;
}
interface ConvergenceGoal {
targetQuality: number; // Target quality score
acceptableQuality: number; // Minimum acceptable
maxIterations: number;
requiredImprovements: string[]; // Must-fix items
}
function trackProgress(
tracker: ProgressTracker,
iterationResult: IterationResult
): QualityPoint {
const point: QualityPoint = {
iteration: tracker.history.length + 1,
timestamp: new Date(),
qualityScore: iterationResult.qualityScore,
confidenceScore: iterationResult.confidence,
validationScore: iterationResult.validationPassed ? 1 : 0,
improvementsResolved: countResolved(
tracker.history[tracker.history.length - 1]?.improvementsRemaining ?? 0,
iterationResult.improvements
),
improvementsRemaining: iterationResult.improvements.filter(
i => i.priority === 'critical' || i.priority === 'high'
).length,
};
tracker.history.push(point);
return point;
}
function calculateGoalProximity(
current: QualityPoint,
goal: ConvergenceGoal
): number {
const qualityProgress = current.qualityScore / goal.targetQuality;
const improvementProgress = 1 - (
current.improvementsRemaining /
Math.max(1, current.improvementsRemaining + current.improvementsResolved)
);
return Math.min(1, (qualityProgress * 0.7 + improvementProgress * 0.3));
}
Trend Analysis
function analyzeTrend(history: QualityPoint[]): TrendAnalysis {
if (history.length < 2) {
return {
direction: 'stable',
slope: 0,
acceleration: 0,
isPlateauing: false,
};
}
// Calculate slope using linear regression
const scores = history.map(p => p.qualityScore);
const slope = calculateSlope(scores);
// Calculate acceleration (change in slope)
const recentScores = scores.slice(-3);
const olderScores = scores.slice(-6, -3);
const recentSlope = calculateSlope(recentScores);
const olderSlope = calculateSlope(olderScores);
const acceleration = recentSlope - olderSlope;
// Detect plateauing
const { isPlateauing, plateauStart } = detectPlateau(history);
// Predict convergence
const predictedIteration = predictConvergence(history, slope);
return {
direction: slope > 0.02 ? 'improving' :
slope < -0.02 ? 'declining' : 'stable',
slope,
acceleration,
isPlateauing,
plateauStartIteration: plateauStart,
predictedConvergenceIteration: predictedIteration,
};
}
function calculateSlope(values: number[]): number {
if (values.length < 2) return 0;
const n = values.length;
const sumX = (n * (n - 1)) / 2;
const sumY = values.reduce((a, b) => a + b, 0);
const sumXY = values.reduce((sum, y, x) => sum + x * y, 0);
const sumXX = (n * (n - 1) * (2 * n - 1)) / 6;
return (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
}
function detectPlateau(history: QualityPoint[]): {
isPlateauing: boolean;
plateauStart?: number;
} {
if (history.length < 3) {
return { isPlateauing: false };
}
// Check last 3 iterations for plateau
const recent = history.slice(-3);
const scores = recent.map(p => p.qualityScore);
const variance = calculateVariance(scores);
// Plateau if variance is very low
if (variance < 0.01) {
return {
isPlateauing: true,
plateauStart: history.length - 3,
};
}
return { isPlateauing: false };
}
function calculateVariance(values: number[]): number {
const mean = values.reduce((a, b) => a + b, 0) / values.length;
const squaredDiffs = values.map(v => Math.pow(v - mean, 2));
return squaredDiffs.reduce((a, b) => a + b, 0) / values.length;
}
function predictConvergence(
history: QualityPoint[],
currentSlope: number
): number | undefined {
if (history.length < 2 || currentSlope <= 0) {
return undefined;
}
const currentScore = history[history.length - 1].qualityScore;
const targetScore = 0.85; // Acceptable threshold
if (currentScore >= targetScore) {
return history.length; // Already converged
}
const iterationsNeeded = (targetScore - currentScore) / currentSlope;
if (iterationsNeeded > 20) {
return undefined; // Too far to predict
}
return Math.ceil(history.length + iterationsNeeded);
}
Convergence Assessment
function assessConvergence(
tracker: ProgressTracker,
trend: TrendAnalysis
): ConvergenceAssessment {
const current = tracker.history[tracker.history.length - 1];
const goal = tracker.goal;
// Check if we've reached the goal
const meetsTarget = current.qualityScore >= goal.targetQuality;
const meetsAcceptable = current.qualityScore >= goal.acceptableQuality;
const noBlockingIssues = current.improvementsRemaining === 0;
const isConverged = meetsTarget && noBlockingIssues;
// Calculate convergence score
const convergenceScore = calculateGoalProximity(current, goal);
// Estimate iterations to goal
const estimatedIterations = trend.predictedConvergenceIteration
? trend.predictedConvergenceIteration - tracker.history.length
: Infinity;
// Assess if goal is achievable
const budgetRemaining = goal.maxIterations - tracker.history.length;
const goalAchievable =
!trend.isPlateauing &&
trend.direction !== 'declining' &&
(isConverged || estimatedIterations <= budgetRemaining);
// Calculate confidence in assessment
const confidence = calculateConfidence(tracker.history, trend);
return {
isConverged,
convergenceScore,
confidenceInConvergence: confidence,
estimatedIterationsToGoal: estimatedIterations,
goalAchievable,
};
}
function calculateConfidence(
history: QualityPoint[],
trend: TrendAnalysis
): number {
let confidence = 0.5; // Base confidence
// More history = more confidence
if (history.length >= 3) confidence += 0.1;
if (history.length >= 5) confidence += 0.1;
// Consistent improvement = more confidence
if (trend.direction === 'improving' && trend.acceleration >= 0) {
confidence += 0.15;
}
// Low variance = more confidence
const recentVariance = calculateVariance(
history.slice(-3).map(p => p.qualityScore)
);
if (recentVariance < 0.05) confidence += 0.1;
// Plateau reduces confidence in further improvement
if (trend.isPlateauing) confidence -= 0.2;
return Math.max(0, Math.min(1, confidence));
}
Stopping Recommendations
type ConvergenceRecommendation =
| { action: 'continue'; reason: string; priority: string }
| { action: 'accept'; reason: string; qualityLevel: string }
| { action: 'escalate'; reason: string; blockers: string[] }
| { action: 'abort'; reason: string };
function recommendAction(
tracker: ProgressTracker,
trend: TrendAnalysis,
convergence: ConvergenceAssessment
): ConvergenceRecommendation {
const current = tracker.history[tracker.history.length - 1];
const budgetRemaining = tracker.goal.maxIterations - tracker.history.length;
// Case 1: Goal achieved
if (convergence.isConverged) {
return {
action: 'accept',
reason: 'Target quality achieved with no blocking issues',
qualityLevel: 'target',
};
}
// Case 2: Acceptable quality, close to budget limit
if (
current.qualityScore >= tracker.goal.acceptableQuality &&
budgetRemaining <= 1
) {
return {
action: 'accept',
reason: 'Acceptable quality reached, iteration budget nearly exhausted',
qualityLevel: 'acceptable',
};
}
// Case 3: No budget remaining
if (budgetRemaining <= 0) {
if (current.qualityScore >= tracker.goal.acceptableQuality) {
return {
action: 'accept',
reason: 'Budget exhausted, quality is acceptable',
qualityLevel: 'acceptable',
};
}
return {
action: 'escalate',
reason: 'Budget exhausted without reaching acceptable quality',
blockers: extractBlockers(tracker),
};
}
// Case 4: Plateaued below acceptable
if (
trend.isPlateauing &&
current.qualityScore < tracker.goal.acceptableQuality
) {
return {
action: 'escalate',
reason: 'Quality plateaued below acceptable threshold',
blockers: extractBlockers(tracker),
};
}
// Case 5: Declining quality
if (trend.direction === 'declining' && tracker.history.length >= 3) {
return {
action: 'escalate',
reason: 'Quality declining over multiple iterations',
blockers: ['Iterations making things worse, not better'],
};
}
// Case 6: Goal not achievable within budget
if (!convergence.goalAchievable) {
return {
action: 'escalate',
reason: 'Target quality unlikely to be achieved within remaining budget',
blockers: extractBlockers(tracker),
};
}
// Case 7: Continue improving
return {
action: 'continue',
reason: 'Progress being made, goal achievable within budget',
priority: current.improvementsRemaining > 0 ? 'high' : 'medium',
};
}
function extractBlockers(tracker: ProgressTracker): string[] {
const current = tracker.history[tracker.history.length - 1];
const blockers: string[] = [];
if (current.qualityScore < tracker.goal.acceptableQuality) {
blockers.push(`Quality score ${(current.qualityScore * 100).toFixed(0)}% below acceptable ${(tracker.goal.acceptableQuality * 100).toFixed(0)}%`);
}
if (current.improvementsRemaining > 0) {
blockers.push(`${current.improvementsRemaining} critical/high improvements unresolved`);
}
if (current.validationScore < 1) {
blockers.push('Validation still failing');
}
return blockers;
}
Convergence Report
convergenceReport:
taskId: code-review-task
currentIteration: 4
analyzedAt: "2024-01-15T10:45:00Z"
goal:
targetQuality: 0.85
acceptableQuality: 0.70
maxIterations: 5
requiredImprovements:
- "Security analysis section"
- "Performance metrics"
qualityHistory:
- iteration: 1
qualityScore: 0.52
confidenceScore: 0.55
improvementsRemaining: 5
- iteration: 2
qualityScore: 0.58
confidenceScore: 0.62
improvementsRemaining: 4
- iteration: 3
qualityScore: 0.68
confidenceScore: 0.70
improvementsRemaining: 2
- iteration: 4
qualityScore: 0.75
confidenceScore: 0.73
improvementsRemaining: 1
trend:
direction: improving
slope: 0.077
acceleration: 0.02
isPlateauing: false
predictedConvergenceIteration: 5
convergence:
isConverged: false
convergenceScore: 0.88
confidenceInConvergence: 0.72
estimatedIterationsToGoal: 1
goalAchievable: true
recommendation:
action: continue
reason: "Progress being made, target quality likely achievable in next iteration"
priority: high
progressVisualization: |
Iteration Quality Target
1 ████░░░░ 52%
2 █████░░░ 58%
3 ██████░░ 68%
4 ███████░ 75% ← Current
5 (est) ████████ 85% ← Target
nextIterationFocus:
- "Resolve remaining high-priority improvement"
- "Improve confidence through better sourcing"
- "Verify all validation criteria pass"
Integration Points
- Input: Iteration results from
dag-iteration-detectoranddag-feedback-synthesizer - Output: Recommendations to
dag-dynamic-replanner - History: Stores patterns for
dag-pattern-learner - Metrics: Reports to
dag-performance-profiler
Best Practices
- Sufficient History: Wait for 3+ iterations before trend analysis
- Budget Awareness: Always consider remaining iterations
- Early Detection: Catch plateaus before wasting iterations
- Clear Thresholds: Define target and acceptable levels upfront
- Confidence Calibration: Trust predictions more with more data
Track progress. Detect plateaus. Know when to stop.
GitHub Repository
Related Skills
shift-right-testing
OtherThis skill enables testing in production using feature flags, canary deployments, and chaos engineering. It's designed for implementing production observability and progressive delivery strategies. Key capabilities include progressive rollouts, synthetic monitoring, and failure injection to build system resilience.
code-review-quality
OtherThis skill conducts automated code reviews focused on quality, testability, and maintainability, using specialized agents for security, performance, and coverage analysis. It provides prioritized, context-driven feedback for pull requests or when establishing review practices. Developers should use it to get actionable, structured reviews that emphasize bugs and maintainability over subjective style preferences.
dag-pattern-learner
OtherThis skill analyzes DAG execution history to identify successful workflow patterns and detect anti-patterns, providing optimization recommendations. Use it when prompted to "learn patterns" or "optimize based on history" to improve future DAG performance. It pairs with execution tracers and graph builders to apply learned insights.
dag-semantic-matcher
OtherThis skill matches natural language task descriptions to appropriate skills using semantic similarity, handling fuzzy matching and intent extraction. It is activated by phrases like "find skill" or "match task" to discover relevant capabilities from the skill registry. Use this for skill discovery, not for ranking results or catalog management.
