Class: Diogenes::Evaluation::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/diogenes/evaluation/session.rb,
sig/generated/diogenes/evaluation/session.rbs

Defined Under Namespace

Classes: Result

Constant Summary collapse

SEPARATOR =

: String

Returns:

  • (String)
("─" * 60).freeze

Instance Method Summary collapse

Constructor Details

#initialize(description:, out:, err:, **opts) ⇒ Session

: (description: String, out: IO, err: IO, **untyped) -> void

Parameters:

  • description: (String)
  • out: (IO)
  • err: (IO)
  • (Object)


15
16
17
18
19
20
21
22
# File 'lib/diogenes/evaluation/session.rb', line 15

def initialize(description:, out:, err:, **opts)
  @description = description
  @out = out
  @err = err
  @in = opts.fetch(:in, $stdin)
  @cwd = opts.fetch(:cwd, Dir.pwd) #: String
  @results = [] #: Array[untyped]
end

Instance Method Details

#ask_yes_no(question) ⇒ Boolean

: (String) -> bool

Parameters:

  • (String)

Returns:

  • (Boolean)


129
130
131
132
133
# File 'lib/diogenes/evaluation/session.rb', line 129

def ask_yes_no(question)
  @out.print "  #{question} "
  response = @in.gets&.strip&.downcase || ""
  response.empty? || response.start_with?("y")
end

#collect_failure_details(record) ⇒ void

This method returns an undefined value.

: (DecisionRecord) -> void

Parameters:



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/diogenes/evaluation/session.rb', line 101

def collect_failure_details(record)
  @out.puts
  @out.puts "  One or more gates failed. How should this be recorded?"
  @out.puts "    [1] REJECT — this feature should not use AI"
  @out.puts "    [2] PROCEED WITH CONDITIONS — proceeding with documented mitigations"
  @out.print "  Your choice (default: 1): "
  choice = @in.gets&.strip

  if choice == "2"
    record.verdict = "PROCEED WITH CONDITIONS"
    @out.print "  Describe the conditions or mitigations: "
    record.conditions = @in.gets&.strip || ""
  else
    record.verdict = "REJECT"
    @out.print "  Describe the recommended software alternative: "
    record.alternative = @in.gets&.strip || ""
  end
end

#detect_evaluatorString

: () -> String

Returns:

  • (String)


121
122
123
124
125
126
# File 'lib/diogenes/evaluation/session.rb', line 121

def detect_evaluator
  name = `git config user.name 2>/dev/null`.strip
  name.empty? ? ENV.fetch("USER", "Unknown") : name
rescue Errno::ENOENT
  ENV.fetch("USER", "Unknown")
end

This method returns an undefined value.

: () -> void



136
137
138
139
140
141
142
143
144
145
# File 'lib/diogenes/evaluation/session.rb', line 136

def print_final_summary
  if @results.all?(&:passed?)
    @out.puts "All #{@results.size} gates passed! ✓"
  else
    @out.puts "Evaluation complete."
  end
  @out.puts
  print_summary_table
  @out.puts
end

This method returns an undefined value.

: () -> void



50
51
52
53
54
# File 'lib/diogenes/evaluation/session.rb', line 50

def print_header
  @out.puts
  @out.puts "Evaluating: \"#{@description}\""
  @out.puts
end

This method returns an undefined value.

: () -> void



148
149
150
151
152
# File 'lib/diogenes/evaluation/session.rb', line 148

def print_partial_summary
  @out.puts
  @out.puts "Gates evaluated:"
  print_summary_table
end

This method returns an undefined value.

: () -> void



155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/diogenes/evaluation/session.rb', line 155

def print_summary_table
  Gates::ALL.each_with_index do |gate, index|
    result = @results[index]
    status = if result.nil?
      "(not evaluated)"
    elsif result.passed?
      "PASS"
    else
      "FAIL"
    end
    @out.puts "  Gate #{index + 1} — #{gate.name.ljust(22)} #{status}"
  end
end

#prompt_continue?Boolean

: () -> bool

Returns:

  • (Boolean)


80
81
82
# File 'lib/diogenes/evaluation/session.rb', line 80

def prompt_continue?
  ask_yes_no("Continue evaluating remaining gates? (Y/n)")
end

#prompt_decision_recordvoid

This method returns an undefined value.

: () -> void



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/diogenes/evaluation/session.rb', line 85

def prompt_decision_record
  return unless ask_yes_no("Generate a decision record?")

  record = DecisionRecord.new(
    description: @description,
    results: @results,
    evaluator: detect_evaluator
  )

  collect_failure_details(record) if @results.any?(&:failed?)

  path = record.write(cwd: @cwd)
  @out.puts "  Decision record written to #{path}"
end

#runInteger

: () -> Integer

Returns:

  • (Integer)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/diogenes/evaluation/session.rb', line 25

def run
  print_header

  Gates::ALL.each_with_index do |gate, index|
    run_gate(gate, index + 1)

    if @results.last.failed? && !prompt_continue?
      print_partial_summary
      return 1
    end
  end

  print_final_summary
  prompt_decision_record

  @results.all?(&:passed?) ? 0 : 1
rescue Interrupt
  @out.puts "\n\nEvaluation interrupted."
  print_partial_summary
  1
end

#run_gate(gate, number) ⇒ void

This method returns an undefined value.

: (Gate, Integer) -> void

Parameters:



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/diogenes/evaluation/session.rb', line 57

def run_gate(gate, number)
  @out.puts SEPARATOR
  @out.puts "Gate #{number} of #{Gates::ALL.size} — #{gate.name}"
  @out.puts "Principle: #{gate.principle}"
  @out.puts SEPARATOR
  @out.puts
  @out.puts wrap(gate.explanation, 70)
  @out.puts

  passed = ask_yes_no(gate.question)
  @results << Result.new(gate:, passed:)

  if passed
    @out.puts "  ✓ Gate #{number} — PASS"
  else
    @out.puts "  ✗ Gate #{number} — FAIL"
    @out.puts
    @out.puts "  #{gate.fail_message}"
  end
  @out.puts
end

#wrap(text, width) ⇒ String

: (String, Integer) -> String

Parameters:

  • (String)
  • (Integer)

Returns:

  • (String)


170
171
172
# File 'lib/diogenes/evaluation/session.rb', line 170

def wrap(text, width)
  text.gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n").strip
end