Class: Ast::Merge::PortableBenchmarkContract::Consumer

Inherits:
Object
  • Object
show all
Defined in:
lib/ast/merge/portable_benchmark_contract.rb,
sig/ast/merge.rbs

Overview

Parses, validates, and deterministically interprets a contract without executing its payloads. rubocop:disable Metrics/AbcSize, Metrics/ClassLength, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity -- Contract conformance keeps each envelope's validation together.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, contract_digest: nil) ⇒ Consumer

Returns a new instance of Consumer.

Parameters:

  • document (Hash[String, untyped])
  • contract_digest: (String, nil) (defaults to: nil)


40
41
42
43
# File 'lib/ast/merge/portable_benchmark_contract.rb', line 40

def initialize(document, contract_digest: nil)
  @document = document
  @contract_digest = contract_digest || Digest::SHA256.hexdigest(canonical_json(document))
end

Instance Attribute Details

#contract_digestString (readonly)

Returns the value of attribute contract_digest.

Returns:

  • (String)


27
28
29
# File 'lib/ast/merge/portable_benchmark_contract.rb', line 27

def contract_digest
  @contract_digest
end

#documentHash[String, untyped] (readonly)

Returns the value of attribute document.

Returns:

  • (Hash[String, untyped])


27
28
29
# File 'lib/ast/merge/portable_benchmark_contract.rb', line 27

def document
  @document
end

Class Method Details

.load_file(path) ⇒ Consumer

Parameters:

  • path (String, _ToPath)

Returns:



36
37
38
# File 'lib/ast/merge/portable_benchmark_contract.rb', line 36

def self.load_file(path)
  parse(File.binread(path))
end

.parse(source) ⇒ Consumer

Parameters:

  • source (String)

Returns:



29
30
31
32
33
34
# File 'lib/ast/merge/portable_benchmark_contract.rb', line 29

def self.parse(source)
  source = String(source)
  new(JSON.parse(source), contract_digest: Digest::SHA256.hexdigest(source)).tap(&:validate!)
rescue JSON::ParserError => e
  raise ValidationError, "invalid benchmark contract JSON: #{e.message}"
end

Instance Method Details

#canonical_summaryHash[String, untyped] Also known as: summary

Returns:

  • (Hash[String, untyped])


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
# File 'lib/ast/merge/portable_benchmark_contract.rb', line 56

def canonical_summary
  validate!
  cases = fetch_array(@document, 'cases', 'contract')
  results = fetch_array(@document, 'case_results', 'contract')
  adapters = adapter_records
  excluded = results.select { |result| QUALITY_EXCLUDED_OUTCOMES.include?(result['outcome']) }
  false_auto_merges = results.filter_map do |result|
    next unless result['outcome'] == 'false_auto_merge' && result['score_eligible']

    { 'id' => result.fetch('id'), 'severity' => result.dig('dimensions', 'safety', 'severity') }
  end

  {
    'schema' => @document.fetch('schema_version'),
    'counts' => {
      'adapters' => adapters.length,
      'cases' => cases.length,
      'results' => results.length,
      'selected_cases' => @document.dig('run_manifest', 'selection', 'selected_case_ids').length,
      'score_eligible_results' => results.count { |result| result['score_eligible'] },
      'quality_denominator_excluded_results' => excluded.length,
      'eligible_false_auto_merges' => false_auto_merges.length
    },
    'case_ids_by_operation' => grouped_case_ids(cases, 'operations', 'operation'),
    'case_ids_by_partition' => grouped_case_ids(cases, 'partitions', 'partition'),
    'score_eligible_result_ids' => results.filter_map do |result|
      result['id'] if result['score_eligible']
    end.sort,
    'quality_denominator_excluded_result_ids' => excluded.map { |result| result.fetch('id') }.sort,
    'false_auto_merges' => false_auto_merges.sort_by { |entry| entry.fetch('id') },
    'safety_gate' => {
      'status' => false_auto_merges.empty? ? 'pass' : 'fail',
      'eligible_false_auto_merge_count' => false_auto_merges.length,
      'non_compensable' => true
    },
    'selection_reason_categories' => @document.dig('run_manifest', 'selection', 'explanation').keys.sort,
    'contract_digest' => @contract_digest
  }
end

#validate!Consumer

Returns:



45
46
47
48
49
50
51
52
53
54
# File 'lib/ast/merge/portable_benchmark_contract.rb', line 45

def validate!
  object!(@document, 'contract')
  validate_schema_versions!
  validate_enum_contract!
  validate_cases!
  validate_run!
  validate_results!
  validate_report!
  self
end