Class: Aidp::Harness::OutputFilter

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/harness/output_filter.rb

Overview

Filters test and linter output to reduce token consumption

Supports two filtering approaches:

  1. AI-generated FilterDefinitions (preferred) - created once during config, applied deterministically at runtime for ANY tool

  2. Built-in RSpec strategy (fallback) - for backward compatibility

Examples:

Using AI-generated filter

definition = FilterDefinition.from_hash(config[:filter_definitions][:pytest])
filter = OutputFilter.new(mode: :failures_only, filter_definition: definition)
filtered = filter.filter(output)

See Also:

Constant Summary collapse

MODES =

Output modes

{
  full: :full,                   # No filtering (default for first run)
  failures_only: :failures_only, # Only failure information
  minimal: :minimal              # Minimal failure info + summary
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = {}, filter_definition: nil) ⇒ OutputFilter

Returns a new instance of OutputFilter.

Parameters:

  • config (OutputFilterConfig, Hash) (defaults to: {})

    Configuration options

  • filter_definition (FilterDefinition, nil) (defaults to: nil)

    AI-generated filter patterns

Options Hash (config):

  • :mode (Symbol)

    Output mode (:full, :failures_only, :minimal)

  • :include_context (Boolean)

    Include surrounding lines

  • :context_lines (Integer)

    Number of context lines

  • :max_lines (Integer)

    Maximum output lines



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/aidp/harness/output_filter.rb', line 35

def initialize(config = {}, filter_definition: nil)
  @config = normalize_config(config)
  @mode = @config.mode
  @include_context = @config.include_context
  @context_lines = @config.context_lines
  @max_lines = @config.max_lines
  @filter_definition = filter_definition

  Aidp.log_debug("output_filter", "initialized",
    mode: @mode,
    include_context: @include_context,
    max_lines: @max_lines,
    has_definition: !@filter_definition.nil?)
rescue NameError
  # Logging infrastructure not available in some tests
end

Instance Attribute Details

#configObject (readonly)

Accessors for strategy use



101
102
103
# File 'lib/aidp/harness/output_filter.rb', line 101

def config
  @config
end

#context_linesObject (readonly)

Accessors for strategy use



101
102
103
# File 'lib/aidp/harness/output_filter.rb', line 101

def context_lines
  @context_lines
end

#filter_definitionObject (readonly)

Accessors for strategy use



101
102
103
# File 'lib/aidp/harness/output_filter.rb', line 101

def filter_definition
  @filter_definition
end

#include_contextObject (readonly)

Accessors for strategy use



101
102
103
# File 'lib/aidp/harness/output_filter.rb', line 101

def include_context
  @include_context
end

#max_linesObject (readonly)

Accessors for strategy use



101
102
103
# File 'lib/aidp/harness/output_filter.rb', line 101

def max_lines
  @max_lines
end

#modeObject (readonly)

Accessors for strategy use



101
102
103
# File 'lib/aidp/harness/output_filter.rb', line 101

def mode
  @mode
end

Instance Method Details

#filter(output, framework: :unknown) ⇒ String

Filter output based on framework and mode

Parameters:

  • output (String)

    Raw output

  • framework (Symbol) (defaults to: :unknown)

    Framework identifier (:rspec, :minitest, :jest, :pytest, :unknown)

Returns:

  • (String)

    Filtered output



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/aidp/harness/output_filter.rb', line 56

def filter(output, framework: :unknown)
  return output if @mode == :full
  return "" if output.nil? || output.empty?

  Aidp.log_debug("output_filter", "filtering_start",
    framework: framework,
    mode: @mode,
    input_lines: output.lines.count)

  strategy = strategy_for_framework(framework)
  filtered = strategy.filter(output, self)

  truncated = truncate_if_needed(filtered)

  Aidp.log_debug("output_filter", "filtering_complete",
    framework: framework,
    output_lines: truncated.lines.count,
    reduction: reduction_stats(output, truncated))

  truncated
rescue NameError
  # Logging infrastructure not available
  return output if @mode == :full
  return "" if output.nil? || output.empty?

  strategy = strategy_for_framework(framework)
  filtered = strategy.filter(output, self)
  truncate_if_needed(filtered)
rescue => e
  # External failure - graceful degradation
  begin
    Aidp.log_error("output_filter", "filtering_failed",
      framework: framework,
      mode: @mode,
      error: e.message,
      error_class: e.class.name)
  rescue NameError
    # Logging not available
  end

  # Return original output as fallback
  output
end