Class: Woods::Operator::ErrorEscalator

Inherits:
Object
  • Object
show all
Defined in:
lib/woods/operator/error_escalator.rb

Overview

Classifies pipeline errors by severity and suggests remediation.

Examples:

escalator = ErrorEscalator.new
result = escalator.classify(Timeout::Error.new("connection timed out"))
result[:severity]     # => :transient
result[:remediation]  # => "Retry after a short delay"

Constant Summary collapse

TRANSIENT_PATTERNS =
[
  { class_pattern: /Timeout|ETIMEDOUT/, category: 'timeout', remediation: 'Retry after a short delay' },
  { class_pattern: /Net::/, category: 'network', remediation: 'Check network connectivity and retry' },
  { class_pattern: /RateLimited|429/, category: 'rate_limit',
    remediation: 'Back off and retry with exponential delay' },
  { class_pattern: /CircuitOpenError/, category: 'circuit_open',
    remediation: 'Wait for circuit breaker reset timeout' },
  { class_pattern: /ConnectionPool|Busy/, category: 'resource_contention',
    remediation: 'Wait for resources to free up' }
].freeze
PERMANENT_PATTERNS =
[
  { class_pattern: /NameError|NoMethodError/, category: 'code_error',
    remediation: 'Fix the code error and re-extract' },
  { class_pattern: /Errno::ENOENT|FileNotFoundError/, category: 'missing_file',
    remediation: 'Verify file paths and re-run extraction' },
  { class_pattern: /JSON::ParserError/, category: 'corrupt_data',
    remediation: 'Clean index and re-extract' },
  { class_pattern: /ConfigurationError/, category: 'configuration',
    remediation: 'Review Woods configuration' },
  { class_pattern: /ExtractionError/, category: 'extraction_failure',
    remediation: 'Check extraction logs for specific failure details' }
].freeze

Instance Method Summary collapse

Instance Method Details

#classify(error, class_name: nil) ⇒ Hash

Classify an error by severity and suggest remediation.

Most patterns key on the error's class name, so a caller that only has the class name as a string (e.g. the pipeline_diagnose MCP tool, which receives error_class over the wire and can't reconstruct the real exception class) must pass class_name: — otherwise the synthesized StandardError makes every class-keyed pattern miss and the error falls through to :unknown.

Parameters:

  • error (StandardError)

    The error to classify

  • class_name (String, nil) (defaults to: nil)

    Override for the class name used in pattern matching and reported as :error_class (defaults to error.class.name)

Returns:

  • (Hash)

    :severity (:transient or :permanent), :category, :remediation, :error_class, :message



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/woods/operator/error_escalator.rb', line 52

def classify(error, class_name: nil)
  resolved_class = class_name || error.class.name
  error_string = "#{resolved_class} #{error.message}"

  match = find_match(error_string, TRANSIENT_PATTERNS, :transient) ||
          find_match(error_string, PERMANENT_PATTERNS, :permanent)

  if match
    match.merge(error_class: resolved_class, message: error.message)
  else
    {
      severity: :unknown,
      category: 'unclassified',
      remediation: 'Investigate error details and check logs',
      error_class: resolved_class,
      message: error.message
    }
  end
end