skilldrop-cli 1.4.0 → 1.6.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 +8 -7
- package/bin/skilldrop.js +15 -10
- package/catalogue.json +13 -2
- package/contracts/catalogue.schema.json +2 -1
- package/model-routing.json +12 -8
- package/package.json +1 -1
- package/packs/ai-engineering/skills/judge-audit/SKILL.md +28 -11
- package/packs/ai-engineering/skills/judge-audit/evals/evals.json +30 -0
- package/packs/ai-engineering/skills/judge-audit/evals/files/12/judge_runs.csv +241 -0
- package/packs/ai-engineering/skills/judge-audit/evals/files/12/rosa_labels.csv +33 -0
- package/packs/ai-engineering/skills/judge-audit/evals/files/13/moderation_eval.csv +601 -0
- package/packs/ai-engineering/skills/judge-audit/manifest.json +2 -2
- package/packs/ai-engineering/skills/mcp-pairing/manifest.json +1 -1
- package/packs/ai-engineering/skills/mcp-pairing/reference.md +4 -3
- package/packs/ai-engineering/skills/subagent-design/SKILL.md +1 -0
- package/packs/ai-engineering/skills/subagent-design/examples/help-center-localization.md +146 -0
- package/packs/ai-engineering/skills/subagent-design/manifest.json +2 -2
- package/packs/api-builder/skills/prompt-caching-advisor/SKILL.md +4 -0
- package/packs/api-builder/skills/prompt-caching-advisor/examples/support-bot-block-order.md +120 -0
- package/packs/api-builder/skills/prompt-caching-advisor/manifest.json +2 -2
- package/packs/civil-architect/pack.json +60 -0
- package/packs/civil-architect/skills/floor-plan-layout/SKILL.md +103 -0
- package/packs/civil-architect/skills/floor-plan-layout/evals/eval_queries.json +30 -0
- package/packs/civil-architect/skills/floor-plan-layout/evals/evals.json +57 -0
- package/packs/civil-architect/skills/floor-plan-layout/evals/files/4/adu-programme.md +12 -0
- package/packs/civil-architect/skills/floor-plan-layout/examples/ground-floor.md +65 -0
- package/packs/civil-architect/skills/floor-plan-layout/examples/ground-floor.svg +135 -0
- package/packs/civil-architect/skills/floor-plan-layout/manifest.json +34 -0
- package/packs/civil-architect/skills/floor-plan-layout/scripts/plan_check.py +449 -0
- package/packs/civil-architect/skills/floor-plan-layout/templates/plan.json +38 -0
- package/packs/dev-team/loops/release/LOOP.md +4 -4
- package/packs/dev-team/loops/release/loop.json +1 -1
- package/packs/dev-team/skills/bug-triage/SKILL.md +1 -0
- package/packs/dev-team/skills/bug-triage/examples/export-row-limit-escalation.md +126 -0
- package/packs/dev-team/skills/bug-triage/manifest.json +2 -2
- package/packs/product-manager/skills/prd-draft/SKILL.md +1 -0
- package/packs/product-manager/skills/prd-draft/examples/approver-delay-not-slack.md +142 -0
- package/packs/product-manager/skills/prd-draft/manifest.json +2 -2
- package/profiles.json +1 -1
- package/packs/ai-engineering/loops/adopt/LOOP.md +0 -120
- package/packs/ai-engineering/loops/adopt/evals/eval_queries.json +0 -10
- package/packs/ai-engineering/loops/adopt/evals/evals.json +0 -69
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-first-wave-to-sign-off/ai-ideas.md +0 -15
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-first-wave-to-sign-off/org-context.md +0 -27
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-first-wave-to-sign-off/staff-survey.csv +0 -11
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-sponsor-slice-blocked-by-client-data/ai-ideas.md +0 -13
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-sponsor-slice-blocked-by-client-data/firm-context.md +0 -23
- package/packs/ai-engineering/loops/adopt/loop.json +0 -53
- package/packs/career/loops/apply/LOOP.md +0 -97
- package/packs/career/loops/apply/evals/eval_queries.json +0 -9
- package/packs/career/loops/apply/evals/evals.json +0 -55
- package/packs/career/loops/apply/evals/files/apply-candidate-decided-full-run/application-form.md +0 -10
- package/packs/career/loops/apply/evals/files/apply-candidate-decided-full-run/job-posting.md +0 -33
- package/packs/career/loops/apply/evals/files/apply-candidate-decided-full-run/resume.md +0 -34
- package/packs/career/loops/apply/evals/files/apply-fit-gate-hard-requirement/cv.md +0 -27
- package/packs/career/loops/apply/evals/files/apply-fit-gate-hard-requirement/warehouse-supervisor.md +0 -30
- package/packs/career/loops/apply/loop.json +0 -52
- package/packs/product-manager/loops/discover/LOOP.md +0 -82
- package/packs/product-manager/loops/discover/evals/eval_queries.json +0 -30
- package/packs/product-manager/loops/discover/evals/evals.json +0 -54
- package/packs/product-manager/loops/discover/evals/files/discover-no-show-signal/interview-notes.md +0 -63
- package/packs/product-manager/loops/discover/evals/files/discover-no-show-signal/support-tickets.csv +0 -13
- package/packs/product-manager/loops/discover/evals/files/discover-vp-loyalty-no-evidence/vp-message.txt +0 -13
- package/packs/product-manager/loops/discover/loop.json +0 -41
- package/packs/sre-oncall/loops/operate/LOOP.md +0 -84
- package/packs/sre-oncall/loops/operate/evals/eval_queries.json +0 -30
- package/packs/sre-oncall/loops/operate/evals/evals.json +0 -53
- package/packs/sre-oncall/loops/operate/evals/files/operate-export-service-first-outage/alerts.log +0 -22
- package/packs/sre-oncall/loops/operate/evals/files/operate-export-service-first-outage/incident-chat.txt +0 -27
- package/packs/sre-oncall/loops/operate/evals/files/operate-export-service-first-outage/service-notes.md +0 -46
- package/packs/sre-oncall/loops/operate/evals/files/operate-incident-still-open/oncall-log.txt +0 -17
- package/packs/sre-oncall/loops/operate/evals/files/operate-incident-still-open/runbook-webhooks.md +0 -38
- package/packs/sre-oncall/loops/operate/loop.json +0 -41
package/README.md
CHANGED
|
@@ -25,12 +25,12 @@ Both blind judges picked the skill's answer: *"A keeps each comment to a single
|
|
|
25
25
|
|
|
26
26
|
## The receipts
|
|
27
27
|
|
|
28
|
-
Every skill runs as a real agent session twice: once with the skill, once without. The results are [published either way](https://sananthanarayan.github.io/skilldrop/evals/). In the
|
|
28
|
+
Every skill runs as a real agent session twice: once with the skill, once without. The results are [published either way](https://sananthanarayan.github.io/skilldrop/evals/). In the latest run (5 November 2026: 111 skills, 300 held-out evals written blind from each skill's description, `claude-sonnet-5-5`, scripts free to run):
|
|
29
29
|
|
|
30
|
-
- **With a skill, answers met
|
|
31
|
-
- **Two blind judges preferred the skill's answer in
|
|
32
|
-
- **
|
|
33
|
-
- **
|
|
30
|
+
- **With a skill, answers met 84% of their checks; without one, 76%.**
|
|
31
|
+
- **Two blind judges preferred the skill's answer in 44% and 42% of pairs.** Each judge saw only the request and both answers, in shuffled order. Skills that ship a script came out slightly ahead of the plain agent (52%); skills that are instructions alone lost about two pairs in three ([what the benchmark showed](guides/explanation/what-the-benchmark-showed.md#a-new-baseline-with-scripts-free-to-run)).
|
|
32
|
+
- **Loops are measured against their own skills, used without the loop.** Three are clearly ahead of both their skills and the plain agent: [`release`](packs/dev-team/loops/release/LOOP.md), [`modernize`](packs/dev-team/loops/modernize/LOOP.md) and [`ship-agent`](packs/ai-engineering/loops/ship-agent/LOOP.md). Start there: `npx skilldrop-cli install --loop release`. Four loops that lost to their own skills were retired ([RFC-0074](docs/rfcs/0074-loops-measured-four-retired.md)).
|
|
33
|
+
- **Ten skills and four loops that didn't beat the alternative were [retired](https://sananthanarayan.github.io/skilldrop/evals/#retired)**, and they're listed. Each new skill has to win on held-out evals before it ships.
|
|
34
34
|
|
|
35
35
|
[Get started](https://sananthanarayan.github.io/skilldrop/start/) · [Browse the packs](https://sananthanarayan.github.io/skilldrop/packs/) · [Search all skills](https://sananthanarayan.github.io/skilldrop/catalogue/) · [Docs](https://sananthanarayan.github.io/skilldrop/docs/) · [What stays stable in 1.x](guides/reference/versioning-and-stability.md) · [Contribute](CONTRIBUTING.md)
|
|
36
36
|
|
|
@@ -51,7 +51,7 @@ A good result runs your lint, typecheck and tests through a gate script, then a
|
|
|
51
51
|
In Claude Code you can use the plugin marketplace instead: run `/plugin marketplace add sananthanarayan/skilldrop`, then `/plugin install dev-team@skilldrop`. [Every install route](guides/how-to/install.md) covers single skills, other IDEs, loops, reviewer subagents, profiles and updates.
|
|
52
52
|
|
|
53
53
|
<details>
|
|
54
|
-
<summary><b>Choose your role:</b>
|
|
54
|
+
<summary><b>Choose your role:</b> 20 packs, from product management and architecture to SRE, GRC, job applications and building design</summary>
|
|
55
55
|
|
|
56
56
|
Install one pack. Every role pack also brings `core` (intake, critique, review council, output hygiene, and the decisions behind a codebase). Each pack page has a starter prompt to paste and says what a good result looks like.
|
|
57
57
|
|
|
@@ -73,6 +73,7 @@ Install one pack. Every role pack also brings `core` (intake, critique, review c
|
|
|
73
73
|
- **Frontend:** `frontend` — what makes a page slow for real users, what makes a bundle heavy, and how each route should be rendered. [Open pack](https://sananthanarayan.github.io/skilldrop/packs/frontend/)
|
|
74
74
|
- **Writing agent skills:** `skill-engineering` — author a portable skill with evals, and review one before it ships. [Open pack](https://sananthanarayan.github.io/skilldrop/packs/skill-engineering/)
|
|
75
75
|
- **Applying for a job:** `career` — an honest fit check against the posting, a tailored resume and cover letter that claim nothing you didn't, and the application form's answers. [Open pack](https://sananthanarayan.github.io/skilldrop/packs/career/)
|
|
76
|
+
- **Designing buildings:** `civil-architect` — a dimensioned concept floor plan from a room list and a footprint, checked for overlapping rooms, doors on no wall and rooms no one can reach. [Open pack](https://sananthanarayan.github.io/skilldrop/packs/civil-architect/)
|
|
76
77
|
- **Everyone:** `core` on its own. [Open pack](https://sananthanarayan.github.io/skilldrop/packs/core/)
|
|
77
78
|
|
|
78
79
|
</details>
|
|
@@ -80,7 +81,7 @@ Install one pack. Every role pack also brings `core` (intake, critique, review c
|
|
|
80
81
|
## How it works
|
|
81
82
|
|
|
82
83
|
- **A skill produces one file you own.** Each ships a quality bar, named anti-patterns and acceptance evals, so the output is an artifact, not a conversation. See [every skill, by category](guides/reference/skill-catalogue.md).
|
|
83
|
-
- **Loops order skills, and a gate decides when work moves on.**
|
|
84
|
+
- **Loops order skills, and a gate decides when work moves on.** Loops cover three lifecycle stages (`design`, `build`, `release`), plus the `ship-a-draft` wrapper for any document and loops for jobs beside it, such as `research`, `comply`, `ship-agent` for an AI agent and `provision` for a Terraform change. Every loop is measured against its own skills used without it; four that lost were retired. Each gate is a script, a review panel or a person, chosen by how expensive the mistake is to undo. See [the operating model](guides/explanation/operating-model.md) for every stage and gate on one page, [the loops, stage by stage](guides/reference/loops.md), and [why loops](guides/explanation/loops.md).
|
|
84
85
|
- **Measured, not asserted.** `run_bench.py` runs each acceptance eval with the skill and without it, in a sandbox, and reports the lift, a blind preference from two judges, and the cost per run. The results are published whether or not they flatter the skills. See [how skills are checked](https://sananthanarayan.github.io/skilldrop/evals/) and [RFC-0040](docs/rfcs/0040-skill-benchmark.md).
|
|
85
86
|
- **Copy, never transform.** A skill is a plain `SKILL.md` folder in the [Agent Skills](https://agentskills.io) format, at `packs/<pack>/skills/<name>/`. What runs in your agent is byte-identical to what is reviewed here. There is no runtime, and the tooling has zero dependencies.
|
|
86
87
|
- **Updates keep your edits.** `npx skilldrop-cli update` replaces files you haven't touched. For any file you changed, it leaves the new version beside it as `<file>.upstream`. See [upgrade installed skills](guides/how-to/upgrade-skills.md).
|
package/bin/skilldrop.js
CHANGED
|
@@ -264,11 +264,16 @@ function readPacksCatalog(dir, source) {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
/* RFC-0046: a skill that left the catalogue keeps a record in catalogue.json `retired`, so an
|
|
267
|
-
installed copy can say why it stopped updating instead of looking like an unreachable source.
|
|
268
|
-
|
|
267
|
+
installed copy can say why it stopped updating instead of looking like an unreachable source.
|
|
268
|
+
RFC-0074: a loop can be retired too; its record says "kind": "loop". `isLoop` picks the kind
|
|
269
|
+
the caller is asking about; left out, a record of either kind answers (search). */
|
|
270
|
+
function retiredNote(cat, s, isLoop) {
|
|
269
271
|
const r = cat && cat.retired && cat.retired[s];
|
|
270
272
|
if (!r) return null;
|
|
271
|
-
|
|
273
|
+
const kind = r.kind || "skill";
|
|
274
|
+
if (isLoop !== undefined && kind !== (isLoop ? "loop" : "skill")) return null;
|
|
275
|
+
const what = kind === "loop" ? `The loop '${s}'` : `'${s}'`;
|
|
276
|
+
return `${what} was retired in ${r.in}: ${r.why}` + (r.instead ? ` Use ${r.instead} instead.` : "");
|
|
272
277
|
}
|
|
273
278
|
|
|
274
279
|
/* Minimal TOML read — the [pack] table's basic-string scalars (name, version, description).
|
|
@@ -1225,7 +1230,7 @@ function expandNames(args, cat) {
|
|
|
1225
1230
|
return packMembers(ps, args.flags.pack, "skills");
|
|
1226
1231
|
}
|
|
1227
1232
|
if (!args._.length) die("nothing to install — pass skill names, --pack <name>, or --all");
|
|
1228
|
-
for (const s of args._) if (!skillExists(cat, s)) die(retiredNote(cat, s) || `unknown skill '${s}' in catalog '${cat.source}'`);
|
|
1233
|
+
for (const s of args._) if (!skillExists(cat, s)) die(retiredNote(cat, s, false) || `unknown skill '${s}' in catalog '${cat.source}'`);
|
|
1229
1234
|
return args._.slice();
|
|
1230
1235
|
}
|
|
1231
1236
|
|
|
@@ -1567,7 +1572,7 @@ function installedRows(flags) {
|
|
|
1567
1572
|
const loop = isLoopEntry(entry);
|
|
1568
1573
|
try {
|
|
1569
1574
|
cat = resolveCatalog(src === BUNDLED ? undefined : src);
|
|
1570
|
-
if (!
|
|
1575
|
+
if (!unitExists(cat, s, loop)) retired = retiredNote(cat, s, loop);
|
|
1571
1576
|
if (unitExists(cat, s, loop)) {
|
|
1572
1577
|
current = unitMeta(cat, s, loop).version || null;
|
|
1573
1578
|
// Same version, different files: the catalog changed the skill without bumping it.
|
|
@@ -1711,7 +1716,7 @@ function outdated(args) {
|
|
|
1711
1716
|
console.log(`\n${drift.length} skill(s) changed upstream with the same version. Read the change first (skilldrop diff <skill>),` +
|
|
1712
1717
|
`\nthen take it with: skilldrop update --changed`);
|
|
1713
1718
|
if (gone.length)
|
|
1714
|
-
console.log(`\n${gone.length} retired skill(s) will not update. Keep them as they are, or remove them: skilldrop uninstall ${gone.map((r) => r.s).join(" ")}${targetHint(args.flags)}`);
|
|
1719
|
+
console.log(`\n${gone.length} retired skill(s) or loop(s) will not update. Keep them as they are, or remove them: skilldrop uninstall ${gone.map((r) => r.s).join(" ")}${targetHint(args.flags)}`);
|
|
1715
1720
|
console.log(stale.length ? `\n${stale.length} outdated — run: skilldrop update` : (drift.length || gone.length ? "" : "everything up to date."));
|
|
1716
1721
|
}
|
|
1717
1722
|
|
|
@@ -1767,7 +1772,7 @@ function diff(args) {
|
|
|
1767
1772
|
const loop = isLoopEntry(entry);
|
|
1768
1773
|
const src = args.flags.from || (entry ? lsrc(entry) : BUNDLED);
|
|
1769
1774
|
const cat = resolveCatalog(src === BUNDLED ? undefined : src);
|
|
1770
|
-
if (!unitExists(cat, s, loop)) die(
|
|
1775
|
+
if (!unitExists(cat, s, loop)) die(retiredNote(cat, s, loop) || `'${s}' is no longer in catalog '${cat.source}'`);
|
|
1771
1776
|
const theirs = unitHashes(cat, s, loop), mine = fileHashes(path.join(dest, s));
|
|
1772
1777
|
const base = (entry && entry.files) || {};
|
|
1773
1778
|
const changed = Object.keys(theirs).filter((f) => f in mine && mine[f] !== theirs[f]).sort();
|
|
@@ -1811,7 +1816,7 @@ function doctor(args) {
|
|
|
1811
1816
|
else try { data = JSON.parse(raw); } catch (e) { add("error", `${lp} is not valid JSON`, "fix or delete it; skilldrop can't track updates until then"); }
|
|
1812
1817
|
const names = Object.keys(data);
|
|
1813
1818
|
for (const n of names) {
|
|
1814
|
-
const note =
|
|
1819
|
+
const note = lsrc(data[n]) === BUNDLED && retiredNote(resolveCatalog(), n, isLoopEntry(data[n]));
|
|
1815
1820
|
if (note) add("warn", note, `skilldrop uninstall ${n}${targetHint(args.flags)}, or keep it as it is; it will not update`);
|
|
1816
1821
|
if (!fs.existsSync(path.join(dest, n))) add("error", `${n} is in the ledger but its folder is gone`, `skilldrop install ${n} (or uninstall ${n} to drop the record)`);
|
|
1817
1822
|
else if (!data[n].file) {
|
|
@@ -2293,7 +2298,7 @@ function installLoops(args) {
|
|
|
2293
2298
|
}
|
|
2294
2299
|
if (!names.length && args.flags.all) names = available.slice();
|
|
2295
2300
|
if (!names.length) die("nothing to install — pass loop names, --pack <name>, or --all");
|
|
2296
|
-
for (const n of names) if (!available.includes(n)) die(`unknown loop '${n}' in catalog '${cat.source}'`);
|
|
2301
|
+
for (const n of names) if (!available.includes(n)) die(retiredNote(cat, n, true) || `unknown loop '${n}' in catalog '${cat.source}'`);
|
|
2297
2302
|
|
|
2298
2303
|
let bad = 0;
|
|
2299
2304
|
for (const n of names) {
|
|
@@ -2569,7 +2574,7 @@ function info(args) {
|
|
|
2569
2574
|
if (args.flags.pack) return infoPack(args);
|
|
2570
2575
|
const cat = resolveCatalog(args.flags.from);
|
|
2571
2576
|
const s = args._[0] || die("pass a skill name, or --pack <name>");
|
|
2572
|
-
if (!skillExists(cat, s)) die(retiredNote(cat, s) || `unknown skill '${s}' in catalog '${cat.source}'`);
|
|
2577
|
+
if (!skillExists(cat, s)) die(retiredNote(cat, s, false) || `unknown skill '${s}' in catalog '${cat.source}'`);
|
|
2573
2578
|
const m = manifestOf(cat, s);
|
|
2574
2579
|
const ps = packsOf(cat) || {};
|
|
2575
2580
|
const inPacks = Object.entries(ps).filter(([, p]) => p.skills.includes(s)).map(([n]) => n);
|
package/catalogue.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "RFC-0034. The catalogue index: pack display order and the outcome browse axis (RFC-0026). Pack metadata lives in packs/<pack>/pack.json; membership is the folders — a skill is in a pack because it sits at packs/<pack>/skills/<name>/.",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"packs": ["core", "solution-architect", "product-manager", "dev-team", "sre-oncall", "stakeholder-comms", "design", "ai-engineering", "api-builder", "converters", "experience-design", "research", "trackers", "data-analytics", "grc", "infra-as-code", "frontend", "skill-engineering", "career"],
|
|
4
|
+
"packs": ["core", "solution-architect", "product-manager", "dev-team", "sre-oncall", "stakeholder-comms", "design", "ai-engineering", "api-builder", "converters", "experience-design", "research", "trackers", "data-analytics", "grc", "infra-as-code", "frontend", "skill-engineering", "career", "civil-architect"],
|
|
5
5
|
"outcomes": {
|
|
6
6
|
"decide-what-to-build": {
|
|
7
7
|
"for": "Product managers · founders · strategists",
|
|
@@ -205,6 +205,13 @@
|
|
|
205
205
|
"cover-letter",
|
|
206
206
|
"application-form-answers"
|
|
207
207
|
]
|
|
208
|
+
},
|
|
209
|
+
"design-a-building": {
|
|
210
|
+
"for": "Architects · building designers · owners planning a build",
|
|
211
|
+
"description": "Go from a room list and a footprint to a first floor plan: every room at its size, doors on real walls, every room reachable, drawn to scale and checked before anyone sees it.",
|
|
212
|
+
"skills": [
|
|
213
|
+
"floor-plan-layout"
|
|
214
|
+
]
|
|
208
215
|
}
|
|
209
216
|
},
|
|
210
217
|
"retired": {
|
|
@@ -217,6 +224,10 @@
|
|
|
217
224
|
"marketing-flyer": { "in": "1.2.0", "why": "On its held-out evals, in each of two trials and with both blind judges, the agent without it built the whole flyer with placeholders where the skill stopped or used a generic template; it adds no rule the agent breaks." },
|
|
218
225
|
"deck-builder": { "in": "1.2.0", "why": "On its held-out evals the agent without it built the better deck in each of two trials; rebuilt rule-first, with its script able to run, it still lost on fresh evals (judges 2 and 1 of 4; 69% of checks against 81%).", "instead": "md-to-pptx" },
|
|
219
226
|
"ai-usage-report": { "in": "1.4.0", "why": "On its held-out evals, over three trials and with both blind judges, the agent without it made the better report: it kept every rule the skill teaches (counts show activity, not quality; missing data is not zero; no leaderboard), while the skill refused to rank when asked, hid names the manager had supplied, and its script read neither eval's export." },
|
|
220
|
-
"lean-canvas": { "in": "1.4.0", "why": "On its held-out evals, in each of three trials and with both blind judges, the agent without it made the better canvas: it caught the same errors and went further, while the skill's lead on checks came from its own format and its script's break-even left out the cost of replacing lost customers.", "instead": "business-case" }
|
|
227
|
+
"lean-canvas": { "in": "1.4.0", "why": "On its held-out evals, in each of three trials and with both blind judges, the agent without it made the better canvas: it caught the same errors and went further, while the skill's lead on checks came from its own format and its script's break-even left out the cost of replacing lost customers.", "instead": "business-case" },
|
|
228
|
+
"adopt": { "in": "1.5.0", "kind": "loop", "why": "On its held-out evals its own four skills, installed without the loop, were preferred in every pair by both blind judges: the loop narrowed the policy to the first use case when the team had no rules at all, its gate swapped out the use case the sponsor had chosen, and its reply carried gate jargon. Install ai-use-case-triage, ai-readiness-assessment, ai-usage-policy and ai-adoption-rollout and run them in the pack's order." },
|
|
229
|
+
"apply": { "in": "1.5.0", "kind": "loop", "why": "On its held-out evals its own skills, installed without the loop, were preferred in every pair by both blind judges: its fit gate stopped before writing anything even when the candidate had already decided to apply, and its confirm gate left form answers blank. Use job-fit-analysis to decide, then resume-tailor, cover-letter and application-form-answers." },
|
|
230
|
+
"discover": { "in": "1.5.0", "kind": "loop", "why": "On its held-out evals the plain agent was preferred in every pair and its own skills in three of four: its ratification gate refused to record an approval the requester had already given, and its reply carried gate jargon. Use feedback-synthesis on raw signal, then prd-draft." },
|
|
231
|
+
"operate": { "in": "1.5.0", "kind": "loop", "why": "On its held-out evals its own skills, installed without the loop, were preferred in every pair by both blind judges: the skills already link instrumentation, runbook, comms and postmortem, and the loop added gate jargon and broke its own one rule. Use observability-plan, runbook-generator, incident-comms and postmortem-generator in that order." }
|
|
221
232
|
}
|
|
222
233
|
}
|
|
@@ -31,13 +31,14 @@
|
|
|
31
31
|
},
|
|
32
32
|
"retired": {
|
|
33
33
|
"type": "object",
|
|
34
|
-
"description": "RFC-0046. Skills removed from the catalogue, so an installed copy can say why it stopped updating. A retired name has no folder and nothing references it; validate.py checks both.",
|
|
34
|
+
"description": "RFC-0046. Skills (and, RFC-0074, loops) removed from the catalogue, so an installed copy can say why it stopped updating. A retired name has no folder and nothing references it; validate.py checks both.",
|
|
35
35
|
"additionalProperties": {
|
|
36
36
|
"type": "object",
|
|
37
37
|
"additionalProperties": false,
|
|
38
38
|
"required": ["in", "why"],
|
|
39
39
|
"properties": {
|
|
40
40
|
"in": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$", "description": "The skilldrop-cli version that removed it." },
|
|
41
|
+
"kind": { "enum": ["skill", "loop"], "description": "RFC-0074. What was retired; a record without it is a skill." },
|
|
41
42
|
"why": { "type": "string", "description": "One sentence, shown by outdated, update, doctor, diff, info and install." },
|
|
42
43
|
"instead": { "type": "string", "description": "A skill that covers the same job, when one does. Omit it when the agent without a skill does as well." }
|
|
43
44
|
}
|
package/model-routing.json
CHANGED
|
@@ -183,8 +183,8 @@
|
|
|
183
183
|
"rationale": "Extraction + tagging [explicit]/[implied]/[inferred]. The tagging needs care — above light, below heavy."
|
|
184
184
|
},
|
|
185
185
|
"bug-triage": {
|
|
186
|
-
"tier": "
|
|
187
|
-
"rationale": "
|
|
186
|
+
"tier": "heavy",
|
|
187
|
+
"rationale": "Measured (RFC-0073): on its held-out evals the heavy tier met 92% and 92% of checks in two tier trials, against standard's 76% and light's 70% and 86%, more than 5 points ahead both times; moved once its examples/ oracle shipped (RFC-0074)."
|
|
188
188
|
},
|
|
189
189
|
"bundle-size-review": {
|
|
190
190
|
"tier": "standard",
|
|
@@ -287,6 +287,10 @@
|
|
|
287
287
|
"tier": "light",
|
|
288
288
|
"rationale": "A deterministic stdlib script does the extraction; the model runs it, relays the dropped-content report and hands off. No generation beyond a short summary of losses."
|
|
289
289
|
},
|
|
290
|
+
"floor-plan-layout": {
|
|
291
|
+
"tier": "heavy",
|
|
292
|
+
"rationale": "Spatial layout is design judgment: zoning, adjacencies, daylight and circulation traded against areas, with a checker to iterate against."
|
|
293
|
+
},
|
|
290
294
|
"guide-builder": {
|
|
291
295
|
"tier": "standard",
|
|
292
296
|
"rationale": "Shapes notes into a guide without adding to them. Generation, not adversarial review."
|
|
@@ -372,8 +376,8 @@
|
|
|
372
376
|
"rationale": "Measured (RFC-0073): on its held-out evals the light tier met 85% and 85% of checks in two tier trials, against standard's 85% and heavy's 77% and 85%, within 5 points of the best both times."
|
|
373
377
|
},
|
|
374
378
|
"prd-draft": {
|
|
375
|
-
"tier": "
|
|
376
|
-
"rationale": "
|
|
379
|
+
"tier": "heavy",
|
|
380
|
+
"rationale": "Measured (RFC-0073): on its held-out evals the heavy tier met 85% and 76% of checks in two tier trials, against standard's 68% and light's 68% and 68%, more than 5 points ahead both times; moved once its examples/ oracle shipped (RFC-0074)."
|
|
377
381
|
},
|
|
378
382
|
"pre-merge-review": {
|
|
379
383
|
"tier": "light",
|
|
@@ -384,8 +388,8 @@
|
|
|
384
388
|
"rationale": "Synthesizes a press release and FAQs from a product concept against a fixed format. The specificity discipline needs care but the template bounds it; escalate via ambiguous-input when the concept itself is contested."
|
|
385
389
|
},
|
|
386
390
|
"prompt-caching-advisor": {
|
|
387
|
-
"tier": "
|
|
388
|
-
"rationale": "
|
|
391
|
+
"tier": "heavy",
|
|
392
|
+
"rationale": "Measured (RFC-0073): on its held-out evals the heavy tier met 90% and 90% of checks in two tier trials, against standard's 63% and light's 83% and 73%, more than 5 points ahead both times; moved once its examples/ oracle shipped (RFC-0074)."
|
|
389
393
|
},
|
|
390
394
|
"refactor-plan": {
|
|
391
395
|
"tier": "standard",
|
|
@@ -480,8 +484,8 @@
|
|
|
480
484
|
"rationale": "Framework selection plus evidenced multi-factor judgment ending in a ranked, committal verdict. Cheaper models fill cells with generic filler, skip the TOWS crossings, and refuse to take a side. Never downgrade."
|
|
481
485
|
},
|
|
482
486
|
"subagent-design": {
|
|
483
|
-
"tier": "
|
|
484
|
-
"rationale": "
|
|
487
|
+
"tier": "heavy",
|
|
488
|
+
"rationale": "Measured (RFC-0073): on its held-out evals the heavy tier met 100% and 100% of checks in two tier trials, against standard's 86% and light's 85% and 86%, more than 5 points ahead both times; moved once its examples/ oracle shipped (RFC-0074)."
|
|
485
489
|
},
|
|
486
490
|
"success-metrics": {
|
|
487
491
|
"tier": "standard",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skilldrop-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Portable AI-agent skills, measured against the agent without them. ADRs, PRDs, runbooks, decks and reviews, installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Sanjay Ananthanarayan",
|
|
@@ -19,7 +19,10 @@ cases for a skill is `eval-harness-generator`.
|
|
|
19
19
|
- **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
|
|
20
20
|
- **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
|
|
21
21
|
- **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
|
|
22
|
-
- **For this skill
|
|
22
|
+
- **For this skill, three more:**
|
|
23
|
+
- **Every repeated run is its own row, then the flips by item id.** Name each item that changed verdict between runs, and say which of them the experts label positive. A pooled figure over two runs hides the items a decision turns on.
|
|
24
|
+
- **Answer the decision as the user will run it.** Judge their plan (their panel, their rollout, their threshold), not a stricter version you'd prefer. A swap into a three-person panel is judged as that swap.
|
|
25
|
+
- **The pass mark is the user's, never yours. ** Judge the numbers against the gate or criterion the user or their files state; when there is none, say what the numbers do to their decision. A threshold the input doesn't contain ("kappa ≥ 0.6", "n ≥ 100") never decides the answer.
|
|
23
26
|
|
|
24
27
|
1. **Pin the decision, the user's criterion, and the comparison.** Find the decision (rank
|
|
25
28
|
variants, publish a number, gate a release, act on single items) and the criterion the user
|
|
@@ -43,8 +46,10 @@ cases for a skill is `eval-harness-generator`.
|
|
|
43
46
|
Several files are one run each, joined on the item id with columns resolved per file;
|
|
44
47
|
`--gold` reads expert labels from their own file; `--judges` reads one column per judge;
|
|
45
48
|
`--map` renames labels that mean the same; `--col` maps any other column. Given only counts,
|
|
46
|
-
rebuild one row per item and run it anyway
|
|
47
|
-
[`reference.md`](reference.md)
|
|
49
|
+
rebuild one row per item and run it anyway. When the script can't run, for any reason,
|
|
50
|
+
count by hand from the files with the formulas in [`reference.md`](reference.md), show the
|
|
51
|
+
arithmetic, and deliver the same answer. The reply never mentions the script, a tool, an
|
|
52
|
+
approval or how the run was set up.
|
|
48
53
|
|
|
49
54
|
3. **Quote every number from the output, with its subset, run and n.** All-rows and
|
|
50
55
|
labelled-rows figures are different numbers; so are run 1 and run 2. ✅ *"On the 20 items the
|
|
@@ -108,20 +113,28 @@ cases for a skill is `eval-harness-generator`.
|
|
|
108
113
|
spans it). "Which judge can we use" names one: ✅ *"Switch to the mid tier: it is the cheapest
|
|
109
114
|
judge whose error doesn't move with length (bias shift −2 points against a 2.0-point gate);
|
|
110
115
|
the small tier says relevant to 9 of 10 long passages the reviewer rejected."* — ❌ *"None
|
|
111
|
-
can be recommended until 100 more labels exist."* Conditions are actions with an n (label
|
|
112
|
-
|
|
116
|
+
can be recommended until 100 more labels exist."* Conditions are actions with an n (label more long
|
|
117
|
+
passages, sized as below); a small sample widens the interval, it doesn't withhold the answer.
|
|
113
118
|
When the judge in use today also reads *can't tell*, the sample can't certify anyone: compare
|
|
114
119
|
the candidate with the incumbent on the same items (the accuracy difference and its interval).
|
|
120
|
+
**More labels are sized, never stock.** When a condition is "label more", work out how many
|
|
121
|
+
from the interval: the n at which an interval of the width you observed would stop spanning
|
|
122
|
+
the user's bar, with the arithmetic in one line. ✅ *"At 4 of 6 caught, the interval is
|
|
123
|
+
30%–90%; about 40 more violations would narrow it to ±15 points, enough to tell 80% recall
|
|
124
|
+
from 50%."* — ❌ *"Label ~30 more."* When the file lacks a column the condition needs (a
|
|
125
|
+
severity, a timestamp), say so instead of sizing it.
|
|
115
126
|
Kappa bands (Landis–Koch "moderate") appear only as labelled context, never as the reason.
|
|
116
127
|
**One evidence standard for every subgroup.** If 30 cases are too few to clear one segment,
|
|
117
128
|
12 are too few to clear another: give each its interval and decide them by the same rule.
|
|
118
|
-
The headline and the verdict
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
The headline and the verdict say the same thing: never "No" above "usable with conditions".
|
|
130
|
+
Say the verdict in plain words, in sentence case: *trustworthy for this decision*, *usable
|
|
131
|
+
with conditions* or *don't rely on it*. Never in capitals: a shouted verdict reads as alarm,
|
|
132
|
+
not evidence.
|
|
121
133
|
|
|
122
134
|
13. **Write the reply short.** First line: the answer (yes/no, which judge, which arm it
|
|
123
135
|
favours and by how much). Then the two to four numbers behind it, each with its subset and
|
|
124
|
-
run;
|
|
136
|
+
run; with repeated runs, the per-run rows and the flipped item ids; one line on what the
|
|
137
|
+
data can't measure; one next step that fits the user's deadline. No kappa tutorial,
|
|
125
138
|
no tables unless asked. A chat question gets a chat answer. Write only the files the user
|
|
126
139
|
asked for, and delete any scratch files you made.
|
|
127
140
|
|
|
@@ -135,7 +148,7 @@ counts`, because a verdict without them is invented.
|
|
|
135
148
|
|
|
136
149
|
- [`reference.md`](reference.md) — turning the user's gate into the number that answers it, kappa (unweighted, weighted, Fleiss') and Wilson formulas with worked tables, the both-orders protocol, and every input shape the script reads
|
|
137
150
|
- [`scripts/judge_stats.py`](scripts/judge_stats.py) — per-group, per-run and pooled agreement, weighted kappa, rare-class precision and recall, flips joined on item id, position and length bias, `--gate` (stdlib only; `--self-test` checks the maths)
|
|
138
|
-
- [`examples/summary-panel.md`](examples/summary-panel.md) — worked example: a three-judge panel on summary faithfulness, a
|
|
151
|
+
- [`examples/summary-panel.md`](examples/summary-panel.md) — worked example: a three-judge panel on summary faithfulness, a usable-with-conditions verdict
|
|
139
152
|
|
|
140
153
|
## Quality bar
|
|
141
154
|
|
|
@@ -144,7 +157,9 @@ counts`, because a verdict without them is invented.
|
|
|
144
157
|
- **Statistics are stratified by the compared variable** before any pooled figure is quoted.
|
|
145
158
|
- **Ordinal scores get weighted kappa, named as quadratic or linear.**
|
|
146
159
|
- **A rare class gets its count, confusion, recall and precision with intervals,** not accuracy.
|
|
147
|
-
- **Each run is reported on its own,
|
|
160
|
+
- **Each run is reported on its own, then the flipped items by id,** and which of them are positives.
|
|
161
|
+
- **The decision judged is the user's plan,** not a stricter stand-in.
|
|
162
|
+
- **A "label more" condition carries an n worked out from the interval,** never a stock number.
|
|
148
163
|
- **Every number matches the output for the subset and run it is labelled with,** n included.
|
|
149
164
|
- **What the data cannot measure is named,** never estimated.
|
|
150
165
|
|
|
@@ -171,4 +186,6 @@ counts`, because a verdict without them is invented.
|
|
|
171
186
|
- ❌ **Accuracy on a rare class.** 96% when 95% is the always-"fine" score.
|
|
172
187
|
- ❌ **A pooled kappa for a comparison,** or unweighted kappa on a 1–5 scale.
|
|
173
188
|
- ❌ **Position bias stated backwards,** or judgements counted as the unit instead of questions.
|
|
189
|
+
- ❌ **"Label about 30 more."** A number with no arithmetic behind it reads as a guess, because it is one.
|
|
190
|
+
- ❌ **Stopping, or narrating, when a tool won't run.** Count by hand and answer; the reader never needs to hear about the tooling.
|
|
174
191
|
- ❌ **Leading with the stats dump.** The reader asked whether to act; tell them, then show why.
|
|
@@ -160,6 +160,36 @@
|
|
|
160
160
|
"Points out that 'catch most of the really bad stuff' has no number and asks for one or proposes one, and offers a safer interim option, such as using a judge to flag comments into a human review queue instead of removing them automatically.",
|
|
161
161
|
"Invents nothing: every count, comment ID and rate it cites comes from mod_sample_scored.csv or the prompt, with no made-up model names, prices, comment text or extra data."
|
|
162
162
|
]
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": 12,
|
|
166
|
+
"held_out": "2026-11-05",
|
|
167
|
+
"prompt": "We're testing a new system prompt (v2) for our order-support bot against the current one (v1). 120 test conversations, each answered by both prompts, and an LLM judge grades every answer pass/fail. The rule we agreed up front: ship v2 if it beats v1 by at least 5 points. Run 1 came out 83% vs 71%, so a clear yes, but the judge runs at temperature 0.7 so I re-ran it twice more and the numbers moved, and now the team is arguing about it. Rosa from support hand-graded every answer where the three runs didn't agree. Everything is in judge_runs.csv and rosa_labels.csv. Can we ship v2 or not?",
|
|
168
|
+
"assertions": [
|
|
169
|
+
"Reports each of the three runs separately for both prompts: v2 vs v1 at 83.3% vs 70.8%, 73.3% vs 72.5% and 75.0% vs 71.7%, so the gap is +12.5, +0.8 and +3.3 points, and only run 1 clears the 5-point rule",
|
|
170
|
+
"Finds that the flips are lopsided: 24 of 120 v2 answers changed verdict across runs against 8 of 120 v1 answers, so the judge's instability falls mostly on v2",
|
|
171
|
+
"Finds the planted length effect: 22 of the 24 v2 flips are long answers (over about 350 output tokens). 22 of the 40 long v2 answers flipped, against 2 of the 80 short ones",
|
|
172
|
+
"Uses Rosa's labels on the flipped answers: only 7 of the 24 v2 flips pass against 4 of the 8 v1 flips, which gives about 87 vs 86 passes (72.5% vs 71.7%, +0.8 points), well short of the 5-point rule",
|
|
173
|
+
"Does not accept a majority vote as the fix: majority-of-three gives 94 vs 86 (+6.7 points), but Rosa passes only 4 of the 14 v2 flips that the majority calls pass",
|
|
174
|
+
"Notes that on the answers judged the same in all three runs, v1 passes 82 and v2 passes 80, so v2's apparent lead comes entirely from answers the judge cannot decide on",
|
|
175
|
+
"Gives a direct answer that v2 does not meet the agreed 5-point rule on this evidence and should not ship on the strength of run 1, and names a concrete next step, such as fixing the judge's instability on long answers or setting temperature to 0 before re-comparing",
|
|
176
|
+
"Does not invent figures that are not in the files, such as Rosa's verdicts on answers she did not grade or the judge's accuracy on the answers whose verdict never changed"
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": 13,
|
|
181
|
+
"held_out": "2026-11-05",
|
|
182
|
+
"prompt": "We moderate product reviews on our marketplace. Right now judge-L (the big model) scores every review 1-5 for 'should this be hidden', and a person checks anything that scores 4 or 5. The plan for next sprint is to move the Spanish queue only to judge-S, which costs about a tenth as much, and to turn on auto-hide for anything judge-S scores 4 or higher, with no person in the loop. Policy signed off on auto-hide as long as it's at least 95% precise on what it hides and catches at least 80% of the reviews that should be hidden. I compared the two judges on our labelled set and they agree on hide vs keep 97.5% of the time, so I think we're fine? The file is moderation_eval.csv, and expert_label comes from the trust and safety team. Can we go ahead with the plan?",
|
|
183
|
+
"assertions": [
|
|
184
|
+
"Tests the plan as stated (judge-S, Spanish rows only, auto-hide at a score of 4 or more) against the trust and safety labels: 14 of the 20 Spanish reviews it would hide should be hidden (70% precision), and it catches 14 of the 20 that should be hidden (70% recall), so it fails both the 95% bar and the 80% bar",
|
|
185
|
+
"Explains why the 97.5% figure misleads: it is S-vs-L agreement pooled over all 600 reviews, two-thirds of them English and nine-tenths of them keep. On Spanish alone the two judges agree 95.0% of the time, with Cohen's kappa of about 0.71",
|
|
186
|
+
"Reports chance-corrected agreement with the expert labels on Spanish: judge-S's 94.0% raw agreement is a kappa of about 0.67, against about 0.94 for judge-L",
|
|
187
|
+
"Checks whether a different cut-off saves judge-S on Spanish and finds none that does: a score of 5 or more gives 88.9% precision (8 of 9) but 40% recall, and 3 or more gives 90% recall but 48.6% precision (18 of 37)",
|
|
188
|
+
"Shows that the problem is specific to Spanish: on English, judge-S at 4 or more reaches 97.4% precision (38 of 39) and 95% recall (38 of 40)",
|
|
189
|
+
"Reports judge-L on Spanish at 18 of 18 precision and 90% recall (18 of 20), meeting both bars on the point estimates. It also notes that with only 20 Spanish reviews that should be hidden, the 95% confidence interval on that precision has a lower bound of about 81-82%, so even judge-L is not shown to meet 95% with confidence",
|
|
190
|
+
"Gives a direct answer: do not move the Spanish queue to judge-S with auto-hide. It names a workable alternative, such as keeping judge-L with human review, or using judge-S only to route reviews to people, together with labelling more Spanish reviews that should be hidden",
|
|
191
|
+
"Does not invent figures that are not in the file, such as judge prices beyond 'about a tenth', Spanish queue volumes, or the text of individual reviews"
|
|
192
|
+
]
|
|
163
193
|
}
|
|
164
194
|
]
|
|
165
195
|
}
|