rhales 0.3.0 → 0.5.3
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 +4 -4
- data/.github/renovate.json5 +52 -0
- data/.github/workflows/ci.yml +123 -0
- data/.github/workflows/claude-code-review.yml +69 -0
- data/.github/workflows/claude.yml +49 -0
- data/.github/workflows/code-smells.yml +146 -0
- data/.github/workflows/ruby-lint.yml +78 -0
- data/.github/workflows/yardoc.yml +126 -0
- data/.gitignore +55 -0
- data/.pr_agent.toml +63 -0
- data/.pre-commit-config.yaml +89 -0
- data/.prettierignore +8 -0
- data/.prettierrc +38 -0
- data/.reek.yml +98 -0
- data/.rubocop.yml +428 -0
- data/.serena/.gitignore +3 -0
- data/.yardopts +56 -0
- data/CHANGELOG.md +44 -0
- data/CLAUDE.md +1 -2
- data/Gemfile +29 -0
- data/Gemfile.lock +189 -0
- data/README.md +706 -589
- data/Rakefile +46 -0
- data/debug_context.rb +25 -0
- data/demo/rhales-roda-demo/.gitignore +7 -0
- data/demo/rhales-roda-demo/Gemfile +32 -0
- data/demo/rhales-roda-demo/Gemfile.lock +151 -0
- data/demo/rhales-roda-demo/MAIL.md +405 -0
- data/demo/rhales-roda-demo/README.md +376 -0
- data/demo/rhales-roda-demo/RODA-TEMPLATE-ENGINES.md +192 -0
- data/demo/rhales-roda-demo/Rakefile +49 -0
- data/demo/rhales-roda-demo/app.rb +325 -0
- data/demo/rhales-roda-demo/bin/rackup +26 -0
- data/demo/rhales-roda-demo/config.ru +13 -0
- data/demo/rhales-roda-demo/db/migrate/001_create_rodauth_tables.rb +266 -0
- data/demo/rhales-roda-demo/db/migrate/002_create_rodauth_password_tables.rb +79 -0
- data/demo/rhales-roda-demo/db/migrate/003_add_admin_account.rb +68 -0
- data/demo/rhales-roda-demo/templates/change_login.rue +31 -0
- data/demo/rhales-roda-demo/templates/change_password.rue +36 -0
- data/demo/rhales-roda-demo/templates/close_account.rue +31 -0
- data/demo/rhales-roda-demo/templates/create_account.rue +40 -0
- data/demo/rhales-roda-demo/templates/dashboard.rue +150 -0
- data/demo/rhales-roda-demo/templates/home.rue +78 -0
- data/demo/rhales-roda-demo/templates/layouts/main.rue +168 -0
- data/demo/rhales-roda-demo/templates/login.rue +65 -0
- data/demo/rhales-roda-demo/templates/logout.rue +25 -0
- data/demo/rhales-roda-demo/templates/reset_password.rue +26 -0
- data/demo/rhales-roda-demo/templates/verify_account.rue +27 -0
- data/demo/rhales-roda-demo/test_full_output.rb +27 -0
- data/demo/rhales-roda-demo/test_simple.rb +24 -0
- data/docs/.gitignore +9 -0
- data/docs/architecture/data-flow.md +499 -0
- data/examples/dashboard-with-charts.rue +271 -0
- data/examples/form-with-validation.rue +180 -0
- data/examples/simple-page.rue +61 -0
- data/examples/vue.rue +136 -0
- data/generate-json-schemas.ts +158 -0
- data/json_schemer_migration_summary.md +172 -0
- data/lib/rhales/adapters/base_auth.rb +2 -0
- data/lib/rhales/adapters/base_request.rb +2 -0
- data/lib/rhales/adapters/base_session.rb +2 -0
- data/lib/rhales/adapters.rb +7 -0
- data/lib/rhales/configuration.rb +161 -1
- data/lib/rhales/core/context.rb +354 -0
- data/lib/rhales/{rue_document.rb → core/rue_document.rb} +59 -43
- data/lib/rhales/{template_engine.rb → core/template_engine.rb} +80 -33
- data/lib/rhales/core/view.rb +529 -0
- data/lib/rhales/{view_composition.rb → core/view_composition.rb} +81 -9
- data/lib/rhales/core.rb +9 -0
- data/lib/rhales/errors/hydration_collision_error.rb +2 -0
- data/lib/rhales/errors.rb +2 -0
- data/lib/rhales/hydration/earliest_injection_detector.rb +153 -0
- data/lib/rhales/hydration/hydration_data_aggregator.rb +487 -0
- data/lib/rhales/hydration/hydration_endpoint.rb +215 -0
- data/lib/rhales/hydration/hydration_injector.rb +175 -0
- data/lib/rhales/{hydration_registry.rb → hydration/hydration_registry.rb} +2 -0
- data/lib/rhales/hydration/hydrator.rb +102 -0
- data/lib/rhales/hydration/link_based_injection_detector.rb +195 -0
- data/lib/rhales/hydration/mount_point_detector.rb +109 -0
- data/lib/rhales/hydration/safe_injection_validator.rb +103 -0
- data/lib/rhales/hydration.rb +13 -0
- data/lib/rhales/{refinements → integrations/refinements}/require_refinements.rb +7 -13
- data/lib/rhales/{tilt.rb → integrations/tilt.rb} +26 -18
- data/lib/rhales/integrations.rb +6 -0
- data/lib/rhales/middleware/json_responder.rb +191 -0
- data/lib/rhales/middleware/schema_validator.rb +300 -0
- data/lib/rhales/middleware.rb +6 -0
- data/lib/rhales/parsers/handlebars_parser.rb +2 -0
- data/lib/rhales/parsers/rue_format_parser.rb +55 -36
- data/lib/rhales/parsers.rb +9 -0
- data/lib/rhales/{csp.rb → security/csp.rb} +27 -3
- data/lib/rhales/utils/json_serializer.rb +114 -0
- data/lib/rhales/utils/logging_helpers.rb +75 -0
- data/lib/rhales/utils/schema_extractor.rb +132 -0
- data/lib/rhales/utils/schema_generator.rb +194 -0
- data/lib/rhales/utils.rb +40 -0
- data/lib/rhales/version.rb +5 -1
- data/lib/rhales.rb +47 -19
- data/lib/tasks/rhales_schema.rake +197 -0
- data/package.json +10 -0
- data/pnpm-lock.yaml +345 -0
- data/pnpm-workspace.yaml +2 -0
- data/proofs/error_handling.rb +79 -0
- data/proofs/expanded_object_inheritance.rb +82 -0
- data/proofs/partial_context_scoping_fix.rb +168 -0
- data/proofs/ui_context_partial_inheritance.rb +236 -0
- data/rhales.gemspec +14 -6
- data/schema_vs_data_comparison.md +254 -0
- data/test_direct_access.rb +36 -0
- metadata +142 -18
- data/CLAUDE.locale.txt +0 -7
- data/lib/rhales/context.rb +0 -240
- data/lib/rhales/hydration_data_aggregator.rb +0 -220
- data/lib/rhales/hydrator.rb +0 -141
- data/lib/rhales/parsers/handlebars-grammar-review.txt +0 -39
- data/lib/rhales/view.rb +0 -412
data/.gitignore
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Globs
|
|
2
|
+
*.env
|
|
3
|
+
*.log
|
|
4
|
+
*.txt
|
|
5
|
+
.byebug*
|
|
6
|
+
.ruby-version
|
|
7
|
+
|
|
8
|
+
# Directories
|
|
9
|
+
.claude
|
|
10
|
+
.continue/
|
|
11
|
+
.devcontainer
|
|
12
|
+
.history
|
|
13
|
+
.pnpm/
|
|
14
|
+
.pnpm-store/
|
|
15
|
+
.prompts/
|
|
16
|
+
.prompts*
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.ruby-lsp/
|
|
19
|
+
.vscode/
|
|
20
|
+
.idea/
|
|
21
|
+
.cache/
|
|
22
|
+
.temp/
|
|
23
|
+
.zed/
|
|
24
|
+
.bundle/
|
|
25
|
+
.rspec
|
|
26
|
+
data/
|
|
27
|
+
node_modules/
|
|
28
|
+
vendor/
|
|
29
|
+
log/
|
|
30
|
+
tmp/
|
|
31
|
+
coverage/
|
|
32
|
+
dist/
|
|
33
|
+
|
|
34
|
+
# Files
|
|
35
|
+
.DS_Store
|
|
36
|
+
.github/*md
|
|
37
|
+
.eslintcache
|
|
38
|
+
.claude
|
|
39
|
+
.rspec*
|
|
40
|
+
.qodo
|
|
41
|
+
*.gem
|
|
42
|
+
bin/bundle
|
|
43
|
+
bin/rspec
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Ignore WIP or temp dev files with uppercase names
|
|
47
|
+
[A-Z]*.rb
|
|
48
|
+
[A-Z]*.ts
|
|
49
|
+
[A-Z]*.md
|
|
50
|
+
|
|
51
|
+
!CLAUDE.md
|
|
52
|
+
|
|
53
|
+
# Environment files
|
|
54
|
+
.env*
|
|
55
|
+
!.env.example
|
data/.pr_agent.toml
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Global configuration for the Codium PR Agent.
|
|
2
|
+
#
|
|
3
|
+
# Change only what's needed to ease upstream merges. Be concise.
|
|
4
|
+
#
|
|
5
|
+
# @see https://github.com/qodo-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml
|
|
6
|
+
|
|
7
|
+
[config]
|
|
8
|
+
|
|
9
|
+
# model="o4-mini"
|
|
10
|
+
# fallback_models=["gpt-4.1"]
|
|
11
|
+
# git_provider="github"
|
|
12
|
+
patch_extra_lines = 1
|
|
13
|
+
response_language="en-CA" # Language locales code for PR responses in ISO 3166 and ISO 639 format (e.g., "en-US", "it-IT", "zh-CN", ...)
|
|
14
|
+
log_level="INFO"
|
|
15
|
+
large_patch_policy = "skip" # "clip", "skip"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
[pr_reviewer] # /review #
|
|
19
|
+
# general options
|
|
20
|
+
publish_output_no_suggestions=false # Set to "false" if you only need the reviewer's remarks (not labels, not "security audit", etc.) and want to avoid noisy "No major issues detected" comments.
|
|
21
|
+
num_code_suggestions=0
|
|
22
|
+
inline_code_comments = true
|
|
23
|
+
inline_code_comments_max_lines = 25
|
|
24
|
+
ask_and_reflect=true
|
|
25
|
+
automatic_review=true
|
|
26
|
+
num_max_findings = 4
|
|
27
|
+
|
|
28
|
+
# specific configurations for incremental review (/review -i)
|
|
29
|
+
require_all_thresholds_for_incremental_review=true
|
|
30
|
+
minimal_commits_for_incremental_review=1
|
|
31
|
+
minimal_minutes_for_incremental_review=5
|
|
32
|
+
enable_help_text=false # Determines whether to include help text in the PR review. Enabled by default.
|
|
33
|
+
# auto approval
|
|
34
|
+
enable_auto_approval=false
|
|
35
|
+
maximal_review_effort=9
|
|
36
|
+
|
|
37
|
+
[pr_description] # /describe #
|
|
38
|
+
publish_labels=false
|
|
39
|
+
generate_ai_title=true
|
|
40
|
+
keep_original_user_title=true
|
|
41
|
+
use_bullet_points=true
|
|
42
|
+
extra_instructions = ""
|
|
43
|
+
enable_pr_type=true
|
|
44
|
+
final_update_message = true
|
|
45
|
+
enable_help_text=false
|
|
46
|
+
enable_help_comment=true
|
|
47
|
+
inline_file_summary='table' # false, true, 'table'
|
|
48
|
+
# markers
|
|
49
|
+
use_description_markers=true
|
|
50
|
+
include_generated_by_header=true
|
|
51
|
+
|
|
52
|
+
[pr_questions] # /ask #
|
|
53
|
+
enable_help_text=true
|
|
54
|
+
|
|
55
|
+
[pr_add_docs] # /add_docs #
|
|
56
|
+
extra_instructions = ""
|
|
57
|
+
docs_style = "Sphinx Style" # "Google Style with Args, Returns, Attributes...etc", "Numpy Style", "Sphinx Style", "PEP257", "reStructuredText"
|
|
58
|
+
|
|
59
|
+
[pr_update_changelog] # /update_changelog #
|
|
60
|
+
push_changelog_changes=true
|
|
61
|
+
|
|
62
|
+
[pr_test] # /test #
|
|
63
|
+
enable_help_text=true
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Pre-Commit Hooks Configuration
|
|
3
|
+
#
|
|
4
|
+
# Fast, lightweight code quality checks that run before each commit
|
|
5
|
+
#
|
|
6
|
+
# Setup:
|
|
7
|
+
# 1. Install pre-commit:
|
|
8
|
+
# $ pip install pre-commit
|
|
9
|
+
#
|
|
10
|
+
# 2. Install git hooks:
|
|
11
|
+
# $ pre-commit install
|
|
12
|
+
#
|
|
13
|
+
# Usage:
|
|
14
|
+
# Hooks run automatically on 'git commit'
|
|
15
|
+
#
|
|
16
|
+
# Manual commands:
|
|
17
|
+
# - Check all files:
|
|
18
|
+
# $ pre-commit run --all-files
|
|
19
|
+
#
|
|
20
|
+
# - Update hooks:
|
|
21
|
+
# $ pre-commit autoupdate
|
|
22
|
+
#
|
|
23
|
+
# - Reinstall after config changes:
|
|
24
|
+
# $ pre-commit install
|
|
25
|
+
#
|
|
26
|
+
# Best Practices:
|
|
27
|
+
# - Reinstall hooks after modifying this config
|
|
28
|
+
# - Commit config changes in isolation
|
|
29
|
+
# - Keep checks fast to maintain workflow
|
|
30
|
+
#
|
|
31
|
+
# Resources:
|
|
32
|
+
# - Docs: https://pre-commit.com
|
|
33
|
+
# - Available hooks: https://pre-commit.com/hooks.html
|
|
34
|
+
#
|
|
35
|
+
# Note: These lightweight checks maintain code quality without
|
|
36
|
+
# slowing down the local development process.
|
|
37
|
+
|
|
38
|
+
# Hook installation configuration
|
|
39
|
+
default_install_hook_types:
|
|
40
|
+
- pre-commit # Primary code quality checks
|
|
41
|
+
- prepare-commit-msg # Commit message preprocessing
|
|
42
|
+
- post-commit # Actions after successful commit
|
|
43
|
+
- post-checkout # Triggered after git checkout
|
|
44
|
+
- post-merge # Triggered after git merge
|
|
45
|
+
|
|
46
|
+
# Default execution stage
|
|
47
|
+
default_stages: [pre-commit]
|
|
48
|
+
|
|
49
|
+
# Run all hooks even if some fail (allows multiple auto-fixes in one run)
|
|
50
|
+
fail_fast: false
|
|
51
|
+
|
|
52
|
+
# Ignore generated and dependency directories
|
|
53
|
+
exclude: '^$'
|
|
54
|
+
|
|
55
|
+
repos:
|
|
56
|
+
# Meta hooks: basic checks for pre-commit config itself
|
|
57
|
+
- repo: meta
|
|
58
|
+
hooks:
|
|
59
|
+
- id: check-hooks-apply
|
|
60
|
+
- id: check-useless-excludes
|
|
61
|
+
- id: identity
|
|
62
|
+
name: Identity Hook (for sanity checking)
|
|
63
|
+
args: ['--hello', '--world']
|
|
64
|
+
|
|
65
|
+
# Standard pre-commit hooks: lightweight, universal checks
|
|
66
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
67
|
+
rev: v5.0.0
|
|
68
|
+
hooks:
|
|
69
|
+
# Formatting and basic sanitization
|
|
70
|
+
- id: trailing-whitespace # Remove trailing whitespaces
|
|
71
|
+
- id: end-of-file-fixer # Ensure files end with newline
|
|
72
|
+
- id: check-merge-conflict # Detect unresolved merge conflicts
|
|
73
|
+
- id: detect-private-key # Warn about committing private keys
|
|
74
|
+
- id: check-added-large-files # Prevent committing oversized files
|
|
75
|
+
args: ['--maxkb=2500'] # 2.5MB file size threshold
|
|
76
|
+
- id: no-commit-to-branch # Prevent direct commits to critical branches
|
|
77
|
+
args: ['--branch', 'develop', '--branch', 'rel/.*']
|
|
78
|
+
|
|
79
|
+
# Commit message issue tracking integration
|
|
80
|
+
- repo: https://github.com/avilaton/add-msg-issue-prefix-hook
|
|
81
|
+
rev: v0.0.11
|
|
82
|
+
hooks:
|
|
83
|
+
- id: add-msg-issue-prefix
|
|
84
|
+
stages: [prepare-commit-msg]
|
|
85
|
+
description: Automatically prefix commits with issue numbers
|
|
86
|
+
args:
|
|
87
|
+
- '--default='
|
|
88
|
+
- '--pattern=(?:i18n(?=\/)|[a-zA-Z0-9]{0,10}-?[0-9]{1,5})'
|
|
89
|
+
- '--template=[#{}]'
|
data/.prettierignore
ADDED
data/.prettierrc
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"arrowParens": "always",
|
|
3
|
+
"bracketSameLine": true,
|
|
4
|
+
"bracketSpacing": true,
|
|
5
|
+
"embeddedLanguageFormatting": "auto",
|
|
6
|
+
"endOfLine": "lf",
|
|
7
|
+
"htmlWhitespaceSensitivity": "strict",
|
|
8
|
+
"jsxSingleQuote": false,
|
|
9
|
+
"overrides": [
|
|
10
|
+
{
|
|
11
|
+
"files": "*.svg",
|
|
12
|
+
"options": {
|
|
13
|
+
"parser": "html",
|
|
14
|
+
"plugins": []
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"files": ["*.vue"],
|
|
19
|
+
"options": {
|
|
20
|
+
"parser": "vue",
|
|
21
|
+
"vueIndentScriptAndStyle": true,
|
|
22
|
+
"htmlWhitespaceSensitivity": "strict",
|
|
23
|
+
"printWidth": 100
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"plugins": ["prettier-plugin-vue", "@prettier/plugin-ruby"],
|
|
28
|
+
"vueIndentScriptAndStyle": true,
|
|
29
|
+
"printWidth": 100,
|
|
30
|
+
"proseWrap": "preserve",
|
|
31
|
+
"quoteProps": "as-needed",
|
|
32
|
+
"semi": true,
|
|
33
|
+
"singleAttributePerLine": true,
|
|
34
|
+
"singleQuote": true,
|
|
35
|
+
"tabWidth": 2,
|
|
36
|
+
"trailingComma": "es5",
|
|
37
|
+
"useTabs": false
|
|
38
|
+
}
|
data/.reek.yml
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# .reek.yml
|
|
2
|
+
# Reek configuration for Rhales
|
|
3
|
+
#
|
|
4
|
+
# Basic commands:
|
|
5
|
+
# bundle exec reek # Analyze all Ruby files
|
|
6
|
+
# bundle exec reek lib/ # Analyze specific directory
|
|
7
|
+
# bundle exec reek lib/rhales.rb # Analyze specific file
|
|
8
|
+
# bundle exec reek --help # Show all options
|
|
9
|
+
# bundle exec reek --docs # Open documentation
|
|
10
|
+
#
|
|
11
|
+
# Advanced usage:
|
|
12
|
+
# bundle exec reek --format=html > report.html # Generate HTML report
|
|
13
|
+
# bundle exec reek --format=json # JSON output for CI
|
|
14
|
+
# bundle exec reek --config .reek.yml # Use specific config
|
|
15
|
+
# bundle exec reek --show-docs IrresponsibleModule # Explain specific smell
|
|
16
|
+
# bundle exec reek --failure-exit-code 1 # Exit with error on smells (for CI)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
detectors:
|
|
20
|
+
# Disable some detectors for initial adoption
|
|
21
|
+
# You can gradually enable these as you clean up the codebase
|
|
22
|
+
|
|
23
|
+
# Class/Module Structure
|
|
24
|
+
IrresponsibleModule:
|
|
25
|
+
enabled: false # Modules without documentation - start with this disabled
|
|
26
|
+
|
|
27
|
+
# Method Complexity
|
|
28
|
+
TooManyStatements:
|
|
29
|
+
enabled: true
|
|
30
|
+
max_statements: 15 # Default is 5, relaxed for initial adoption
|
|
31
|
+
|
|
32
|
+
TooManyMethods:
|
|
33
|
+
enabled: true
|
|
34
|
+
max_methods: 25 # Default is 15, relaxed for ORMs which often have many methods
|
|
35
|
+
|
|
36
|
+
LongParameterList:
|
|
37
|
+
enabled: true
|
|
38
|
+
max_params: 4 # Default is 3, slightly relaxed
|
|
39
|
+
|
|
40
|
+
# Data Classes and Feature Envy
|
|
41
|
+
DataClump:
|
|
42
|
+
enabled: true
|
|
43
|
+
|
|
44
|
+
FeatureEnvy:
|
|
45
|
+
enabled: true
|
|
46
|
+
|
|
47
|
+
# Control Structure
|
|
48
|
+
NestedIterators:
|
|
49
|
+
enabled: true
|
|
50
|
+
max_allowed_nesting: 2 # Default is 1, relaxed for data processing
|
|
51
|
+
|
|
52
|
+
# Variable and Constant Usage
|
|
53
|
+
UnusedParameters:
|
|
54
|
+
enabled: true
|
|
55
|
+
|
|
56
|
+
InstanceVariableAssumption:
|
|
57
|
+
enabled: true
|
|
58
|
+
|
|
59
|
+
# Naming
|
|
60
|
+
UncommunicativeParameterName:
|
|
61
|
+
enabled: true
|
|
62
|
+
reject:
|
|
63
|
+
- '/^.$/' # Single letter names
|
|
64
|
+
- '/[0-9]$/' # Names ending in numbers
|
|
65
|
+
accept:
|
|
66
|
+
- '_' # Single underscore for intentionally unused parameters
|
|
67
|
+
|
|
68
|
+
UncommunicativeVariableName:
|
|
69
|
+
enabled: true
|
|
70
|
+
reject:
|
|
71
|
+
- '/^.$/' # Single letter names
|
|
72
|
+
- '/[0-9]$/' # Names ending in numbers
|
|
73
|
+
accept:
|
|
74
|
+
- e # Exception variable
|
|
75
|
+
- id # Common identifier
|
|
76
|
+
- db # Database connection
|
|
77
|
+
- op # Operation
|
|
78
|
+
- io # Input/output
|
|
79
|
+
|
|
80
|
+
UncommunicativeMethodName:
|
|
81
|
+
enabled: true
|
|
82
|
+
reject:
|
|
83
|
+
- '/^.$/' # Single letter method names
|
|
84
|
+
- '/[0-9]$/' # Methods ending in numbers
|
|
85
|
+
accept:
|
|
86
|
+
- '<<' # Common Ruby operator overload
|
|
87
|
+
|
|
88
|
+
# Directory and file exclusions
|
|
89
|
+
exclude_paths:
|
|
90
|
+
- 'vendor/**/*.rb'
|
|
91
|
+
- 'tmp/**/*.rb'
|
|
92
|
+
- 'try/**/*.rb' # Test files using tryouts framework
|
|
93
|
+
- 'examples/**/*.rb' # Example code files
|
|
94
|
+
- 'bin/*' # Executable scripts
|
|
95
|
+
- '*.gemspec' # Gem specification files
|
|
96
|
+
|
|
97
|
+
# Note: For limiting warnings output, use CLI: bundle exec reek | head -50
|
|
98
|
+
# Note: For failure exit codes, use CLI: bundle exec reek --failure-exit-code 1
|