verdict_rules 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c6ebe08f124cc88d8cdcd68dcbf4335c6aae0c714d02dc03a2dd6610b2ba8eb0
4
+ data.tar.gz: 191c1ec6daf71053d0c24d212972d1bb1be45a7625e136f4f6fa2fe50b350597
5
+ SHA512:
6
+ metadata.gz: 457d29778fd20e42da7fa74db1af6de5678250b031cf77b8fc00ae31e86c50fbf1df5faa0cdc424aa013931f8042e7f4a68e5d0597c0ee47b48e190cc63e8443
7
+ data.tar.gz: 4d15e8bc27ec6977fc8b75ed7c9bb9a328d9c5d502ccaf560500ddf85620691a87ff28d51dcc5c74c54283fcc128e55ce5c05766bd011fa605b49fcc4ca3a13e
data/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-03-23
11
+
12
+ ### Added
13
+ - Initial release
14
+ - Core rule engine with context management
15
+ - Priority-based rule resolution
16
+ - Explainable results with Result object
17
+ - Expressive DSL for rule definition
18
+ - Named rules for better debugging and logging
19
+ - Immutable context for thread safety
20
+ - 100% test coverage
21
+ - Comprehensive examples
22
+ - Full documentation in Portuguese
23
+
24
+ ### Features
25
+ - `VerdictRules::Engine` - Main engine for rule evaluation
26
+ - `VerdictRules::Rule` - Individual rule with condition, action, and priority
27
+ - `VerdictRules::Result` - Rich result object explaining outcomes
28
+ - `VerdictRules::RuleBuilder` - DSL builder for clean syntax
29
+ - Support for complex nested contexts
30
+ - Priority system with stable sort
31
+ - Method chaining support
32
+
33
+ [Unreleased]: https://github.com/tibas-ce/verdict_rules/compare/v0.1.0...HEAD
34
+ [0.1.0]: https://github.com/tibas-ce/verdict_rules/releases/tag/v0.1.0
data/README.md ADDED
@@ -0,0 +1,249 @@
1
+ <div align="center">
2
+
3
+ # ⚖️ VerdictRules
4
+
5
+ ### Rule engine para Ruby com prioridades explícitas, resultados rastreáveis e DSL expressiva.
6
+
7
+ Defina regras de negócio complexas de forma clara, debuggável e pronta para produção.
8
+
9
+ [![CI](https://github.com/tibas-ce/verdict_rules/workflows/CI/badge.svg)](https://github.com/tibas-ce/verdict_rules/actions)
10
+ [![Gem Version](https://img.shields.io/badge/status-not_published-lightgrey.svg)](https://rubygems.org/gems/verdict_rules)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
12
+
13
+ [Recursos](#-recursos) •
14
+ [Instalação](#-instalação) •
15
+ [Início Rápido](#-início-rápido) •
16
+ [API](#-api) •
17
+ [Debugging e Observabilidade](#-debugging-e-observabilidade) •
18
+ [Exemplos](#-exemplos)
19
+
20
+ </div>
21
+
22
+ ---
23
+
24
+ ## 🎯 O que é VerdictRules?
25
+
26
+ **VerdictRules** é uma gem Ruby leve e sem dependências que permite definir regras de negócio de forma declarativa com nome, prioridades explícitas e resultados explicáveis.
27
+
28
+ Perfeita para:
29
+ - 🏦 **Sistemas financeiros**: Aprovação de crédito, detecção de fraude
30
+ - 🛒 **E-commerce**: Regras de preço, lógica de descontos
31
+ - 🔐 **Autorização**: Controle de acesso, sistemas de permissão
32
+ - ✅ **Validação**: Lógica condicional complexa
33
+ - 🎮 **Lógica de jogos**: Sistemas de pontuação, conquistas
34
+
35
+ ---
36
+
37
+ ## ✨ Recursos
38
+
39
+ | Recurso | Descrição |
40
+ |---------|-----------|
41
+ | 🎯 **Sistema de Prioridades** | Resolve conflitos quando múltiplas regras são verdadeiras |
42
+ | 🏷️ **Regras Nomeadas** | Identifique exatamente qual regra foi aplicada |
43
+ | 📊 **Resultados Explicáveis** | Saiba qual regra foi aplicada e por quê |
44
+ | ✨ **DSL Expressiva** | Sintaxe limpa e legível |
45
+ | 🔒 **Contexto Imutável** | Comportamento thread-safe e previsível |
46
+ | 🧪 **100% de Cobertura** | Testado e confiável |
47
+ | 📦 **Zero Dependências** | Leve e rápida |
48
+ | 🚀 **Design pronto para produção** | Arquitetura preparada para uso real |
49
+
50
+ ---
51
+
52
+ ## 📦 Instalação
53
+
54
+ Adicione esta linha ao Gemfile da sua aplicação:
55
+ ```ruby
56
+ gem 'verdict_rules'
57
+ ```
58
+
59
+ E então execute:
60
+ ```bash
61
+ bundle install
62
+ ```
63
+
64
+ Ou instale você mesmo:
65
+ ```bash
66
+ gem install verdict_rules
67
+ ```
68
+
69
+ ---
70
+
71
+ ## 🚀 Início Rápido
72
+
73
+ ### Exemplo Básico
74
+ ```ruby
75
+ require "verdict_rules"
76
+
77
+ context = { age: 25, verified: true }
78
+
79
+ engine = VerdictRules::Engine.new(context)
80
+
81
+ engine.rules do
82
+ rule :verified_user, priority: 10 do
83
+ when_condition { |ctx| ctx[:verified] }
84
+ then_action :approve_verified
85
+ end
86
+
87
+ rule :adult_user, priority: 1 do
88
+ when_condition { |ctx| ctx[:age] >= 18 }
89
+ then_action :approve_adult
90
+ end
91
+ end
92
+
93
+ result = engine.evaluate
94
+
95
+ result.value # => :approve_verified
96
+ result.matched_rule.name # => :verified_user
97
+ ```
98
+
99
+ ---
100
+
101
+ ### Problema que resolve
102
+
103
+ Sem prioridades e rastreabilidade:
104
+
105
+ - decisões imprevisíveis ❌
106
+ - difícil entender por que algo foi aprovado/rejeitado ❌
107
+ - debugging lento e custoso ❌
108
+
109
+ Com VerdictRules:
110
+
111
+ - decisão previsível ✅
112
+ - regra identificável ✅
113
+ - lógica centralizada ✅
114
+
115
+ ---
116
+ ### Exemplo Real: Produção
117
+ ```ruby
118
+ engine.rules do
119
+ rule :vip_customer, priority: 100 do
120
+ when_condition { |ctx| ctx[:vip_customer] }
121
+ then_action({ status: :approved, limit: 50000 })
122
+ end
123
+
124
+ rule :income_not_verified, priority: 10 do
125
+ when_condition { |ctx| !ctx[:verified_income] }
126
+ then_action({ status: :manual_review })
127
+ end
128
+
129
+ rule :good_credit, priority: 1 do
130
+ when_condition { |ctx| ctx[:credit_score] >= 700 }
131
+ then_action({ status: :approved })
132
+ end
133
+ end
134
+
135
+ result = engine.evaluate
136
+
137
+ result.to_h
138
+ # => {
139
+ # value: { status: :manual_review },
140
+ # matched: true,
141
+ # matched_rule: { name: :income_not_verified, priority: 10, ... }
142
+ # }
143
+ ```
144
+
145
+ ---
146
+
147
+ ## 🔍 Debugging e Observabilidade
148
+ Projetado para sistemas onde decisões precisam ser auditáveis e explicáveis.
149
+
150
+ ```ruby
151
+ result = engine.evaluate
152
+
153
+ result.matched_rule.name
154
+ # => :income_not_verified
155
+
156
+ result.matched_rule.priority
157
+ # => 10
158
+ ```
159
+
160
+ ### 📊 Logging estruturado
161
+
162
+ ```ruby
163
+ log = {
164
+ event: "rule_evaluation",
165
+ result: result.value,
166
+ matched: result.matched?,
167
+ rule: result.matched_rule&.to_h
168
+ }
169
+
170
+ puts JSON.pretty_generate(log)
171
+ ```
172
+
173
+ ### Ideal para cenários como:
174
+
175
+ - auditoria
176
+ - debugging em produção
177
+ - sistemas financeiros / críticos
178
+
179
+ ---
180
+
181
+ ## 🔧 API
182
+
183
+ ```ruby
184
+ engine.rule(:name, priority: 10) do
185
+ when_condition { |ctx| ... }
186
+ then_action :result
187
+ end
188
+
189
+ engine.rules do
190
+ rule(:a, priority: 10) { ... }
191
+ rule(:b, priority: 5) { ... }
192
+ end
193
+
194
+ engine.evaluate
195
+ ```
196
+
197
+ ---
198
+
199
+ ## 💡 Exemplos
200
+
201
+ Confira o diretório [`examples/`](examples/) para exemplos completos e funcionais:
202
+
203
+ - **[Uso Básico](examples/basic_usage.rb)** - Regras simples sem DSL
204
+ - **[Sistema de Prioridades](examples/priority_and_exceptions.rb)** - Aprovação de crédito com prioridades
205
+ - **[DSL Básica](examples/dsl_basic.rb)** - DSL vs API tradicional
206
+ - **[DSL no Mundo Real](examples/dsl_real_word.rb)** - Sistema de aprovação de compras
207
+ - **[Debugging com regras nomeadas](examples/named_rules_debugging.rb)** - Investigando decisões e logs estruturados
208
+
209
+ Execute-os:
210
+ ```bash
211
+ ruby examples/basic_usage.rb
212
+ ```
213
+
214
+ ---
215
+
216
+ ## 📊 Princípios de Design
217
+
218
+ VerdictRules segue estes princípios:
219
+
220
+ - ✅ **Explícito sobre Implícito** - Sem mágica, comportamento claro
221
+ - ✅ **Simples sobre Complexo** - Fácil de entender e debugar
222
+ - ✅ **Testável** - Cada componente tem testes unitários
223
+ - ✅ **Imutável** - Contexto não pode ser modificado
224
+ - ✅ **Explicável** - Resultados dizem por que aconteceram
225
+ - ✅ **Componível** - Misture DSL e API tradicional livremente
226
+
227
+ ---
228
+
229
+ ## 📄 Licença
230
+
231
+ Este projeto está licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para detalhes.
232
+
233
+ ---
234
+
235
+ ## 🙏 Construído usando
236
+
237
+ - Ruby
238
+ - RSpec
239
+ - SimpleCov
240
+
241
+ ---
242
+
243
+ <div align="center">
244
+
245
+ **[⬆ voltar ao topo](#️-verdictrules)**
246
+
247
+ Feito por [Tibério dos Santos Ferreira](https://github.com/tibas-ce)
248
+
249
+ </div>
@@ -0,0 +1,111 @@
1
+ # Engine é responsável por:
2
+ # - armazenar o contexto de avaliação
3
+ # - gerenciar a lista de regras
4
+ # - avaliar as regras em ordem e retornar a primeira action válida
5
+ # O contexto é fornecido na inicialização e pertence à Engine.
6
+
7
+ module VerdictRules
8
+ class Engine
9
+ attr_reader :context, :rules
10
+
11
+ def initialize(context = {})
12
+ @context = deep_freeze(context.dup)
13
+ @rules = []
14
+ end
15
+
16
+ # Adiciona uma regra à engine
17
+ # Regras são automaticamente ordenadas por prioridade (maior primeiro)
18
+ # Em caso de empate, ordem de inserção é mantida (stable sort)
19
+ # Retorna self para permitir chaining
20
+ def add_rule(rule)
21
+ @rules << rule
22
+ sort_rules!
23
+ self
24
+ end
25
+
26
+ # DSL: Define uma única regra usando bloco
27
+ # Formas suportadas:
28
+ # rule(priority: 10) { ... }
29
+ # rule(:name, priority: 10) { ... }
30
+ # rule(:name) { ... }
31
+ #
32
+ # Parâmetros:
33
+ # - name: identificador opcional da regra
34
+ # - priority: ordem de avaliação (maior primeiro)
35
+ #
36
+ # O bloco é executado no contexto de RuleBuilder, permitindo:
37
+ # when_condition { |ctx| ... }
38
+ # then_action :value
39
+ # Retorna self para permitir chaining
40
+ def rule(name = nil, priority: 0, &block)
41
+ raise ArgumentError, "block required" unless block_given?
42
+
43
+ builder = RuleBuilder.new(name: name, priority: priority)
44
+ builder.instance_eval(&block)
45
+ add_rule(builder.build)
46
+
47
+ self
48
+ end
49
+
50
+ # DSL: Define múltiplas regras em um bloco
51
+ # Executa o bloco no contexto da Engine, permitindo chamadas a `rule`
52
+ # Exemplo:
53
+ # engine.rules do
54
+ # rule(:check_age, priority: 10) { ... }
55
+ # rule(:check_verified, priority: 5) { ... }
56
+ # end
57
+ #
58
+ # Retorna self para permitir chaining
59
+ def rules(&block)
60
+ return @rules unless block_given?
61
+
62
+ instance_eval(&block)
63
+ self
64
+ end
65
+
66
+ # Avalia as regras utilizando o contexto interno da Engine.
67
+ # Regras são avaliadas em ordem de prioridade (maior primeiro)
68
+ # Decisão de design:
69
+ # - O contexto é definido na inicialização da Engine
70
+ # - O método `evaluate` não recebe argumentos
71
+ # - Cada regra recebe o contexto da Engine durante a avaliação
72
+ # Retorna um Result contendo:
73
+ # - value: a action da primeira regra que bater (ou nil)
74
+ # - matched_rule: a regra que bateu (ou nil)
75
+ # Isso mantém a API simples e evita múltiplas formas de fornecer contexto.
76
+ def evaluate
77
+ rules.each do |rule|
78
+ action = rule.evaluate(context)
79
+
80
+ unless action.nil?
81
+ return Result.new(value: action, matched_rule: rule)
82
+ end
83
+ end
84
+
85
+ # Nenhuma regra bateu
86
+ Result.new(value: nil, matched_rule: nil)
87
+ end
88
+
89
+ private
90
+
91
+ # Congela recursivamente hashes e arrays para garantir a imutabilidade do contexto após a inicialização
92
+ def deep_freeze(object)
93
+ case object
94
+ when Hash
95
+ object.each { |key, value| deep_freeze(value) }
96
+ object.freeze
97
+ when Array
98
+ object.each { |value| deep_freeze(value) }
99
+ object.freeze
100
+ else
101
+ object.freeze
102
+ end
103
+ end
104
+
105
+ # Ordena regras por prioridade (maior primeiro)
106
+ # Em caso de empate, preserva a ordem de inserção para garantir previsibilidade na avaliação.
107
+ def sort_rules!
108
+ @rules = @rules.sort_by.with_index { |rule, index| [-rule.priority, index] }
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,43 @@
1
+ module VerdictRules
2
+ # Representa o resultado da avaliação de uma Rule Engine. Encapsula o valor retornado e a regra que foi satisfeita (se houver)
3
+ class Result
4
+ attr_reader :value, :matched_rule
5
+
6
+ def initialize(value:, matched_rule:)
7
+ @value = value
8
+ @matched_rule = matched_rule
9
+ end
10
+
11
+ # Indica se alguma regra foi satisfeita
12
+ def matched?
13
+ !matched_rule.nil?
14
+ end
15
+
16
+ # Retorna representação em hash do resultado da avaliação
17
+ def to_h
18
+ {
19
+ value: value,
20
+ matched: matched?,
21
+ matched_rule: matched_rule
22
+ }
23
+ end
24
+
25
+ # Representação legível para debugging
26
+ def inspect
27
+ if matched?
28
+ "#<VerdictRules::Result value=#{value.inspect} matched=true rule=#{matched_rule.object_id}>"
29
+ else
30
+ "#<VerdictRules::Result value=#{value.inspect} matched=false>"
31
+ end
32
+ end
33
+
34
+ # Define igualdade semâtica entre dois Results
35
+ def ==(other)
36
+ return false unless other.is_a?(Result)
37
+
38
+ value == other.value && matched_rule == other.matched_rule
39
+ end
40
+
41
+ alias eql? ==
42
+ end
43
+ end
@@ -0,0 +1,80 @@
1
+ module VerdictRules
2
+ # Representa uma regra simples composta por:
3
+ # - name: identificador opcional da regra (útil para debug e logging)
4
+ # - uma condition (Proc que recebe o contexto e retorna true/false)
5
+ # - uma action (valor retornado quando a condição é satisfeita)
6
+ # - priority: número usado para ordenar regras (quanto maior, maior prioridade)
7
+ class Rule
8
+ attr_reader :name, :condition, :action, :priority
9
+
10
+ def initialize(name: nil, condition:, action:, priority: 0)
11
+ validate_arguments!(name, condition, action, priority)
12
+
13
+ @name = normalize_name(name)
14
+ @condition = condition
15
+ @action = action
16
+ @priority = priority
17
+ end
18
+
19
+ # Avalia a regra contra um contexto
20
+ # Retorna a action se a condition for true, nil caso contrário
21
+ def evaluate(context)
22
+ return action if matches?(context)
23
+ nil
24
+ end
25
+
26
+ # Verifica se a condição é satisfeita pelo contexto
27
+ def matches?(context)
28
+ condition.call(context)
29
+ end
30
+
31
+ # Representação em hash (útil para logging e serialização)
32
+ def to_h
33
+ {
34
+ name: name,
35
+ priority: priority,
36
+ action: action
37
+ }
38
+ end
39
+
40
+ # Representação legível para debugging
41
+ def inspect
42
+ if name
43
+ "#<VerdictRules::Rule name=#{name.inspect} priority=#{priority} action=#{action.inspect}>"
44
+ else
45
+ "#<VerdictRules::Rule priority=#{priority} action=#{action.inspect}>"
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ # Valida os argumentos da regra.
52
+ # Regras de design:
53
+ # - condition deve ser um Proc
54
+ # - action é obrigatória
55
+ # - priority deve ser numérica (pode ser negativa)
56
+ def validate_arguments!(name, condition, action, priority)
57
+ validate_name!(name) unless name.nil?
58
+ raise ArgumentError, "condition" if condition.nil?
59
+ raise ArgumentError, "action" if action.nil?
60
+ raise ArgumentError, "condition must be a Proc" unless condition.is_a?(Proc)
61
+ raise ArgumentError, "priority must be a number" unless priority.is_a?(Numeric)
62
+ end
63
+
64
+ def validate_name!(name)
65
+ unless name.is_a?(Symbol) || name.is_a?(String)
66
+ raise ArgumentError, "name must be a symbol or string"
67
+ end
68
+
69
+ if name.is_a?(String) && name.strip.empty?
70
+ raise ArgumentError, "name cannot be empty"
71
+ end
72
+ end
73
+
74
+ def normalize_name(name)
75
+ return nil if name.nil?
76
+ name = name.strip if name.is_a?(String)
77
+ name.to_sym
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,51 @@
1
+ module VerdictRules
2
+ class RuleBuilder
3
+ # Builder responsável por construir instâncias de Rule a partir da DSL
4
+ # Encapsula validações e evita que a Engine lide com estado parcial
5
+ # Usado internamente pelo Engine#rule e Engine#rules
6
+ # name: identificador opcional da regra
7
+ # priority: define a ordem de avaliação (maior primeiro)
8
+ def initialize(name: nil, priority: 0)
9
+ @name = name
10
+ @priority = priority
11
+ @condition = nil
12
+ @action = nil
13
+ end
14
+
15
+ # Define a condição da regra
16
+ # O bloco a ser chamado posteriormente com o contexto da Engine
17
+ # Exige bloco para garantir previsibilidade do DSL
18
+ def when_condition(&block)
19
+ raise ArgumentError, "block required for when_condition" unless block_given?
20
+
21
+ @condition = block
22
+ end
23
+
24
+ # Define a ação executada quando a condição é satisfeita
25
+ # Aceita qualquer valor (symbol, string, hash, etc)
26
+ def then_action(value)
27
+ @action = value
28
+ end
29
+
30
+ # Constrói e retorna uma instância de Rule
31
+ # Garante que a DSL foi definida corretamente antes da criação
32
+ # Falha cedo caso condition ou action estejam ausentes
33
+ def build
34
+ validate!
35
+
36
+ Rule.new(
37
+ name: @name,
38
+ condition: @condition,
39
+ action: @action,
40
+ priority: @priority
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ def validate!
47
+ raise ArgumentError, "condition is required (use when_condition)" if @condition.nil?
48
+ raise ArgumentError, "action is required (use then_action)" if @action.nil?
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VerdictRules
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "verdict_rules/version"
4
+ require_relative "verdict_rules/result"
5
+ require_relative "verdict_rules/rule"
6
+ require_relative "verdict_rules/rule_builder"
7
+ require_relative "verdict_rules/engine"
8
+
9
+ module VerdictRules
10
+ class Error < StandardError; end
11
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: verdict_rules
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tibério dos Santos Ferreira
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rspec
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '3.0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: simplecov
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.22'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.22'
40
+ description: A gem to define and evaluate business rules with priorities and explainable
41
+ results.
42
+ email:
43
+ - tiberio.ferreiracs@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - CHANGELOG.md
49
+ - README.md
50
+ - lib/verdict_rules.rb
51
+ - lib/verdict_rules/engine.rb
52
+ - lib/verdict_rules/result.rb
53
+ - lib/verdict_rules/rule.rb
54
+ - lib/verdict_rules/rule_builder.rb
55
+ - lib/verdict_rules/version.rb
56
+ homepage: https://github.com/tibas-ce/verdict_rules
57
+ licenses:
58
+ - MIT
59
+ metadata:
60
+ homepage_uri: https://github.com/tibas-ce/verdict_rules
61
+ source_code_uri: https://github.com/tibas-ce/verdict_rules
62
+ changelog_uri: https://github.com/tibas-ce/verdict_rules/blob/main/CHANGELOG.md
63
+ bug_tracker_uri: https://github.com/tibas-ce/verdict_rules/issues
64
+ rubygems_mfa_required: 'true'
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.0.0
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.6.9
80
+ specification_version: 4
81
+ summary: A Ruby gem for defining and evaluating business rules with priorities.
82
+ test_files: []