skillgauntlet 1.0.0 → 1.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.
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # SkillGauntlet
2
+
3
+ *Every skill runs the gauntlet.*
4
+
5
+ Agent skills (SKILL.md) keep piling up and changing fast, yet nobody tells you which ones are still worth keeping. SkillGauntlet is an independent, third-party evaluation of popular skills, using public and reproducible methods to answer what you most need to know before installing one.
6
+
7
+ ## Three layers, cheapest first
8
+
9
+ | Layer | Question | Cost |
10
+ |---|---|---|
11
+ | 0 static | What does it put in my context, what is it allowed to touch, what does its code do, does it try to hijack the model, is the description even usable? | zero |
12
+ | 1 trigger | When I ask for the job it claims, does it actually fire? Does it fire when it shouldn't? | model calls |
13
+ | 2 gain | With it versus without it, on a task a program can grade: does it help? | model calls ×2 |
14
+
15
+ Layer 0 runs first because it is free and because it disqualifies most problems before you spend anything.
16
+ Layers 1 and 2 are opt-in.
17
+
18
+ ## Results so far
19
+
20
+ Step 0 tested 18 popular skills on 2026-10-28. Start with the
21
+ [overview](step0/data/OVERVIEW-2026-10-28.md), which says what each report measures and which numbers
22
+ can be compared.
23
+
24
+ - [Haiku batch](step0/data/2026-10-28_all_haiku/BATCH.md) (headline): Claude Code × claude-haiku-5-5,
25
+ 1,798 trials. 1 skill triggers well, 6 fair, 11 poorly; across all skills, recall is 41%.
26
+ - [DeepSeek batch](step0/data/2026-10-28_all_deepseek/BATCH.md): the same question sets on
27
+ deepseek-v4-flash. Overall recall is the same, but single skills move a lot, one of them by more than 70 points.
28
+ - [Codex probe](step0/data/2026-10-28_codex_probe/BATCH.md): facts only, no trigger rate (see
29
+ "Hosts and models").
30
+ - [Static layer](step0/data/2026-10-28_all_haiku/static/SUMMARY.md): all 18 skills, no model calls.
31
+
32
+ ## Usage
33
+
34
+ Needs Node 18 or later; the package has no dependencies.
35
+
36
+ ```
37
+ npx skillgauntlet # interactive
38
+ npx skillgauntlet static path/to/skill # layer 0 only, no model calls
39
+ npx skillgauntlet static path/to/repo --json
40
+ npx skillgauntlet resume path/to/run-dir # continue an interrupted or stopped run
41
+ ```
42
+
43
+ From a clone, `node bin/skillgauntlet.js` does the same, and
44
+ `node scripts/static-summary.mjs step0/skills.json step0/data/static` runs layer 0 over a whole manifest.
45
+ Add `--lang zh|ja|en`, or set `SG_LANG`, to choose the language without the menu.
46
+
47
+ The interactive flow asks the following, in this order, and takes only arrow keys, `y`/`n` and enter:
48
+
49
+ 1. **Language**: 中文, 日本語 or English.
50
+ 2. **Where the skill comes from**: already installed (scanned in `.agents/skills`,
51
+ `.claude/skills`, `.codex/skills`, user and project scope), another local directory, or a GitHub
52
+ repository for a skill you have not installed.
53
+ 3. **How many**: all discovered skills, or just one picked with the arrow keys.
54
+ 4. **Host**: Claude Code, CodeBuddy Code, Codewhale or Codex (see "Hosts and models").
55
+ 5. **Depth**, then **backend** and **model**.
56
+ 6. **An estimate before anything is spent**: trials and minutes for the whole selection, not just
57
+ per skill. No cash figure is shown, because what a run costs depends on the backend and the plan,
58
+ and a number would be a guess.
59
+ 7. **`y`** to run, `n` to cancel.
60
+
61
+ A skill that is not installed is named the way it can be resolved: `owner/repo`, or
62
+ `owner/repo/path/to/skill` when the repository holds several. There is no global name-to-repository
63
+ registry, so a bare name like `tdd` cannot be resolved and the prompt says so.
64
+
65
+ Layer 2 results are a **local comparison and are never uploaded**. Nothing is uploaded at all: there is
66
+ no public leaderboard yet, so the CLI says so instead of offering a submission that would go nowhere.
67
+
68
+ Every run is archived under the skill's `.skillgauntlet/runs/<timestamp>/`:
69
+
70
+ | file | contents |
71
+ |---|---|
72
+ | `raw.jsonl` | one record per trial, appended as it finishes |
73
+ | `meta.json` | host, backend, model, runs, exploration budget, depth, question-set hash, platform, start and end |
74
+ | `summary.json` | the totals the report was rendered from |
75
+
76
+ `meta.json` is written before the first trial and refreshed every 25 records, so a run killed by
77
+ Ctrl-C, a quota limit or a closed laptop keeps everything it already finished and still says what
78
+ conditions produced it. The records are the only artefact that cannot be regenerated cheaply: the
79
+ report is a rendering of them, and keeping them means the statistics can be corrected, two runs
80
+ compared, or a submission assembled later without paying for the trials again.
81
+
82
+ A run stops by itself after 8 errors or timeouts in a row (a quota limit usually looks like that) and
83
+ exits with code 3. `resume <run-dir>` continues it, and retries the failed trials. It refuses to resume
84
+ when the model, backend, runs, exploration budget, question set or SKILL.md has changed, because records
85
+ made under different conditions cannot be pooled.
86
+
87
+ The report follows the language you picked (Chinese, Japanese or English). Every sentence comes from
88
+ one message table, and the scorecard JSON carries message keys rather than prose
89
+ (`skillgauntlet/scorecard/2`), so a stored scorecard can be rendered in any of the three languages
90
+ without re-analysing the skill. The Japanese wording has not yet been reviewed by a native speaker.
91
+
92
+ The static layer reports by group and never sums them: a weighted total cannot be audited or appealed,
93
+ and appeal is the one thing a rating must allow.
94
+
95
+ - **A context cost** — SKILL.md size in tokens, description length (read on every request), whether the
96
+ body references files instead of inlining them, package size.
97
+ - **B permission surface** — whether `allowed-tools` is declared, how wide the declared scope is,
98
+ whether the skill is manual-invocation only, how much executable code it ships.
99
+ - **C code risk** — network calls, command execution, credential access, obfuscation, install hooks.
100
+ Reported as facts; escalated only when the skill ships code *and* declares no scope.
101
+ - **D instruction hijacking** — override phrases, requests for sensitive paths, instructions to send
102
+ data out, zero-width characters, external images.
103
+ - **E description quality** — presence, whether it states when to use it, over-broad quantifiers,
104
+ rough clause count, name/directory agreement.
105
+
106
+ ## Status
107
+
108
+ Early stage, and honestly labelled.
109
+
110
+ - **Layer 0: implemented and exercised** on the 18 step 0 skills, twice, with identical output; see
111
+ [`static/SUMMARY.md`](step0/data/2026-10-28_all_haiku/static/SUMMARY.md). Its thresholds (SKILL.md
112
+ token counts, package size) are not yet calibrated against a real distribution, so treat them as a
113
+ ranking aid, not as a pass mark.
114
+ - **Layer 1: two runners, published data.**
115
+ - The Python runner in [`step0/`](step0/README.md) produced every published batch. It runs a whole
116
+ manifest, resumes, and pins each skill to a commit.
117
+ - The Node CLI is the one meant for other people. It follows the same verdict rule and has
118
+ been run end to end on one skill on each path: Claude Code × Haiku, Claude Code × DeepSeek,
119
+ CodeBuddy Code and Codewhale.
120
+ - The two runners draft questions with different prompts: the CLI's negatives must borrow the
121
+ description's wording. Their question sets are therefore not interchangeable.
122
+ - **Layer 2: contract DSL implemented** ([`contracts/`](contracts/)), with per-task contracts for tdd,
123
+ xlsx, webapp-testing and diagnosing-bugs: 14 contracts covering 4 of the 18 skills. No LLM judge, on
124
+ purpose: a judge would be expensive, biased and not reproducible. A skill without a contract is
125
+ reported as "not gradable automatically" rather than guessed. `node scripts/check-contracts.mjs`
126
+ validates every contract file offline. It fails any contract that already passes on an untouched
127
+ fixture, because such a contract is measuring nothing.
128
+ - **Tests**: `npm test` and `python -m unittest discover -s tests` run offline and spend no quota; CI
129
+ runs both.
130
+
131
+ Question sets are cached in `.skillgauntlet/queries-<per-clause>x<negatives>.json` next to the report
132
+ and reused while the skill's SKILL.md is unchanged, so re-running a skill does not pay for drafting
133
+ again. Editing the description invalidates the cache, which is exactly when fresh questions are needed.
134
+
135
+ ## Hosts and models
136
+
137
+ | Host | Layer 0 | Trigger rate (layer 1) | Gain (layer 2) | What it spends |
138
+ |---|---|---|---|---|
139
+ | Claude Code | yes | yes | yes | Claude plan quota, or an API key; DeepSeek via `ANTHROPIC_BASE_URL` |
140
+ | CodeBuddy Code | yes | yes | no | the CodeBuddy account's quota |
141
+ | Codewhale | yes | yes | no | DeepSeek API cash (`DEEPSEEK_API_KEY`) |
142
+ | Codex | yes | **no** (not observable) | no; activation probe instead | the ChatGPT plan's quota |
143
+
144
+ A trigger rate is a number for one host and one model. Numbers from two hosts are never merged or
145
+ ranked against each other.
146
+
147
+ Layer 0 is host-agnostic: it reads a skill directory, so it works for a skill installed by any host.
148
+
149
+ Layer 1 drives a CLI, so it measures that CLI's host. The model is whatever `--model` resolves to under
150
+ your credentials: the plan's aliases on a subscription, any model id on an API key. A non-Anthropic
151
+ backend works through `ANTHROPIC_BASE_URL`; DeepSeek's endpoint needs an API key, because there is no
152
+ login it could reuse.
153
+
154
+ **CodeBuddy Code** (the command line behind Tencent's WorkBuddy) is a second host with a measurable trigger rate: a skill call appears in its stream as a `tool_use` named `Skill`, the same shape as in Claude Code, which was confirmed on a live run. It spends the quota of its own account (log in once with `/login` inside `codebuddy`), runs the trigger layer only, and is launched with a restricted tool list because its default one has 60+ tools. A rate measured here is a CodeBuddy number and is never merged with a Claude Code one.
155
+
156
+ **Codewhale** (formerly DeepSeek-TUI, runs DeepSeek models) is a third host with a measurable trigger rate. It reads a skill through a `load_skill` tool, so the first `load_skill` call whose `input.name` is the tested skill counts as a trigger; a search (`input.query`) or a catalogue listing does not. Trials run in a throw-away `HOME` that holds only the tested skill, with `load_skill` as the only tool (its `--auto` mode has no execution sandbox on Windows). It needs `codewhale` on `PATH` (the single exe from the project's release page, renamed `codewhale.exe`) and `DEEPSEEK_API_KEY` in the environment. A rate measured here is a Codewhale number and is never merged with another host's.
157
+
158
+ **Codex is supported for what it exposes, which is a smaller surface:**
159
+
160
+ | Codex emits | Codex does not emit |
161
+ |---|---|
162
+ | `thread.started`, `turn.started`, `turn.completed`, `turn.failed`, `error` | any skill item |
163
+ | `item.started/updated/completed` carrying `command_execution`, `mcp_tool_call`, `file_change`, `todo_list`, `agent_message`, `user_message`, `agent_reasoning`, `error` | a "skill was used" event |
164
+
165
+ That schema was confirmed against a live run (codex-cli 0.159.2, ChatGPT account), which also showed
166
+ two traps worth knowing: with `--sandbox read-only` every `exec_command` is refused by policy, so a
167
+ probe needs `workspace-write`; and without `--ignore-user-config` a stale model id in
168
+ `~/.codex/config.toml` fails every turn for reasons that have nothing to do with the skill.
169
+
170
+ A skill in Codex is host-side context: selected and injected, not called as a tool. `skills_used` exists
171
+ only in the telemetry profile (`unique_skills_used`, `total_skills_used`), never in the stream. So a
172
+ trigger rate cannot be measured here, and reporting one would mean inventing it. What is measurable is
173
+ whether the agent acted and what it changed — which is the **activation probe**: the same request with
174
+ and without the skill, comparing the first action and the changed files. That is evidence of influence,
175
+ not of triggering, and the report labels it that way.
176
+
177
+ The probe path is exercised end to end: two runs of the same request on a task that must produce
178
+ files, one with the skill installed and one without. It reports facts — the first action, the files
179
+ each side produced, and whether those match — and deliberately gives **no influenced/not-influenced
180
+ verdict**. Two runs of the same request never execute identical command strings, so "the action
181
+ differs" is true almost always and would decide nothing.
182
+
183
+ Two things the probe taught us, both now baked in: the skill is installed only into `.agents/skills`,
184
+ because a `.codex/skills` copy in the workspace changed the sandbox outcome of one side and turned the
185
+ comparison into a false positive; and `file_change` items only appear for patch-style edits, so the
186
+ record of what changed comes from a filesystem diff rather than from the stream.
187
+
188
+ ## Method principles
189
+
190
+ - Trigger detection follows Anthropic's skill-creator trigger eval: the model's first tool decision decides.
191
+ - "Answered without calling any tool" is counted apart from "called another tool first". On a backend
192
+ with weaker tool-call adherence that difference decides whether the model or the description is at fault.
193
+ - Each skill is tested with **two or more independently AI-drafted question sets**, grouped by the trigger
194
+ clauses in its description. Results are reported per clause and per set, with the **spread between
195
+ sets**; skills whose sets disagree are flagged.
196
+ - Question sets are not reviewed by hand, and neither are grades, including low ones. Independent sets and
197
+ a published spread make results checkable without a reviewer, and a reviewer's own judgement would be the
198
+ one part of the method nobody could reproduce. Mistakes are corrected through public appeals instead
199
+ (see [CONTRIBUTING.md](CONTRIBUTING.md)). Reports say plainly that they are automated results under stated
200
+ conditions.
201
+ - **Negatives must borrow wording, and the claim is checked.** The drafter has to name a fragment of its
202
+ own request that carries the borrowed wording, and the runner warns when it cannot. Without that, a
203
+ drafter writes negatives from a different domain, they never trigger, and the false-positive rate comes
204
+ out at zero for reasons that have nothing to do with the skill -- which is the one finding the report
205
+ is supposed to deliver. This rule is in the CLI. The published 2026-10-28 batches were drafted by the
206
+ Python runner, whose prompt was kept unchanged so earlier batches stay comparable, so their
207
+ false-positive rates are labelled as measured with weak negatives.
208
+ - Coarse grades only, with confidence intervals computed over **queries** (the independent unit), not
209
+ over trials: three runs of one query are not three independent observations.
210
+ - Every result is pinned on four dimensions: skill version (commit plus SKILL.md hash), host version,
211
+ model version and question-set version. A backend other than Anthropic is recorded too.
212
+ - Raw per-trial records and the question sets are published alongside each report so anyone can
213
+ reproduce it, and anyone can point out a bad question in an Issue.
214
+
215
+ ## Deeper material
216
+
217
+ - [`step0/data/OVERVIEW-2026-10-28.md`](step0/data/OVERVIEW-2026-10-28.md): the step 0 results in one page.
218
+ - [`step0/README.md`](step0/README.md): the Python trigger-test runner (commands, verdict rules,
219
+ isolation).
220
+ - [`step0/batch_tables.py`](step0/batch_tables.py): recounts every table of the 2026-10-28 reports from the
221
+ raw records.
222
+ - [`step0/experiments/qset-tdd/EXPERIMENT.md`](step0/experiments/qset-tdd/EXPERIMENT.md): how much results
223
+ depend on the question set, and why sets are not reviewed by hand.
224
+ - [`SECURITY.md`](SECURITY.md): what the runner executes, what it isolates and what it does not.
225
+
226
+ ## License
227
+
228
+ | Content | License |
229
+ |---|---|
230
+ | Code (runner, scripts) | [Apache-2.0](LICENSE) |
231
+ | Data (`step0/queries/` question packs, test results and reports) | [CC BY-NC-SA 4.0](LICENSE-DATA) |
232
+
233
+ The data is free forever for personal and non-commercial use; for commercial use, contact the maintainers for a separate license. The source code of the skills under test is not in this repository; the runner fetches it from each upstream repository at run time, and copyright stays with the original authors.
234
+
235
+ ## Contributing
236
+
237
+ Issues and appeals are open to everyone. Pull requests need a signed Contributor License Agreement; see
238
+ [CONTRIBUTING.md](CONTRIBUTING.md).