Module: PredictabilityEngine

Defined in:
lib/predictability_engine.rb,
lib/predictability_engine/cli.rb,
lib/predictability_engine/config.rb,
lib/predictability_engine/logger.rb,
lib/predictability_engine/report.rb,
lib/predictability_engine/version.rb,
lib/predictability_engine/duration.rb,
lib/predictability_engine/jira_auth.rb,
lib/predictability_engine/html_style.rb,
lib/predictability_engine/visualizer.rb,
lib/predictability_engine/agents/tools.rb,
lib/predictability_engine/data_manager.rb,
lib/predictability_engine/jira_workflow.rb,
lib/predictability_engine/setup_manager.rb,
lib/predictability_engine/data_generator.rb,
lib/predictability_engine/excel_exporter.rb,
lib/predictability_engine/html_templates.rb,
lib/predictability_engine/jira_auth/base.rb,
lib/predictability_engine/pdf_visualizer.rb,
lib/predictability_engine/calculators/cfd.rb,
lib/predictability_engine/jira_auth/basic.rb,
lib/predictability_engine/vega_visualizer.rb,
lib/predictability_engine/agents/assistant.rb,
lib/predictability_engine/data_sources/csv.rb,
lib/predictability_engine/jira_auth/bearer.rb,
lib/predictability_engine/jira_auth/cookie.rb,
lib/predictability_engine/models/work_item.rb,
lib/predictability_engine/report/constants.rb,
lib/predictability_engine/report_generator.rb,
lib/predictability_engine/calculators/aging.rb,
lib/predictability_engine/data_sources/base.rb,
lib/predictability_engine/data_sources/jira.rb,
lib/predictability_engine/jira_auth/mfa_api.rb,
lib/predictability_engine/raw_data_exporter.rb,
lib/predictability_engine/data_sources/excel.rb,
lib/predictability_engine/mermaid_visualizer.rb,
lib/predictability_engine/summary_visualizer.rb,
lib/predictability_engine/terminal_visualizer.rb,
lib/predictability_engine/data_sources/factory.rb,
lib/predictability_engine/jira_config_prompter.rb,
lib/predictability_engine/report/text_renderer.rb,
lib/predictability_engine/jira_auth/mfa_browser.rb,
lib/predictability_engine/calculators/cycle_time.rb,
lib/predictability_engine/calculators/throughput.rb,
lib/predictability_engine/data_sources/jira_yaml.rb,
lib/predictability_engine/report/image_generator.rb,
lib/predictability_engine/simulators/monte_carlo.rb,
lib/predictability_engine/pdf_visualizer/primitives.rb,
lib/predictability_engine/calculators/cfd_forecaster.rb,
lib/predictability_engine/summary_visualizer/helpers.rb,
lib/predictability_engine/vega_visualizer/cfd_charts.rb,
lib/predictability_engine/vega_visualizer/cfd_layout.rb,
lib/predictability_engine/summary_visualizer/renderer.rb,
lib/predictability_engine/vega_visualizer/basic_charts.rb,
lib/predictability_engine/vega_visualizer/tooltip_helpers.rb,
lib/predictability_engine/simulators/monte_carlo_validator.rb,
lib/predictability_engine/terminal_visualizer/cfd_renderer.rb,
lib/predictability_engine/vega_visualizer/aging_wip_visualizer.rb

Defined Under Namespace

Modules: Agents, Calculators, CliBase, DataGenerator, DataSources, Duration, ExcelExporter, JiraAuth, JiraConfigPrompter, MermaidVisualizer, Models, PdfVisualizer, RawDataExporter, ReportGenerator, Simulators, SummaryVisualizer, TerminalVisualizer, VegaVisualizer Classes: Cli, Config, DataManager, Error, JiraWorkflow, Report, SetupManager, TerminalFormatter, Visualizer, Viz

Constant Summary collapse

DEFAULT_PERCENTILES =
[50, 75, 85, 95, 98].freeze
VERSION =
'0.6.6'

Class Method Summary collapse

Class Method Details

.active_items(items) ⇒ Object



38
39
40
# File 'lib/predictability_engine.rb', line 38

def self.active_items(items)
  items.reject(&:completed?)
end

.completed_items(items) ⇒ Object



34
35
36
# File 'lib/predictability_engine.rb', line 34

def self.completed_items(items)
  items.select(&:completed?)
end

.cycle_time_percentile(items, percentile) ⇒ Object



46
47
48
# File 'lib/predictability_engine.rb', line 46

def self.cycle_time_percentile(items, percentile)
  Calculators::CycleTime.percentile(items, percentile)
end

.format_date(date) ⇒ Object



78
79
80
81
82
# File 'lib/predictability_engine.rb', line 78

def self.format_date(date)
  return nil unless date

  date.to_date.to_s
end

.format_datetime(time) ⇒ Object



96
97
98
99
100
# File 'lib/predictability_engine.rb', line 96

def self.format_datetime(time)
  return nil unless time

  time.to_time.strftime('%Y-%m-%d %H:%M')
end

.format_year_month(date) ⇒ Object



90
91
92
93
94
# File 'lib/predictability_engine.rb', line 90

def self.format_year_month(date)
  return nil unless date

  date.to_date.strftime('%Y-%m')
end

.format_year_week(date) ⇒ Object



84
85
86
87
88
# File 'lib/predictability_engine.rb', line 84

def self.format_year_week(date)
  return nil unless date

  date.to_date.strftime('%G-W%V')
end

.load_items(spec) ⇒ Object



57
58
59
60
61
# File 'lib/predictability_engine.rb', line 57

def self.load_items(spec, **)
  manager = DataManager.new
  manager.load(spec, **)
  manager.work_items
end

.loggerObject

Module-level logger named “PredictabilityEngine”. Memoized so that all call sites share the same instance (required for RSpec ‘receive` mocks, and avoids allocating a new object on every log call).



42
43
44
# File 'lib/predictability_engine/logger.rb', line 42

def self.logger
  @logger ||= SemanticLogger[self]
end

.mapped_percentiles(work_items, percentiles = DEFAULT_PERCENTILES) ⇒ Object



50
51
52
53
54
55
# File 'lib/predictability_engine.rb', line 50

def self.mapped_percentiles(work_items, percentiles = DEFAULT_PERCENTILES)
  percentiles.map do |p|
    val = cycle_time_percentile(work_items, p)
    { val: val, label: "#{p}% Percentile", p: p } if val
  end.compact
end

.run_and_print_report(file, format, options, items: nil, **extra) ⇒ Object



71
72
73
74
75
76
# File 'lib/predictability_engine.rb', line 71

def self.run_and_print_report(file, format, options, items: nil, **extra)
  output = extra.delete(:output)
  opts = options.to_h.symbolize_keys.merge(output: output)
  message = run_report(file, format, items: items, **opts, **extra)
  logger.info { message }
end

.run_report(file, format) ⇒ Object



63
64
65
# File 'lib/predictability_engine.rb', line 63

def self.run_report(file, format, **)
  ReportGenerator.run_report(file, format, **)
end

.sample_data_path(name = 'sample_data.csv') ⇒ Object

Raises:



111
112
113
114
115
116
# File 'lib/predictability_engine.rb', line 111

def self.sample_data_path(name = 'sample_data.csv')
  path = File.join(File.expand_path('..', __dir__), 'data', 'samples', name)
  raise Error, "Sample data not found: #{path}" unless File.exist?(path)

  path
end

.setup_logging(level: 'info', log_file: nil) ⇒ Object

Called from CliBase#initialize via –log-level / –log-file options. Removes only appenders previously added by this method (tracked in @_pe_appenders) so that external appenders — e.g. test StringIO captures —are never disturbed.



28
29
30
31
32
33
34
35
36
37
# File 'lib/predictability_engine/logger.rb', line 28

def self.setup_logging(level: 'info', log_file: nil)
  SemanticLogger.default_level = level.to_sym
  (@_pe_appenders || []).each { |a| SemanticLogger.remove_appender(a) }
  @_pe_appenders = []
  @_pe_appenders << SemanticLogger.add_appender(io: $stdout, formatter: TerminalFormatter.new)
  return unless log_file

  FileUtils.mkdir_p(File.dirname(log_file))
  @_pe_appenders << SemanticLogger.add_appender(file_name: log_file, formatter: :json)
end

.todayObject



42
43
44
# File 'lib/predictability_engine.rb', line 42

def self.today
  ENV['MOCK_TODAY'] ? Date.parse(ENV['MOCK_TODAY']) : Date.current
end

.warn_chart_failure(error, context:) ⇒ Object



102
103
104
# File 'lib/predictability_engine.rb', line 102

def self.warn_chart_failure(error, context:)
  logger.warn { "Chart image generation failed: #{error.message}. #{context}" }
end

.write_file(path, content) ⇒ Object



106
107
108
109
# File 'lib/predictability_engine.rb', line 106

def self.write_file(path, content)
  FileUtils.mkdir_p(File.dirname(path))
  File.write(path, content)
end

.write_report(input_file, format, content, output, type: :all) ⇒ Object



67
68
69
# File 'lib/predictability_engine.rb', line 67

def self.write_report(input_file, format, content, output, type: :all)
  ReportGenerator.write_report(input_file, format, content, output, type: type)
end