feat: workflow recipes, eval badges, one-click MCP, playground upgrades, sample gallery, skill-of-the-week

Signature features that turn breadth (174 skills) into a differentiated product:

- Workflow recipes: 5 cross-profession chains (workflows.json) that pass each
  output forward — slash commands (/ship-a-feature etc.), WORKFLOWS.md generated
  by scripts/build-workflows.mjs, README + MCP (list_workflows/get_workflow) wired
- Eval-backed quality: real per-skill scores from evals/results.json surfaced as
  badges in the playground and an honest README section (6 scored skills)
- One-click MCP: 'claude mcp add' install + workflow tools, works in any MCP client
- Playground: 'which skill?' recommender, with/without compare toggle, shareable
  ?skill= deep-links with prefilled inputs
- Sample-output gallery: hand-written examples for the hero five + generator
  (scripts/build-samples.mjs) + web/examples.html
- Skill-of-the-week: scheduled workflow + script that composes X/LinkedIn posts
  and posts to an optional webhook

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Mohit
2026-06-19 09:56:11 +01:00
parent 7f06f0a993
commit 54f76456ab
30 changed files with 1168 additions and 67 deletions
+21
View File
@@ -20,6 +20,26 @@ const experimentalSet = new Set(TIERS.experimental);
const tierFor = (name) =>
productionSet.has(name) ? 'production' : experimentalSet.has(name) ? 'experimental' : 'stable';
// --- Eval scores (from evals/results.json) ---
// Average the per-model "overall" (a 05 rubric score) for each scored skill.
// Only skills with eval cases get a score; the rest stay unscored (honest).
const evalScores = {};
const evalsFile = join(root, 'evals', 'results.json');
if (existsSync(evalsFile)) {
try {
const acc = {};
for (const r of JSON.parse(readFileSync(evalsFile, 'utf8')).results || []) {
(acc[r.skill] ||= []).push(r.overall);
}
for (const [skill, arr] of Object.entries(acc)) {
evalScores[skill] = {
score: Math.round((arr.reduce((a, b) => a + b, 0) / arr.length) * 10) / 10,
runs: arr.length,
};
}
} catch { /* leave unscored on parse error */ }
}
// --- Map each skill name -> plugin bundle (for grouping/filtering) ---
const skillToPlugin = {};
if (existsSync(pluginsDir)) {
@@ -109,6 +129,7 @@ for (const name of readdirSync(skillsDir)) {
summary: summarize(meta.description || ''),
plugin: skillToPlugin[name] || 'other',
tier: tierFor(name),
eval: evalScores[meta.name || name] || null,
inputs: parseInputs(body),
instructions: body.trim(),
});