swe-workflow-skills 0.2.0 → 0.4.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 CHANGED
@@ -1,10 +1,10 @@
1
1
  # SWE Workflow Skills for Claude Code
2
2
 
3
3
  [![roles-check](https://github.com/SWEStash/swe-workflow-skills/actions/workflows/roles-check.yml/badge.svg)](https://github.com/SWEStash/swe-workflow-skills/actions/workflows/roles-check.yml)
4
- ![skills](https://img.shields.io/badge/skills-62-blue)
4
+ ![skills](https://img.shields.io/badge/skills-65-blue)
5
5
  [![license: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
6
6
 
7
- A curated library of **62 Claude Code Agent Skills** that walk Claude through the
7
+ A curated library of **65 Claude Code Agent Skills** that walk Claude through the
8
8
  software lifecycle the way a disciplined senior engineer would — planning, design,
9
9
  TDD, review, security, deployment, incidents, and the project-management work around
10
10
  them.
@@ -43,8 +43,8 @@ full-SDLC breadth that popular collections don't cover:
43
43
  know of aim for (they tend to go deep on the coding inner loop; see
44
44
  [Acknowledgements](#acknowledgements)).
45
45
  - **Role-scoped.** `/role backend` (or `frontend`, `devops`, `ml`, `ai`, `data`,
46
- `security`, `architect`, `em`, `pm`, `strategy`, `qa`, `mobile`, `designer`) promotes
47
- a working set to auto-trigger; the rest stay one route away.
46
+ `data-scientist`, `security`, `architect`, `em`, `pm`, `strategy`, `qa`, `mobile`,
47
+ `designer`) promotes a working set to auto-trigger; the rest stay one route away.
48
48
  - **Cross-platform install.** The installer and SessionStart hook are **pure Node** — the
49
49
  one runtime Claude Code already requires — so they run identically on Linux, macOS, and
50
50
  Windows (no bash, Python, or `sed`).
@@ -62,7 +62,7 @@ web, claude.ai chat, and Cowork):
62
62
  **Want the whole library with the orchestrator** (CLI) — no clone needed:
63
63
 
64
64
  ```bash
65
- npx swe-workflow-skills install --global # all 62 skills + router + /role + the SessionStart hook
65
+ npx swe-workflow-skills install --global # all 65 skills + router + /role + the SessionStart hook
66
66
  ```
67
67
 
68
68
  Or from a clone: `node install.mjs --global`.
@@ -120,7 +120,7 @@ review) live in the `skill-router` skill and **[ROLES.md](docs/ROLES.md)**.
120
120
 
121
121
  ## What's included
122
122
 
123
- 62 skills — **[full catalog → SKILLS.md](docs/SKILLS.md)**:
123
+ 65 skills — **[full catalog → SKILLS.md](docs/SKILLS.md)**:
124
124
 
125
125
  | Area | Count | Examples |
126
126
  |------|-------|----------|
@@ -130,6 +130,7 @@ review) live in the `skill-router` skill and **[ROLES.md](docs/ROLES.md)**.
130
130
  | Design | 3 | ui-ux-design, frontend-architecture, accessibility-design |
131
131
  | MLOps | 3 | ml-pipeline-design, ml-experiment-tracking, ml-model-deployment |
132
132
  | AI Engineering | 2 | llm-app-engineering, ai-evaluation |
133
+ | Data Science | 3 | exploratory-data-analysis, statistical-analysis, notebook-to-production |
133
134
  | Data Engineering | 2 | data-pipeline-design, data-quality |
134
135
  | Mobile | 2 | mobile-architecture, mobile-release |
135
136
  | Evaluation & Monitoring | 2 | observability-design, test-data-strategy |
@@ -143,6 +144,7 @@ review) live in the `skill-router` skill and **[ROLES.md](docs/ROLES.md)**.
143
144
  - **[EVALS.md](docs/EVALS.md)** — how the skills are tested (RED/GREEN, pressure tests, CI gate).
144
145
  - **[AUTHORING.md](docs/AUTHORING.md)** — write or modify a skill (descriptions, budget, progressive disclosure, evals).
145
146
  - **[RELEASING.md](docs/RELEASING.md)** — versioning policy and how to cut a release. Changes are tracked in **[CHANGELOG.md](CHANGELOG.md)**.
147
+ - **[SECURITY.md](SECURITY.md)** — the security model: trust boundaries, what runs automatically, supply-chain guarantees, and how to report a vulnerability.
146
148
 
147
149
  ## Evaluation
148
150
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.4.0
package/catalog.json CHANGED
@@ -8,7 +8,7 @@
8
8
  },
9
9
  {
10
10
  "name": "ai-evaluation",
11
- "description": "Define how to evaluate ML models and GenAI/LLM apps — golden datasets, offline metrics, RAG evaluation (faithfulness, answer relevance, context precision/recall) with ragas/deepeval/promptfoo, LLM-as-judge design and calibration, eval regression gates in CI, online A/B and human feedback. Triggers: evaluate the model, eval my chatbot, RAG evals, ragas, LLM as judge, golden dataset, eval suite, is the new prompt better, hallucination rate, benchmark our AI app. Logging/comparing runs → ml-experiment-tracking; building the app → llm-app-engineering.",
11
+ "description": "Define how to evaluate ML models and GenAI/LLM apps — golden datasets, offline metrics, RAG evaluation (faithfulness, relevance, context precision/recall) with ragas/deepeval/promptfoo, LLM-as-judge design and calibration, eval regression gates in CI, online A/B and human feedback. Logging/comparing runs → ml-experiment-tracking; building the app → llm-app-engineering; general experiment statistics → statistical-analysis. Triggers: evaluate the model, eval my chatbot, RAG evals, ragas, LLM as judge, golden dataset, eval suite, is the new prompt better, hallucination rate, benchmark our AI app.",
12
12
  "path": "ai-evaluation/SKILL.md"
13
13
  },
14
14
  {
@@ -121,6 +121,11 @@
121
121
  "description": "Estimate engineering effort with agile techniques — story points, t-shirt sizing, three-point estimation, capacity planning. Triggers: estimate this, how long will this take, story points, t-shirt sizing, effort estimation, capacity planning, sprint planning, budget estimate, forecast, velocity, when will this be done.",
122
122
  "path": "effort-estimation/SKILL.md"
123
123
  },
124
+ {
125
+ "name": "exploratory-data-analysis",
126
+ "description": "Explore and profile an unfamiliar dataset before modeling or analysis — structural profiling, missingness structure, distributions and outliers, feature–target relationships, leakage awareness, and explicit hypothesis generation. Pipeline-level data trust (broken dashboards, tests, contracts, freshness) → data-quality; formal inference on the hypotheses → statistical-analysis. Triggers: explore this dataset, EDA, profile the data, what's in this data, first look at the data, understand this CSV, distributions, outliers, missing values, correlation, data leakage.",
127
+ "path": "exploratory-data-analysis/SKILL.md"
128
+ },
124
129
  {
125
130
  "name": "feature-planning",
126
131
  "description": "Break features into well-scoped tasks with acceptance criteria, risk assessment, and dependency mapping. Triggers: plan this, break this down, scope this feature, create tasks for, sprint planning, how should I implement this feature, user stories, acceptance criteria, dependency mapping, feature breakdown. Creates the plan — executing an already-approved plan checkpoint by checkpoint → plan-execution.",
@@ -178,7 +183,7 @@
178
183
  },
179
184
  {
180
185
  "name": "ml-pipeline-design",
181
- "description": "Design reproducible ML training and data pipelines — ingestion, validation, feature engineering, training, evaluation, continuous training orchestration. Triggers: training pipeline, ML data pipeline, feature engineering, ETL for ML, continuous training, data validation, feature store, preprocessing, notebook to pipeline, orchestrate training, Kubeflow, pipeline DAG, point-in-time features. Analytics/BI ELT and dbt warehouse pipelines → data-pipeline-design.",
186
+ "description": "Design reproducible ML training and data pipelines — ingestion, validation, feature engineering, training, evaluation, continuous training orchestration. Analytics/BI ELT and dbt warehouse pipelines → data-pipeline-design; refactoring general analysis/reporting notebooks (no model training) to production code → notebook-to-production. Triggers: training pipeline, ML data pipeline, feature engineering, ETL for ML, continuous training, data validation, feature store, preprocessing, notebook to training pipeline, orchestrate training, Kubeflow, pipeline DAG, point-in-time features.",
182
187
  "path": "ml-pipeline-design/SKILL.md"
183
188
  },
184
189
  {
@@ -191,6 +196,11 @@
191
196
  "description": "Ship mobile apps through the app stores — signing and provisioning, store review and rejection handling, phased/staged rollouts with halt criteria, crash monitoring, versioning and build numbers, beta channels (TestFlight, Play tracks), forced updates, and the no-instant-rollback reality of mobile. Triggers: app store release, publish to App Store, Play Store, TestFlight, staged rollout, app review rejected, code signing, provisioning profile, mobile release, hotfix a mobile bug. General semver/registry/library publishing → release-management.",
192
197
  "path": "mobile-release/SKILL.md"
193
198
  },
199
+ {
200
+ "name": "notebook-to-production",
201
+ "description": "Refactor analysis notebooks into production-grade code — triage what deserves productionizing, extract modules with tests, parameterize hardcoded values, pin environments for reproducibility, and schedule unattended runs with alerting. Owns general analysis/reporting notebooks; notebooks that feed model TRAINING (feature engineering + training DAGs, scheduled retraining) → ml-pipeline-design. Triggers: productionize this notebook, notebook to script, notebook to module, refactor my notebook, parameterize notebook, papermill, schedule this analysis, reproducible analysis, notebook is a mess.",
202
+ "path": "notebook-to-production/SKILL.md"
203
+ },
194
204
  {
195
205
  "name": "observability-design",
196
206
  "description": "Design production observability — SLIs, SLOs, SLAs, error budgets, OpenTelemetry traces/metrics/logs, structured logging, alerting, dashboards. Triggers: SLO, SLI, SLA, error budget, observability, monitoring, OpenTelemetry, OTel, tracing, distributed tracing, structured logging, alerting, dashboard, metrics, correlation ID, alert fatigue.",
@@ -223,7 +233,7 @@
223
233
  },
224
234
  {
225
235
  "name": "project-review",
226
- "description": "Review a built project's execution health before a milestone — scope alignment, roadmap / execution-plan adherence, implementation maturity (what's production-ready vs stub/deferred), and the evidence it actually works (tests, coverage, validation results, changelog). Triggers: project review, execution review, are we on track, implementation vs roadmap, scope drift, readiness review, what's actually built, validation results review, pre-launch review. Use strategic-review for vision/positioning/market; technical-debt-review for a pure code-health audit.",
236
+ "description": "Review a built project's execution health before a milestone — scope alignment, roadmap / execution-plan adherence, implementation maturity (what's production-ready vs stub/deferred), and the evidence it actually works (tests, coverage, validation results, changelog). Use strategic-review for vision/positioning/market; technical-debt-review for a pure code-health audit. Triggers: project review, execution review, are we on track, implementation vs roadmap, scope drift, readiness review, what's actually built, validation results review, pre-launch review.",
227
237
  "path": "project-review/SKILL.md"
228
238
  },
229
239
  {
@@ -253,17 +263,22 @@
253
263
  },
254
264
  {
255
265
  "name": "security-audit",
256
- "description": "Comprehensive security analysis — OWASP Top 10, auth/authz flows, injection vulnerabilities, data exposure, secrets detection, dependency CVEs, hardening recommendations. Triggers: security audit, vulnerability, is this secure, security review, pentest prep, OWASP, harden this, check for vulnerabilities, injection, XSS, CSRF, auth security. Reviews EXISTING code/config — design-time analysis of a system not yet built → threat-modeling.",
266
+ "description": "Comprehensive security analysis — OWASP Top 10, auth/authz flows, injection vulnerabilities, data exposure, secrets detection, dependency CVEs, hardening recommendations. Reviews EXISTING code/config — design-time analysis of a system not yet built → threat-modeling. Triggers: security audit, vulnerability, is this secure, security review, pentest prep, OWASP, harden this, check for vulnerabilities, injection, XSS, CSRF, auth security.",
257
267
  "path": "security-audit/SKILL.md"
258
268
  },
259
269
  {
260
270
  "name": "skill-router",
261
- "description": "Orchestrator and entry point for the swe-workflow skills library — consult FIRST when starting any non-trivial software task; most skills load name-only and only activate when invoked here. Triggers: starting a feature, planning, an architecture or design decision, implementing, debugging, reviewing, refactoring, testing, security, deployment, an incident, shipping, or unsure which skill fits. Routes intent to the right skill(s) and invokes them by name; shows the Golden Path chains.",
271
+ "description": "Orchestrator and entry point for the swe-workflow skills library — consult FIRST when starting any non-trivial software task; most skills load name-only and only activate when invoked here. Routes intent to the right skill(s) and invokes them by name; shows the Golden Path chains. Triggers: starting a feature, planning, an architecture or design decision, implementing, debugging, reviewing, refactoring, testing, security, deployment, an incident, shipping, or unsure which skill fits.",
262
272
  "path": "skill-router/SKILL.md"
263
273
  },
274
+ {
275
+ "name": "statistical-analysis",
276
+ "description": "Design and analyze experiments and statistical tests — test selection with stated assumptions, sample size and power, effect sizes and confidence intervals over bare p-values, and pitfall discipline (multiple comparisons, p-hacking, peeking/optional stopping). Owns experiment statistics generally; live A/B evaluation of AI/LLM apps (quality metrics, judges, feedback) → ai-evaluation. Triggers: hypothesis test, t-test, chi-square, p-value, statistical significance, confidence interval, sample size, power analysis, design an experiment, A/B test, multiple comparisons, is this difference real.",
277
+ "path": "statistical-analysis/SKILL.md"
278
+ },
264
279
  {
265
280
  "name": "strategic-review",
266
- "description": "Review a project's strategic position before going public, launching, or raising — vision, mission, value proposition, scope positioning, the defensible wedge, and a live competitive / market comparative analysis. Triggers: strategic review, positioning, go public, go-to-market, market analysis, competitive landscape, value proposition, is there a moat, who are our competitors, platform absorption risk, market positioning, comparable products. Use project-review for execution/roadmap/implementation health; delegates deep market scans to deep-research.",
281
+ "description": "Review a project's strategic position before going public, launching, or raising — vision, mission, value proposition, scope positioning, the defensible wedge, and a live competitive / market comparative analysis. Use project-review for execution/roadmap/implementation health; delegates deep market scans to deep-research. Triggers: strategic review, positioning, go public, go-to-market, market analysis, competitive landscape, value proposition, is there a moat, who are our competitors, platform absorption risk, market positioning, comparable products.",
267
282
  "path": "strategic-review/SKILL.md"
268
283
  },
269
284
  {
package/commands/role.md CHANGED
@@ -8,27 +8,61 @@ disable-model-invocation: true
8
8
 
9
9
  The user is managing the active swe-workflow skill role. The requested role argument is: `$ARGUMENTS`
10
10
 
11
- Run this script exactly once via Bash, then report the result to the user concisely (the new active role, and that the change hot-reloads so it applies to the next prompt):
11
+ **Validate the argument before running anything this is the security-critical
12
+ step.** It must be empty or match `^[a-z0-9_-]{1,32}$` (role keys are short
13
+ kebab-case names). If it contains ANYTHING else — a space, quote, `$`, backtick,
14
+ slash, semicolon, or any other character — the argument is invalid: do NOT run any
15
+ Bash command that contains the argument in any form (not in a variable, not as an
16
+ argument, not anywhere). Instead reply that the role name is invalid and list the
17
+ available roles by running only the fixed command `node "@@RESOLVE@@" roles` with
18
+ `ROLES_JSON="@@ROLES@@"` exported — that command does not reference the argument at
19
+ all.
20
+
21
+ If the argument is valid (or empty), run the setup block once, then run the ONE
22
+ branch below that matches, substituting the validated role for `__ROLE__` **only
23
+ where shown** (always inside double quotes as the final argument of a `node`
24
+ call — never assigned to a shell variable). Then report the result concisely (the
25
+ new active role, and that the change hot-reloads so it applies to the next
26
+ prompt):
12
27
 
13
28
  ```bash
14
- ROLE="$ARGUMENTS"
29
+ # --- setup (no argument appears here) ---
15
30
  RESOLVE="@@RESOLVE@@"; SKILLS="@@SKILLS@@"; SETTINGS="@@SETTINGS@@"
16
31
  ROLES="@@ROLES@@"; ACTIVE="@@ACTIVE_ROLE@@"
17
32
  export ROLES_JSON="$ROLES"
18
- if [ -z "$ROLE" ]; then
19
- echo "Active role: $(cat "$ACTIVE" 2>/dev/null || echo 'baseline (none)')"
20
- echo "Available roles:"; node "$RESOLVE" roles
21
- elif [ "$ROLE" = "all" ] || [ "$ROLE" = "none" ]; then
22
- node "$RESOLVE" apply "$SETTINGS" "$SKILLS" none && rm -f "$ACTIVE"
23
- echo "Reset to baseline only the pinned skills auto-trigger now."
24
- elif node "$RESOLVE" label "$ROLE" >/dev/null 2>&1; then
25
- node "$RESOLVE" apply "$SETTINGS" "$SKILLS" "$ROLE" && printf '%s\n' "$ROLE" > "$ACTIVE"
26
- echo "Active role set to '$ROLE' its skills now auto-trigger."
33
+ ```
34
+
35
+ Empty argument (no role given) — show current + available, no substitution:
36
+ ```bash
37
+ echo "Active role: $(cat "$ACTIVE" 2>/dev/null || echo 'baseline (none)')"
38
+ echo "Available roles:"; node "$RESOLVE" roles
39
+ ```
40
+
41
+ Argument is `all` or `none`reset to baseline:
42
+ ```bash
43
+ node "$RESOLVE" apply "$SETTINGS" "$SKILLS" none && rm -f "$ACTIVE"
44
+ echo "Reset to baseline — only the pinned skills auto-trigger now."
45
+ ```
46
+
47
+ Any other validated role — apply it. `resolve.mjs` rejects an unknown role with a
48
+ non-zero exit, so the `&&` short-circuits and the marker is only written for a role
49
+ that actually resolved:
50
+ ```bash
51
+ if node "$RESOLVE" apply "$SETTINGS" "$SKILLS" "__ROLE__" && printf '%s\n' "__ROLE__" > "$ACTIVE"; then
52
+ echo "Active role set — its skills now auto-trigger."
27
53
  else
28
- echo "Unknown role '$ROLE'. Available roles:"; node "$RESOLVE" roles
54
+ echo "Unknown role. Available roles:"; node "$RESOLVE" roles
29
55
  fi
30
56
  ```
31
57
 
32
58
  Notes:
33
59
  - `skillOverrides` and the skill listing hot-reload when `settings.local.json` changes, so the new auto-trigger set takes effect on the next prompt without a restart.
34
60
  - This command is for the full (all-skills) CLI install. Hard-subset (`--role`) installs and the per-role marketplace plugins don't need it.
61
+ - Security: `$ARGUMENTS` is never embedded directly (slash-command templates
62
+ interpolate it as text, so a crafted argument would execute in the shell). The
63
+ **primary control is the model-side regex validation above** — do it before
64
+ emitting any Bash. As a deterministic backstop, the validated value reaches the
65
+ shell only as the final quoted argv of a `node "$RESOLVE"` call, where
66
+ `resolve.mjs` (`roleOrDie`) rejects any string that is not a known role before
67
+ it is used — the value is never placed in a bare `ROLE=...` assignment. See
68
+ `SECURITY.md` for the residual (quote-escape) risk and why it is accepted.
package/install.mjs CHANGED
@@ -52,6 +52,9 @@ Options:
52
52
  -p, --prune After installing the selected set, remove previously-installed
53
53
  library skills that are NOT in the new selection (never touches
54
54
  your own custom skills). Use to narrow a prior all-skills install.
55
+ -f, --force Overwrite a same-named skill directory that this installer did
56
+ not create (by default such a collision is skipped, so your own
57
+ custom skill with a library name is never clobbered).
55
58
  -k, --hook (default) Install the SessionStart hook that re-asserts the
56
59
  name-only baseline each session + injects the router nudge
57
60
  (prints the settings snippet; never edits settings)
@@ -106,6 +109,7 @@ function toPosix(p) {
106
109
  let global = false;
107
110
  let hook = true;
108
111
  let prune = false;
112
+ let force = false;
109
113
  let configDir = "";
110
114
  let role = "";
111
115
  const selected = [];
@@ -125,6 +129,7 @@ for (let i = 0; i < argv.length; i++) {
125
129
  if (role === undefined) fatal("--role requires a role name");
126
130
  } else if (a.startsWith("--role=")) role = a.slice("--role=".length);
127
131
  else if (a === "-p" || a === "--prune") prune = true;
132
+ else if (a === "-f" || a === "--force") force = true;
128
133
  else if (a === "-k" || a === "--hook") hook = true;
129
134
  else if (a === "--no-hook") hook = false;
130
135
  else if (a === "-l" || a === "--list") {
@@ -161,6 +166,17 @@ if (role) {
161
166
  }
162
167
  }
163
168
 
169
+ // Positional args must be exact skill names, never paths: a traversal like
170
+ // `install.mjs ../..` would pass the isDir guard below and the clean-copy rmSync
171
+ // would then delete outside the destination. Reject before touching anything.
172
+ if (selected.length > 0) {
173
+ const known = new Set(listSkillDirs());
174
+ const bad = selected.filter((s) => !known.has(s));
175
+ if (bad.length > 0) {
176
+ fatal(`unknown skill(s): ${bad.join(", ")}. Run 'install.mjs --list' to see skills.`);
177
+ }
178
+ }
179
+
164
180
  // ---- resolve destination ---------------------------------------------------
165
181
 
166
182
  let claudeDir;
@@ -181,9 +197,46 @@ if (skillSet.length === 0) {
181
197
  skillSet = role ? resolvedSkills(rolesData, role) : listSkillDirs();
182
198
  }
183
199
 
200
+ // ---- provenance manifest ---------------------------------------------------
201
+ // Records which skill directories THIS installer created, so uninstall/--prune
202
+ // only ever remove our own skills and a re-install never clobbers a user's custom
203
+ // skill that happens to share a library name. See docs SECURITY.md (LOW-003).
204
+ const MANIFEST = join(dest, ".swe-workflow-manifest.json");
205
+
206
+ function readManifestSkills() {
207
+ if (existsSync(MANIFEST)) {
208
+ try {
209
+ const m = JSON.parse(readFileSync(MANIFEST, "utf-8"));
210
+ if (Array.isArray(m.skills)) return new Set(m.skills);
211
+ } catch {
212
+ /* unreadable manifest -> treat as absent */
213
+ }
214
+ }
215
+ return null; // null = no manifest present
216
+ }
217
+
218
+ const priorManifest = readManifestSkills();
219
+ // A prior swe-workflow install (any version) leaves these machinery markers even
220
+ // before manifests existed. If neither a manifest nor a marker is present, the dest
221
+ // is not one we've installed into, so a same-named dir there must be the user's.
222
+ const priorInstall =
223
+ priorManifest !== null ||
224
+ existsSync(join(dest, ".roles.json")) ||
225
+ existsSync(join(claudeDir, "hooks", "resolve.mjs"));
226
+
227
+ // Do we own the skill dir currently at dest? Manifest is authoritative when present;
228
+ // otherwise fall back to "is this dest a prior swe install at all?" so pre-manifest
229
+ // upgrades still overwrite our own skills rather than skipping them.
230
+ function installerOwns(skill) {
231
+ if (priorManifest !== null) return priorManifest.has(skill);
232
+ return priorInstall;
233
+ }
234
+
184
235
  // ---- copy skills -----------------------------------------------------------
185
236
 
186
237
  let errors = 0;
238
+ const installedNow = [];
239
+ const skippedCollisions = [];
187
240
  for (const skill of skillSet) {
188
241
  const src = join(SKILLS_DIR, skill);
189
242
  if (!isDir(src)) {
@@ -191,24 +244,59 @@ for (const skill of skillSet) {
191
244
  errors++;
192
245
  continue;
193
246
  }
247
+ const destPath = join(dest, skill);
248
+ // Never clobber a same-named directory we didn't create unless --force.
249
+ if (isDir(destPath) && !force && !installerOwns(skill)) {
250
+ warn(
251
+ `skipping '${skill}': a skill of that name already exists and was not installed ` +
252
+ `by swe-workflow-skills. Use --force to overwrite it.`,
253
+ );
254
+ skippedCollisions.push(skill);
255
+ continue;
256
+ }
194
257
  // Clean copy: drop any prior version first so files removed upstream don't linger.
195
- rmSync(join(dest, skill), { recursive: true, force: true });
196
- cpSync(src, join(dest, skill), { recursive: true });
197
- log(`Installed: ${skill} -> ${join(dest, skill)}`);
258
+ rmSync(destPath, { recursive: true, force: true });
259
+ cpSync(src, destPath, { recursive: true });
260
+ installedNow.push(skill);
261
+ log(`Installed: ${skill} -> ${destPath}`);
198
262
  }
199
263
 
200
264
  // --prune: narrow a prior install to the current selection. Only ever removes skills
201
- // that exist in our source tree (so the user's own custom skills are never touched).
265
+ // that exist in our source tree AND that this installer created (so the user's own
266
+ // custom skills — including any that share a library name — are never touched).
267
+ const pruned = new Set();
202
268
  if (prune) {
203
269
  const keep = new Set(skillSet);
204
270
  for (const s of listSkillDirs()) {
205
- if (!keep.has(s) && isDir(join(dest, s))) {
271
+ if (!keep.has(s) && isDir(join(dest, s)) && installerOwns(s)) {
206
272
  rmSync(join(dest, s), { recursive: true, force: true });
273
+ pruned.add(s);
207
274
  log(`Pruned: ${s} (not in selection)`);
208
275
  }
209
276
  }
210
277
  }
211
278
 
279
+ // Rewrite the provenance manifest: every library skill we own that is still present.
280
+ // = (what we owned before) ∪ (installed this run) − (pruned this run), intersected
281
+ // with library skill dirs actually on disk. Skipped collisions never enter it.
282
+ const libNames = new Set(listSkillDirs());
283
+ const ownedSkills = new Set([...(priorManifest || []), ...installedNow]);
284
+ const manifestSkills = [...ownedSkills]
285
+ .filter((s) => !pruned.has(s) && libNames.has(s) && isDir(join(dest, s)))
286
+ .sort();
287
+ if (installedNow.length > 0 || priorManifest !== null || prune) {
288
+ let manifestVersion = "";
289
+ try {
290
+ manifestVersion = readFileSync(join(REPO_ROOT, "VERSION"), "utf-8").trim();
291
+ } catch {
292
+ /* VERSION is optional metadata in the manifest */
293
+ }
294
+ writeFileSync(
295
+ MANIFEST,
296
+ JSON.stringify({ installer: "swe-workflow-skills", version: manifestVersion, skills: manifestSkills }, null, 2) + "\n",
297
+ );
298
+ }
299
+
212
300
  // ---- orchestrator machinery (only when skill-router is in the set) ---------
213
301
 
214
302
  const hasRouter = skillSet.includes("skill-router");
@@ -292,21 +380,39 @@ if (hook) {
292
380
  }
293
381
  }
294
382
 
383
+ // Per-skill collision warnings scroll away during a full install; restate them once
384
+ // at the end so an unowned same-named skill that was left in place is not missed.
385
+ if (skippedCollisions.length > 0) {
386
+ warn(
387
+ `left ${skippedCollisions.length} existing skill(s) untouched (not installed by ` +
388
+ `swe-workflow-skills): ${skippedCollisions.join(", ")}. Re-run with --force to overwrite.`,
389
+ );
390
+ }
391
+
295
392
  if (errors !== 0) process.exit(1);
296
393
 
297
394
  function copyIfExists(src, destPath) {
298
395
  if (existsSync(src)) cpSync(src, destPath);
299
396
  }
300
397
 
301
- // The SessionStart block to merge into settings.json. JSON.stringify keeps the path
302
- // correctly escaped on every OS (Windows backslashes included).
398
+ // Double-quote a path for the POSIX shell that runs the hook command, escaping the
399
+ // chars that stay active inside double quotes (\ $ ` "). Without the $/` escapes, a
400
+ // config path containing e.g. `$(cmd)` would run that command substitution at every
401
+ // session start. For \ and " this produces exactly what JSON.stringify used to (so
402
+ // Windows paths render unchanged); cmd.exe keeps the backslash before $/`, but paths
403
+ // with those chars are effectively POSIX-only.
404
+ function shellQuote(p) {
405
+ return '"' + p.replace(/[\\$`"]/g, (c) => "\\" + c) + '"';
406
+ }
407
+
408
+ // The SessionStart block to merge into settings.json.
303
409
  function hookSnippet(path) {
304
410
  const block = {
305
411
  hooks: {
306
412
  SessionStart: [
307
413
  {
308
414
  matcher: "startup|resume|clear|compact",
309
- hooks: [{ type: "command", command: `node ${JSON.stringify(path)}` }],
415
+ hooks: [{ type: "command", command: `node ${shellQuote(path)}` }],
310
416
  },
311
417
  ],
312
418
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "swe-workflow-skills",
3
- "version": "0.2.0",
4
- "description": "A curated library of 44 Claude Code Agent Skills for the software lifecycle, with orchestrator-routed activation that scales past the skill-listing budget.",
3
+ "version": "0.4.0",
4
+ "description": "A curated library of Claude Code Agent Skills covering the full software lifecycle, with orchestrator-routed activation that scales past the skill-listing budget.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "swe-workflow-skills": "bin/cli.mjs"
package/roles.json CHANGED
@@ -127,6 +127,20 @@
127
127
  "observability-design"
128
128
  ]
129
129
  },
130
+ "data-scientist": {
131
+ "label": "Data Scientist",
132
+ "description": "Skills for exploratory data analysis, statistical rigor, notebook productionization, and the experiment-tracking/data-quality/modeling work around them.",
133
+ "core": "technical",
134
+ "skills": [
135
+ "exploratory-data-analysis",
136
+ "statistical-analysis",
137
+ "notebook-to-production",
138
+ "ml-experiment-tracking",
139
+ "data-quality",
140
+ "data-modeling",
141
+ "ai-evaluation"
142
+ ]
143
+ },
130
144
  "security": {
131
145
  "label": "Security Engineer",
132
146
  "description": "Skills for design-time threat modeling, security audits, dependency/CVE management, blast-radius analysis, and incident handling.",
@@ -104,10 +104,15 @@ function sortKeysDeep(value) {
104
104
 
105
105
  export function loadSettings(settingsPath) {
106
106
  if (existsSync(settingsPath) && statSync(settingsPath).isFile()) {
107
+ const text = readFileSync(settingsPath, "utf-8");
107
108
  try {
108
- return JSON.parse(readFileSync(settingsPath, "utf-8")) || {};
109
- } catch {
110
- return {};
109
+ return JSON.parse(text) || {};
110
+ } catch (e) {
111
+ // A corrupt (e.g. hand-edited) file must NOT read as empty: downstream
112
+ // writers would rebuild it from {} and silently destroy the user's
113
+ // settings. Throw so callers skip the write (the SessionStart hook
114
+ // catches this and leaves the file alone; the CLI surfaces it).
115
+ throw new Error(`unparseable JSON in ${settingsPath} — fix or remove it (${e.message})`);
111
116
  }
112
117
  }
113
118
  return {};
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: ai-evaluation
3
- description: "Define how to evaluate ML models and GenAI/LLM apps — golden datasets, offline metrics, RAG evaluation (faithfulness, answer relevance, context precision/recall) with ragas/deepeval/promptfoo, LLM-as-judge design and calibration, eval regression gates in CI, online A/B and human feedback. Triggers: evaluate the model, eval my chatbot, RAG evals, ragas, LLM as judge, golden dataset, eval suite, is the new prompt better, hallucination rate, benchmark our AI app. Logging/comparing runs → ml-experiment-tracking; building the app → llm-app-engineering."
3
+ description: "Define how to evaluate ML models and GenAI/LLM apps — golden datasets, offline metrics, RAG evaluation (faithfulness, relevance, context precision/recall) with ragas/deepeval/promptfoo, LLM-as-judge design and calibration, eval regression gates in CI, online A/B and human feedback. Logging/comparing runs → ml-experiment-tracking; building the app → llm-app-engineering; general experiment statistics → statistical-analysis."
4
+ when_to_use: "Triggers: evaluate the model, eval my chatbot, RAG evals, ragas, LLM as judge, golden dataset, eval suite, is the new prompt better, hallucination rate, benchmark our AI app."
4
5
  model: sonnet
5
6
  allowed-tools: Read, Grep, Glob, Write, Edit, Bash
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: code-reviewing
3
- description: "Structured code reviews enforcing DRY, KISS, YAGNI, SRP, best practices, and project conventions. Triggers: review this code, code review, check my code, what do you think of this implementation, review this PR, is this code good, feedback on my code, review staged changes before commit."
3
+ description: "Structured code reviews enforcing DRY, KISS, YAGNI, SRP, best practices, and project conventions."
4
+ when_to_use: "Triggers: review this code, code review, check my code, what do you think of this implementation, review this PR, is this code good, feedback on my code, review staged changes before commit."
4
5
  model: sonnet
5
6
  allowed-tools: Read, Grep, Glob, Write, Edit
6
7
  ---
@@ -13,10 +14,19 @@ Perform thorough, constructive code reviews that catch bugs, enforce principles,
13
14
 
14
15
  ### Step 1: Understand the Context
15
16
 
16
- Before reviewing line-by-line, understand the big picture:
17
+ Working-tree changes right now (live at skill load; empty when the tree is clean,
18
+ this isn't a git repo, or the review targets something else — e.g. pasted code or
19
+ a PR):
20
+
21
+ !`git diff --stat 2>/dev/null || true`
22
+
23
+ If the summary above is empty or irrelevant to what you were asked to review,
24
+ proceed with the code as provided. Before reviewing line-by-line, understand the
25
+ big picture:
17
26
 
18
27
  - **What is this code supposed to do?** Read the PR description, linked issue, or ask the user.
19
- - **What changed?** If reviewing a diff, understand the scope of changes.
28
+ - **What changed?** If reviewing a diff, understand the scope of changes — run the
29
+ full `git diff` (or `git diff --staged`) when the stat summary isn't enough.
20
30
  - **What's the surrounding code like?** Read adjacent files for conventions and patterns.
21
31
 
22
32
  ### Step 2: First Pass — Structural Review
@@ -1,92 +1,49 @@
1
1
  ---
2
2
  name: effort-estimation
3
- description: "Estimate engineering effort with agile techniques — story points, t-shirt sizing, three-point estimation, capacity planning. Triggers: estimate this, how long will this take, story points, t-shirt sizing, effort estimation, capacity planning, sprint planning, budget estimate, forecast, velocity, when will this be done."
3
+ description: "Estimate engineering effort with agile techniques — story points, t-shirt sizing, three-point estimation, capacity planning."
4
+ when_to_use: "Triggers: estimate this, how long will this take, story points, t-shirt sizing, effort estimation, capacity planning, sprint planning, budget estimate, forecast, velocity, when will this be done."
4
5
  model: haiku
5
6
  allowed-tools: Read, Grep, Glob, Write, Edit
6
7
  ---
7
8
 
8
9
  # Effort Estimation
9
10
 
10
- Produce honest, useful estimates that help teams plan without creating false precision. Estimation in agile is about making informed decisions under uncertainty, not predicting the future exactly.
11
-
12
- ## Core Philosophy
13
-
14
- **Estimates are forecasts, not commitments.** They communicate "based on what we know today, here's our best guess at the range of effort." They should always include uncertainty ranges, and they should improve as you learn more.
11
+ Produce honest, useful estimates without false precision. Estimates are forecasts,
12
+ not commitments — always ranges, always improving as you learn more.
15
13
 
16
14
  ## Workflow
17
15
 
18
16
  ### Step 1: Ensure Tasks Are Defined
19
17
 
20
- You can't estimate undefined work. Before estimating, ensure:
21
-
22
- - Tasks are broken down (use `feature-planning` if not)
23
- - Acceptance criteria exist for each task
24
- - Technical approach is at least sketched (spikes completed for unknowns)
25
-
26
- If the work is too vague to estimate, say so. "I can't estimate this until we do a spike" is a valid and responsible answer.
27
-
28
- ### Step 2: Choose the Estimation Method
29
-
30
- | Method | Best For | Precision | Speed |
31
- |--------|----------|-----------|-------|
32
- | **T-shirt sizing** | Roadmap planning, early-stage sizing, large backlogs | Low (ranges) | Very fast |
33
- | **Story points** (Fibonacci) | Sprint planning, velocity tracking, mature teams | Medium (relative) | Moderate |
34
- | **Three-point estimation** | High-stakes estimates, budget requests, uncertain work | High (ranges with confidence) | Slow |
35
- | **Time-based** | Well-understood tasks with low uncertainty | High (hours/days) | Moderate |
36
-
37
- **Default recommendation**: T-shirt sizing for roadmap/quarter planning, story points for sprint planning. Three-point for budget requests and stakeholder communication.
18
+ You can't estimate undefined work. Tasks must be broken down (use `feature-planning`
19
+ if not), have acceptance criteria, and have at least a sketched technical approach.
20
+ "I can't estimate this until we do a spike" is a valid and responsible answer.
38
21
 
39
- ### Step 3: Apply the Method
22
+ ### Step 2: Choose the Method
40
23
 
41
- See [references/estimation-methods.md](references/estimation-methods.md) for detailed guidance on each method.
24
+ T-shirt sizing for roadmap and early-stage sizing; story points (Fibonacci) for
25
+ sprint planning and velocity tracking; three-point estimation for budget requests
26
+ and high-uncertainty, high-stakes work; time-based only for well-understood tasks.
27
+ See [references/estimation-methods.md](references/estimation-methods.md) for
28
+ detailed guidance on each method.
42
29
 
43
- **Key principles across all methods:**
30
+ ### Step 3: Apply It
44
31
 
45
- 1. **Estimate as a team**, not individually. The person most and least familiar with the area should both contribute the gap reveals hidden complexity.
46
- 2. **Estimate relative to known work**, not in absolute terms. "This is about twice as hard as that login feature we built" is more accurate than "this will take 3 days."
47
- 3. **Include uncertainty explicitly.** "3-5 days" is more honest than "4 days."
48
- 4. **Estimate the work, not the worker.** Story points measure the task's size, not who's doing it.
49
- 5. **Re-estimate when you learn more.** Initial estimates are educated guesses. Update them as spikes complete and requirements clarify.
32
+ Estimate per task, not the project as a single unit; relative to known work rather
33
+ than in absolute terms; as a team where possible (the familiarity gap between
34
+ estimators reveals hidden complexity); with uncertainty explicit. Re-estimate when
35
+ spikes complete or requirements clarify.
50
36
 
51
- ### Step 4: Handle Budget and Timeline Requests
37
+ ### Step 4: Translate for Stakeholders
52
38
 
53
- When stakeholders need dates or dollars, translate estimates thoughtfully:
54
-
55
- **From story points to time:**
56
- ```
57
- Estimated story points for the project: 85
58
- Team velocity: ~30 points per sprint (2-week sprints)
59
- Sprints needed: 85 / 30 = ~3 sprints = 6 weeks
60
-
61
- Add buffer for unknowns (20-30%): 7-8 weeks
62
- Communicate as range: "6-8 weeks with the current team"
63
- ```
64
-
65
- **From effort to cost:**
66
- ```
67
- Effort estimate: 12-16 person-weeks
68
- Team loaded cost: $X per person-week
69
- Total: 12 × $X to 16 × $X
70
- Communicate as range: "$A - $B"
71
- ```
72
-
73
- **Always provide ranges, never single numbers.** A single number becomes a commitment; a range communicates confidence.
39
+ Convert to time or cost via team velocity or loaded cost, add a 20-30% buffer for
40
+ unknowns, and communicate a range in stakeholder language — weeks and dollars, not
41
+ story points. A single number becomes a commitment; a range communicates confidence.
74
42
 
75
43
  ### Step 5: Track and Calibrate
76
44
 
77
- Estimates improve with feedback. After each sprint or project:
78
-
79
- - Compare estimated vs actual effort
80
- - Identify systematic patterns (always overestimate UI? Always underestimate integrations?)
81
- - Adjust team velocity based on recent data (use the last 3-5 sprints, not all-time average)
82
-
83
- ## Common Estimation Traps
84
-
85
- - **Anchoring**: The first number said influences everyone else. Use blind estimation (planning poker, simultaneous reveal).
86
- - **Planning fallacy**: People consistently underestimate. Use historical data to calibrate.
87
- - **Scope creep blindness**: Estimate the work as defined, then add buffer for scope growth — it always grows.
88
- - **Hero planning**: Estimating based on the best-case scenario with the best developer with zero interruptions. Estimate for a typical day with meetings and context switches.
89
- - **Precision theater**: Saying "47 hours" when you mean "roughly a week." False precision erodes trust faster than honest ranges.
45
+ Compare estimated vs actual each sprint, look for systematic bias, and recalibrate
46
+ velocity on the last 3-5 sprints, not the all-time average.
90
47
 
91
48
  ## Principles Applied
92
49