ruby-skill-bench 1.4.0 → 2.0.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 +4 -4
- data/README.md +11 -10
- data/docs/docker.md +1 -1
- data/docs/first-eval-guide.md +12 -4
- data/lib/skill_bench/clients/base_client.rb +3 -3
- data/lib/skill_bench/judge/variance.rb +5 -4
- data/lib/skill_bench/runner.rb +2 -5
- data/lib/skill_bench/services/batch_runner_service.rb +3 -5
- data/lib/skill_bench/services/output_persistence_service.rb +1 -1
- data/lib/skill_bench/task/directory_finder.rb +20 -0
- data/lib/skill_bench/version.rb +1 -1
- data/lib/skill_bench.rb +1 -0
- metadata +9 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cb1aca517e3a5d2599b68f7bff39222f556e0bc6bce90490b0f1d5358f6547c2
|
|
4
|
+
data.tar.gz: 7e8dffa808ea6248d8b84b00492066f071c8771cb8fc7bbb25121149270affaa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d1bf40f9e8bb02757be1bb2fb2fa5a68187d3bbc472852ce34306aaf85782a6b8acdb8b977d1779f03c8a717c9874fe98f09856925f1446575a519c91a5e997
|
|
7
|
+
data.tar.gz: 42b9b9311d45a376e9d3e15a75be1cdf43bbcf234db2180c23cab7085a64b224026b5b2b6097be33118b532f7f6728f32787168cfa1fdd5cc1fd2bd6cd5a3d45
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://deepwiki.com/igmarin/ruby-skill-bench)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Ruby Skill Bench compares how an AI coding agent completes the same task with and without a skill. It runs both attempts in temporary Git sandboxes, then scores them against criteria you define. You can use it with Ruby projects and other stacks.
|
|
10
10
|
|
|
11
11
|
## Part of the AI Skill Ecosystem
|
|
12
12
|
|
|
@@ -27,12 +27,11 @@ See the [Ecosystem Overview](https://github.com/igmarin/agent-mcp-runtime/blob/m
|
|
|
27
27
|
|
|
28
28
|
## Features
|
|
29
29
|
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
32
|
-
- **
|
|
33
|
-
- **
|
|
34
|
-
- **
|
|
35
|
-
- **Standardized Intelligence**: Consistent reporting format regardless of the underlying LLM provider.
|
|
30
|
+
- **Compare two runs**: See what changes when an agent receives a skill.
|
|
31
|
+
- **Isolate evaluation work**: Each attempt runs in its own temporary Git sandbox.
|
|
32
|
+
- **Score against your criteria**: Configure dimensions, weights, and pass thresholds in `criteria.json`.
|
|
33
|
+
- **Use your provider**: OpenAI, Anthropic, Google Gemini, Azure OpenAI, Ollama, Groq, DeepSeek, Mistral, OpenCode, OpenRouter, xAI, and Amazon Bedrock are supported.
|
|
34
|
+
- **Get consistent reports**: The output format stays the same across providers.
|
|
36
35
|
|
|
37
36
|
---
|
|
38
37
|
|
|
@@ -118,6 +117,8 @@ Configuration is loaded in this order (later sources override earlier ones):
|
|
|
118
117
|
|
|
119
118
|
## Getting Started
|
|
120
119
|
|
|
120
|
+
Ruby Skill Bench requires Ruby 3.3 or newer. For a guided first run, see the [5-minute first eval guide](docs/first-eval-guide.md).
|
|
121
|
+
|
|
121
122
|
### Installation
|
|
122
123
|
|
|
123
124
|
```bash
|
|
@@ -184,7 +185,7 @@ skills/
|
|
|
184
185
|
|
|
185
186
|
**Example `SKILL.md`:**
|
|
186
187
|
|
|
187
|
-
|
|
188
|
+
````markdown
|
|
188
189
|
# Service Object Skill
|
|
189
190
|
|
|
190
191
|
## Pattern
|
|
@@ -200,7 +201,7 @@ All service objects use the `.call` class method and return a standardized hash:
|
|
|
200
201
|
1. Every `.rb` file begins with `# frozen_string_literal: true`
|
|
201
202
|
2. Every public method has YARD docs (`@param`, `@return`, `@raise`)
|
|
202
203
|
3. `rescue StandardError` blocks must log backtrace
|
|
203
|
-
|
|
204
|
+
````
|
|
204
205
|
|
|
205
206
|
---
|
|
206
207
|
|
|
@@ -1153,7 +1154,7 @@ jobs:
|
|
|
1153
1154
|
|
|
1154
1155
|
The action installs the gem and runs `skill-bench run --all --evals-dir <evals-dir> --format <format>` (adding `--skill` when set and appending `args` verbatim). The run step's exit code is the gate. For a full copy-paste workflow template, see [`examples/ci/`](examples/ci/).
|
|
1155
1156
|
|
|
1156
|
-
> The gem's own repository CI (`.github/workflows/ci.yml`) runs
|
|
1157
|
+
> The gem's own repository CI (`.github/workflows/ci.yml`) runs RuboCop, Reek, and Minitest on Ruby 3.3, 3.4, and 4.0. This is separate from the reusable action above.
|
|
1157
1158
|
|
|
1158
1159
|
To preview the machine-readable output locally:
|
|
1159
1160
|
|
data/docs/docker.md
CHANGED
|
@@ -10,7 +10,7 @@ execution when a Docker daemon is available.
|
|
|
10
10
|
|------|--------|
|
|
11
11
|
| Image name | `evaluator-sandbox` (`Constants::Sandbox::DOCKER_IMAGE_NAME`) |
|
|
12
12
|
| Tags | `evaluator-sandbox:<SkillBench::VERSION>` and `evaluator-sandbox:latest` |
|
|
13
|
-
| Base | `ruby:3.4-bookworm` (
|
|
13
|
+
| Base | `ruby:3.4-bookworm` (commands inside the container use Ruby 3.4; the gem also supports Ruby 3.3 and 4.0 on the host) |
|
|
14
14
|
| Preinstalled | Ruby (from base), `git`, minimal Debian tools from base image |
|
|
15
15
|
| Working directory | `/sandbox` (host sandbox dir is bind-mounted here read-write) |
|
|
16
16
|
| Default process | `sleep infinity` — container stays up for `docker exec` |
|
data/docs/first-eval-guide.md
CHANGED
|
@@ -6,13 +6,13 @@ Get started with Ruby Skill Bench in 5 minutes. No prior AI eval experience requ
|
|
|
6
6
|
|
|
7
7
|
## Prerequisites
|
|
8
8
|
|
|
9
|
-
- Ruby 3.
|
|
9
|
+
- Ruby 3.3+
|
|
10
10
|
- Bundler
|
|
11
11
|
|
|
12
12
|
Not sure? Run:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
ruby --version # Should be 3.
|
|
15
|
+
ruby --version # Should be 3.3 or higher
|
|
16
16
|
bundle --version # Should print a version number
|
|
17
17
|
```
|
|
18
18
|
|
|
@@ -42,6 +42,14 @@ skill-bench init --openai
|
|
|
42
42
|
|
|
43
43
|
This creates `skill-bench.json` with the OpenAI provider config. Use `--force` to overwrite.
|
|
44
44
|
|
|
45
|
+
Before running an eval, set your OpenAI key in the shell. Do not commit API keys to your repository:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
export SKILL_BENCH_OPENAI_API_KEY=your-api-key
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
To try the commands without an API key or network access, initialize the offline mock provider instead: `skill-bench init --mock`. The mock provider is useful for learning the workflow; it does not measure a real model.
|
|
52
|
+
|
|
45
53
|
**Available providers:** `--openai`, `--anthropic`, `--gemini`, `--ollama`, `--azure`, `--groq`, `--deepseek`, `--mistral`, `--opencode`, `--openrouter`, `--xai`, `--bedrock`, plus `--mock` for an offline config with no API key.
|
|
46
54
|
|
|
47
55
|
> **What is `skill-bench.json`?** This is your config file. It stores your API key, chosen LLM model, timeout, and allowed shell commands. Think of it as `.env` but structured as JSON. You edit it; SkillBench reads it.
|
|
@@ -66,7 +74,7 @@ This creates `skills/my-service/SKILL.md` with a Rails service object template.
|
|
|
66
74
|
|
|
67
75
|
**Example `SKILL.md`:**
|
|
68
76
|
|
|
69
|
-
|
|
77
|
+
````markdown
|
|
70
78
|
# Service Object Skill
|
|
71
79
|
|
|
72
80
|
## Pattern
|
|
@@ -82,7 +90,7 @@ All service objects use the `.call` class method and return a standardized hash:
|
|
|
82
90
|
1. Every `.rb` file begins with `# frozen_string_literal: true`
|
|
83
91
|
2. Every public method has YARD docs (`@param`, `@return`, `@raise`)
|
|
84
92
|
3. `rescue StandardError` blocks must log backtrace
|
|
85
|
-
|
|
93
|
+
````
|
|
86
94
|
|
|
87
95
|
---
|
|
88
96
|
|
|
@@ -21,10 +21,10 @@ module SkillBench
|
|
|
21
21
|
# @param system_prompt [String] The system instruction for the LLM.
|
|
22
22
|
# @param messages [Array<Hash>] The list of conversation messages.
|
|
23
23
|
# @param tools [Array<Hash>] (optional) Array of tool definitions.
|
|
24
|
-
#
|
|
24
|
+
# Additional keyword options are passed to the selected provider client.
|
|
25
25
|
# @return [Hash] with :success [Boolean] and :response [Hash] keys.
|
|
26
|
-
def self.call(system_prompt:, messages:, tools: [], **
|
|
27
|
-
new(system_prompt: system_prompt, messages: messages, tools: tools, **
|
|
26
|
+
def self.call(system_prompt:, messages:, tools: [], **)
|
|
27
|
+
new(system_prompt: system_prompt, messages: messages, tools: tools, **).call
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Initializes the client with validated parameters.
|
|
@@ -20,15 +20,16 @@ module SkillBench
|
|
|
20
20
|
# @return [Hash]
|
|
21
21
|
def call
|
|
22
22
|
nums = Array(@totals).map { |total| Float(total) }
|
|
23
|
-
|
|
23
|
+
count = nums.size
|
|
24
|
+
return empty_result(count: count) if count < 2
|
|
24
25
|
|
|
25
|
-
mean = nums.sum /
|
|
26
|
-
sample_variance = nums.sum { |value| (value - mean)**2 } / (
|
|
26
|
+
mean = nums.sum / count
|
|
27
|
+
sample_variance = nums.sum { |value| (value - mean)**2 } / (count - 1)
|
|
27
28
|
|
|
28
29
|
{
|
|
29
30
|
success: true,
|
|
30
31
|
response: {
|
|
31
|
-
n:
|
|
32
|
+
n: count,
|
|
32
33
|
mean: mean,
|
|
33
34
|
stddev: Math.sqrt(sample_variance),
|
|
34
35
|
spread: nums.max - nums.min
|
data/lib/skill_bench/runner.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'pathname'
|
|
4
4
|
require 'parallel'
|
|
5
|
+
require_relative 'task/directory_finder'
|
|
5
6
|
require_relative 'task/evaluator'
|
|
6
7
|
require_relative 'error_logger'
|
|
7
8
|
|
|
@@ -79,11 +80,7 @@ module SkillBench
|
|
|
79
80
|
# @param root_path [Pathname] The root directory to search.
|
|
80
81
|
# @return [Array<Pathname>] A list of task directory paths.
|
|
81
82
|
def self.discover_task_dirs(root_path)
|
|
82
|
-
|
|
83
|
-
[root_path]
|
|
84
|
-
else
|
|
85
|
-
Dir.glob(root_path.join('**/task.md')).map { |f| Pathname.new(f).parent }.uniq.sort
|
|
86
|
-
end
|
|
83
|
+
Task::DirectoryFinder.call(root_path)
|
|
87
84
|
end
|
|
88
85
|
end
|
|
89
86
|
end
|
|
@@ -4,7 +4,7 @@ require 'pathname'
|
|
|
4
4
|
require 'parallel'
|
|
5
5
|
require_relative 'runner_service'
|
|
6
6
|
require_relative '../output_formatter'
|
|
7
|
-
require_relative '../
|
|
7
|
+
require_relative '../task/directory_finder'
|
|
8
8
|
|
|
9
9
|
module SkillBench
|
|
10
10
|
module Services
|
|
@@ -14,9 +14,7 @@ module SkillBench
|
|
|
14
14
|
# {RunnerService} over each, returning an aggregate envelope with
|
|
15
15
|
# per-eval results and a pass/fail summary.
|
|
16
16
|
#
|
|
17
|
-
#
|
|
18
|
-
# routes through the deprecated {SkillBench::Task::Evaluator}: each eval
|
|
19
|
-
# is executed by the supported {RunnerService}.
|
|
17
|
+
# Each discovered eval is executed by the supported {RunnerService}.
|
|
20
18
|
class BatchRunnerService
|
|
21
19
|
# Default directory scanned for evals when none is supplied.
|
|
22
20
|
DEFAULT_EVALS_DIR = 'evals'
|
|
@@ -80,7 +78,7 @@ module SkillBench
|
|
|
80
78
|
#
|
|
81
79
|
# @return [Array<Pathname>] Directories that contain a task.md
|
|
82
80
|
def discover_eval_dirs
|
|
83
|
-
|
|
81
|
+
Task::DirectoryFinder.call(Pathname.new(evals_dir))
|
|
84
82
|
end
|
|
85
83
|
|
|
86
84
|
# Runs every eval directory through {RunnerService} concurrently.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pathname'
|
|
4
|
+
|
|
5
|
+
module SkillBench
|
|
6
|
+
module Task
|
|
7
|
+
# Finds evaluation task directories under a root path.
|
|
8
|
+
class DirectoryFinder
|
|
9
|
+
# Finds the root task or all nested task directories in sorted order.
|
|
10
|
+
#
|
|
11
|
+
# @param root_path [Pathname] Directory to search.
|
|
12
|
+
# @return [Array<Pathname>] Directories containing a task.md file.
|
|
13
|
+
def self.call(root_path)
|
|
14
|
+
return [root_path] if File.exist?(root_path.join('task.md'))
|
|
15
|
+
|
|
16
|
+
Dir.glob(root_path.join('**/task.md')).map { |path| Pathname.new(path).parent }.uniq.sort
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/skill_bench/version.rb
CHANGED
data/lib/skill_bench.rb
CHANGED
|
@@ -34,6 +34,7 @@ require_relative 'skill_bench/agent/react_agent'
|
|
|
34
34
|
require_relative 'skill_bench/task'
|
|
35
35
|
require_relative 'skill_bench/task/evaluator'
|
|
36
36
|
require_relative 'skill_bench/task/file_reader'
|
|
37
|
+
require_relative 'skill_bench/runner'
|
|
37
38
|
|
|
38
39
|
# Evaluation orchestration
|
|
39
40
|
require_relative 'skill_bench/evaluation'
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-skill-bench
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ismael Marin
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: cgi
|
|
@@ -44,34 +43,28 @@ dependencies:
|
|
|
44
43
|
requirements:
|
|
45
44
|
- - "~>"
|
|
46
45
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
48
|
-
- - ">="
|
|
49
|
-
- !ruby/object:Gem::Version
|
|
50
|
-
version: 2.21.2
|
|
46
|
+
version: '3.0'
|
|
51
47
|
type: :runtime
|
|
52
48
|
prerelease: false
|
|
53
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
54
50
|
requirements:
|
|
55
51
|
- - "~>"
|
|
56
52
|
- !ruby/object:Gem::Version
|
|
57
|
-
version: '
|
|
58
|
-
- - ">="
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: 2.21.2
|
|
53
|
+
version: '3.0'
|
|
61
54
|
- !ruby/object:Gem::Dependency
|
|
62
55
|
name: parallel
|
|
63
56
|
requirement: !ruby/object:Gem::Requirement
|
|
64
57
|
requirements:
|
|
65
58
|
- - "~>"
|
|
66
59
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '
|
|
60
|
+
version: '2.0'
|
|
68
61
|
type: :runtime
|
|
69
62
|
prerelease: false
|
|
70
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
71
64
|
requirements:
|
|
72
65
|
- - "~>"
|
|
73
66
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: '
|
|
67
|
+
version: '2.0'
|
|
75
68
|
description: |
|
|
76
69
|
ruby-skill-bench orchestrates evaluation runs of AI coding agents
|
|
77
70
|
inside isolated git sandboxes, then scores the results using deterministic
|
|
@@ -225,6 +218,7 @@ files:
|
|
|
225
218
|
- lib/skill_bench/services/variant_parser.rb
|
|
226
219
|
- lib/skill_bench/services/variant_resolver.rb
|
|
227
220
|
- lib/skill_bench/task.rb
|
|
221
|
+
- lib/skill_bench/task/directory_finder.rb
|
|
228
222
|
- lib/skill_bench/task/evaluator.rb
|
|
229
223
|
- lib/skill_bench/task/file_reader.rb
|
|
230
224
|
- lib/skill_bench/tools.rb
|
|
@@ -245,7 +239,6 @@ licenses:
|
|
|
245
239
|
metadata:
|
|
246
240
|
rubygems_mfa_required: 'true'
|
|
247
241
|
source_code_uri: https://github.com/igmarin/ruby-skill-bench
|
|
248
|
-
post_install_message:
|
|
249
242
|
rdoc_options: []
|
|
250
243
|
require_paths:
|
|
251
244
|
- lib
|
|
@@ -253,15 +246,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
253
246
|
requirements:
|
|
254
247
|
- - ">="
|
|
255
248
|
- !ruby/object:Gem::Version
|
|
256
|
-
version: '3.
|
|
249
|
+
version: '3.3'
|
|
257
250
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
258
251
|
requirements:
|
|
259
252
|
- - ">="
|
|
260
253
|
- !ruby/object:Gem::Version
|
|
261
254
|
version: '0'
|
|
262
255
|
requirements: []
|
|
263
|
-
rubygems_version:
|
|
264
|
-
signing_key:
|
|
256
|
+
rubygems_version: 4.0.21
|
|
265
257
|
specification_version: 4
|
|
266
258
|
summary: The evaluation engine for AI Agent Skills benchmarking.
|
|
267
259
|
test_files: []
|