Back to Skills

dag-convergence-monitor

majiayu000
Updated Today
3 views
58
9
58
View on GitHub
Otherdagfeedbackconvergencemonitoringquality-trends

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 CommandRecommended
/plugin add https://github.com/majiayu000/claude-skill-registry
Git CloneAlternative
git clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/dag-convergence-monitor

Copy 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-detector and dag-feedback-synthesizer
  • Output: Recommendations to dag-dynamic-replanner
  • History: Stores patterns for dag-pattern-learner
  • Metrics: Reports to dag-performance-profiler

Best Practices

  1. Sufficient History: Wait for 3+ iterations before trend analysis
  2. Budget Awareness: Always consider remaining iterations
  3. Early Detection: Catch plateaus before wasting iterations
  4. Clear Thresholds: Define target and acceptable levels upfront
  5. Confidence Calibration: Trust predictions more with more data

Track progress. Detect plateaus. Know when to stop.

GitHub Repository

majiayu000/claude-skill-registry
Path: skills/dag-convergence-monitor

Related Skills

shift-right-testing

Other

This 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.

View skill

code-review-quality

Other

This 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.

View skill

dag-pattern-learner

Other

This 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.

View skill

dag-semantic-matcher

Other

This 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.

View skill