skilldrop-cli 0.2.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.
Files changed (226) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +413 -0
  3. package/bin/skilldrop.js +338 -0
  4. package/model-routing.json +147 -0
  5. package/package.json +36 -0
  6. package/packs.json +90 -0
  7. package/skills/accessibility-audit/SKILL.md +74 -0
  8. package/skills/accessibility-audit/examples/login-form.md +76 -0
  9. package/skills/accessibility-audit/manifest.json +11 -0
  10. package/skills/accessibility-audit/reference.md +69 -0
  11. package/skills/adr-generator/SKILL.md +49 -0
  12. package/skills/adr-generator/manifest.json +11 -0
  13. package/skills/adr-generator/templates/madr.md +56 -0
  14. package/skills/adr-generator/templates/nygard.md +19 -0
  15. package/skills/ai-usage-report/SKILL.md +111 -0
  16. package/skills/ai-usage-report/examples/weekly-engineering-team.md +133 -0
  17. package/skills/ai-usage-report/manifest.json +11 -0
  18. package/skills/ai-usage-report/scripts/build_report.py +436 -0
  19. package/skills/ai-usage-report/templates/report-per-user.md +42 -0
  20. package/skills/ai-usage-report/templates/report-team-rollup.md +49 -0
  21. package/skills/ai-usage-report/templates/usage-event-schema.md +76 -0
  22. package/skills/api-contract-draft/SKILL.md +69 -0
  23. package/skills/api-contract-draft/manifest.json +11 -0
  24. package/skills/api-contract-draft/reference.md +73 -0
  25. package/skills/api-contract-draft/templates/openapi-skeleton.yaml +148 -0
  26. package/skills/architecture-diagrams/SKILL.md +66 -0
  27. package/skills/architecture-diagrams/examples/aws-three-tier.md +44 -0
  28. package/skills/architecture-diagrams/examples/c4-container-saas.md +51 -0
  29. package/skills/architecture-diagrams/examples/microservices-sequence.md +49 -0
  30. package/skills/architecture-diagrams/manifest.json +28 -0
  31. package/skills/architecture-diagrams/templates/c4-container.puml +31 -0
  32. package/skills/architecture-diagrams/templates/mermaid-aws.md +52 -0
  33. package/skills/architecture-diagrams/templates/mermaid-flowchart.md +37 -0
  34. package/skills/architecture-diagrams/templates/mermaid-sequence.md +39 -0
  35. package/skills/audience-profile/SKILL.md +73 -0
  36. package/skills/audience-profile/manifest.json +11 -0
  37. package/skills/audience-profile/reference.md +175 -0
  38. package/skills/brief-intake/SKILL.md +78 -0
  39. package/skills/brief-intake/manifest.json +11 -0
  40. package/skills/brief-intake/templates/brief-adr.md +41 -0
  41. package/skills/brief-intake/templates/brief-decision-log.md +35 -0
  42. package/skills/brief-intake/templates/brief-deck.md +43 -0
  43. package/skills/brief-intake/templates/brief-design-doc.md +48 -0
  44. package/skills/brief-intake/templates/brief-exec-summary.md +47 -0
  45. package/skills/brief-intake/templates/brief-generic.md +45 -0
  46. package/skills/brief-intake/templates/brief-runbook.md +44 -0
  47. package/skills/brief-intake/templates/brief-tech-comparison.md +38 -0
  48. package/skills/bug-triage/SKILL.md +67 -0
  49. package/skills/bug-triage/manifest.json +11 -0
  50. package/skills/bug-triage/templates/bug-ticket.md +86 -0
  51. package/skills/business-case/SKILL.md +64 -0
  52. package/skills/business-case/manifest.json +11 -0
  53. package/skills/business-case/templates/business-case.md +60 -0
  54. package/skills/capacity-cost-model/SKILL.md +64 -0
  55. package/skills/capacity-cost-model/manifest.json +11 -0
  56. package/skills/capacity-cost-model/reference.md +54 -0
  57. package/skills/capacity-cost-model/templates/cost-model.md +68 -0
  58. package/skills/council-review/SKILL.md +106 -0
  59. package/skills/council-review/examples/redis-cache-decision.md +75 -0
  60. package/skills/council-review/manifest.json +11 -0
  61. package/skills/council-review/reference.md +76 -0
  62. package/skills/council-review/seats/architect.md +29 -0
  63. package/skills/council-review/seats/bench.md +39 -0
  64. package/skills/council-review/seats/operator.md +27 -0
  65. package/skills/council-review/seats/pragmatist.md +29 -0
  66. package/skills/council-review/seats/security-engineer.md +29 -0
  67. package/skills/council-review/seats/user-advocate.md +27 -0
  68. package/skills/council-review/templates/council-review.md +59 -0
  69. package/skills/data-contract/SKILL.md +67 -0
  70. package/skills/data-contract/manifest.json +11 -0
  71. package/skills/data-contract/reference.md +46 -0
  72. package/skills/data-contract/templates/data-contract.md +69 -0
  73. package/skills/db-schema-design/SKILL.md +68 -0
  74. package/skills/db-schema-design/manifest.json +11 -0
  75. package/skills/db-schema-design/reference.md +56 -0
  76. package/skills/db-schema-design/templates/schema-design.md +75 -0
  77. package/skills/decision-log/SKILL.md +67 -0
  78. package/skills/decision-log/manifest.json +11 -0
  79. package/skills/deck-builder/SKILL.md +114 -0
  80. package/skills/deck-builder/examples/exec-board-update.md +108 -0
  81. package/skills/deck-builder/manifest.json +17 -0
  82. package/skills/deck-builder/reference.md +92 -0
  83. package/skills/deck-builder/requirements.txt +1 -0
  84. package/skills/deck-builder/scripts/build_deck.py +309 -0
  85. package/skills/deck-builder/templates/deck-spec.json +97 -0
  86. package/skills/deck-builder/templates/palettes.json +59 -0
  87. package/skills/design-doc/SKILL.md +49 -0
  88. package/skills/design-doc/manifest.json +11 -0
  89. package/skills/design-doc/templates/design-doc.md +98 -0
  90. package/skills/devils-advocate/SKILL.md +142 -0
  91. package/skills/devils-advocate/lenses/adversarial-review.md +88 -0
  92. package/skills/devils-advocate/lenses/edge-cases.md +95 -0
  93. package/skills/devils-advocate/lenses/future-proofing.md +75 -0
  94. package/skills/devils-advocate/lenses/test-coverage.md +90 -0
  95. package/skills/devils-advocate/manifest.json +11 -0
  96. package/skills/devils-advocate/templates/challenge.md +118 -0
  97. package/skills/doc-critique/SKILL.md +119 -0
  98. package/skills/doc-critique/manifest.json +11 -0
  99. package/skills/doc-critique/rubrics/adr.md +36 -0
  100. package/skills/doc-critique/rubrics/decision-log.md +39 -0
  101. package/skills/doc-critique/rubrics/deck.md +45 -0
  102. package/skills/doc-critique/rubrics/design-doc.md +42 -0
  103. package/skills/doc-critique/rubrics/exec-summary.md +41 -0
  104. package/skills/doc-critique/rubrics/generic.md +40 -0
  105. package/skills/doc-critique/rubrics/runbook.md +42 -0
  106. package/skills/doc-critique/rubrics/tech-comparison.md +40 -0
  107. package/skills/doc-critique/templates/critique.md +49 -0
  108. package/skills/exec-summary/SKILL.md +45 -0
  109. package/skills/exec-summary/manifest.json +11 -0
  110. package/skills/exec-summary/templates/exec-summary.md +48 -0
  111. package/skills/feature-implement-loop/SKILL.md +83 -0
  112. package/skills/feature-implement-loop/manifest.json +11 -0
  113. package/skills/figma-diagrams/SKILL.md +85 -0
  114. package/skills/figma-diagrams/manifest.json +35 -0
  115. package/skills/figma-diagrams/reference.md +91 -0
  116. package/skills/figma-diagrams/requirements.txt +1 -0
  117. package/skills/figma-diagrams/scripts/_figma_client.py +71 -0
  118. package/skills/figma-diagrams/scripts/frame_to_mermaid.py +102 -0
  119. package/skills/figma-diagrams/scripts/inspect_file.py +46 -0
  120. package/skills/figma-diagrams/scripts/list_comments.py +35 -0
  121. package/skills/figma-diagrams/scripts/post_comment.py +52 -0
  122. package/skills/figma-diagrams/templates/figjam-import.json +20 -0
  123. package/skills/guide-builder/SKILL.md +76 -0
  124. package/skills/guide-builder/examples/local-setup-guide.md +127 -0
  125. package/skills/guide-builder/manifest.json +11 -0
  126. package/skills/guide-builder/templates/api-reference.md +120 -0
  127. package/skills/guide-builder/templates/design-walkthrough.md +72 -0
  128. package/skills/guide-builder/templates/setup-guide.md +109 -0
  129. package/skills/incident-comms/SKILL.md +68 -0
  130. package/skills/incident-comms/manifest.json +11 -0
  131. package/skills/incident-comms/reference.md +43 -0
  132. package/skills/incident-comms/templates/messages.md +82 -0
  133. package/skills/llm-eval-harness/SKILL.md +73 -0
  134. package/skills/llm-eval-harness/manifest.json +11 -0
  135. package/skills/llm-eval-harness/reference.md +58 -0
  136. package/skills/llm-eval-harness/templates/eval-plan.md +63 -0
  137. package/skills/llm-eval-harness/templates/golden-case.jsonl +5 -0
  138. package/skills/migration-plan/SKILL.md +68 -0
  139. package/skills/migration-plan/manifest.json +11 -0
  140. package/skills/migration-plan/templates/migration-plan.md +68 -0
  141. package/skills/nfr-spec/SKILL.md +63 -0
  142. package/skills/nfr-spec/manifest.json +11 -0
  143. package/skills/nfr-spec/reference.md +74 -0
  144. package/skills/nfr-spec/templates/nfr-spec.md +56 -0
  145. package/skills/observability-plan/SKILL.md +70 -0
  146. package/skills/observability-plan/manifest.json +11 -0
  147. package/skills/observability-plan/reference.md +67 -0
  148. package/skills/observability-plan/templates/observability-plan.md +62 -0
  149. package/skills/okr-cascade/SKILL.md +59 -0
  150. package/skills/okr-cascade/evals/eval_queries.json +12 -0
  151. package/skills/okr-cascade/evals/evals.json +28 -0
  152. package/skills/okr-cascade/manifest.json +11 -0
  153. package/skills/okr-cascade/templates/okr-cascade.md +46 -0
  154. package/skills/postmortem-generator/SKILL.md +65 -0
  155. package/skills/postmortem-generator/manifest.json +11 -0
  156. package/skills/postmortem-generator/templates/postmortem.md +67 -0
  157. package/skills/prd-draft/SKILL.md +62 -0
  158. package/skills/prd-draft/manifest.json +11 -0
  159. package/skills/prd-draft/templates/prd.md +66 -0
  160. package/skills/prfaq/SKILL.md +75 -0
  161. package/skills/prfaq/evals/eval_queries.json +13 -0
  162. package/skills/prfaq/evals/evals.json +32 -0
  163. package/skills/prfaq/manifest.json +11 -0
  164. package/skills/prfaq/templates/prfaq.md +60 -0
  165. package/skills/release-notes/SKILL.md +61 -0
  166. package/skills/release-notes/manifest.json +11 -0
  167. package/skills/release-notes/templates/release-notes.md +83 -0
  168. package/skills/requirements-interview/SKILL.md +61 -0
  169. package/skills/requirements-interview/manifest.json +11 -0
  170. package/skills/requirements-interview/templates/interview-kit.md +63 -0
  171. package/skills/reverse-architecture/SKILL.md +103 -0
  172. package/skills/reverse-architecture/manifest.json +11 -0
  173. package/skills/reverse-architecture/reference.md +150 -0
  174. package/skills/reverse-architecture/templates/description.md +52 -0
  175. package/skills/reverse-architecture/templates/extraction.md +55 -0
  176. package/skills/runbook-generator/SKILL.md +42 -0
  177. package/skills/runbook-generator/manifest.json +11 -0
  178. package/skills/runbook-generator/templates/runbook.md +109 -0
  179. package/skills/slide-outliner/SKILL.md +58 -0
  180. package/skills/slide-outliner/manifest.json +11 -0
  181. package/skills/slide-outliner/templates/deck-outline.md +131 -0
  182. package/skills/sonar-onboard/SKILL.md +170 -0
  183. package/skills/sonar-onboard/manifest.json +11 -0
  184. package/skills/sonar-onboard/reference.md +151 -0
  185. package/skills/sonar-onboard/templates/github-actions-sonar-server.yml.tmpl +50 -0
  186. package/skills/sonar-onboard/templates/github-actions-sonarcloud.yml.tmpl +53 -0
  187. package/skills/sonar-onboard/templates/readme-snippet.md +38 -0
  188. package/skills/sonar-onboard/templates/sonar-project.properties.tmpl +31 -0
  189. package/skills/sonar-review/SKILL.md +220 -0
  190. package/skills/sonar-review/lenses/bugs.md +48 -0
  191. package/skills/sonar-review/lenses/code-smells.md +64 -0
  192. package/skills/sonar-review/lenses/coverage-and-duplication.md +74 -0
  193. package/skills/sonar-review/lenses/security-hotspots.md +56 -0
  194. package/skills/sonar-review/lenses/vulnerabilities.md +52 -0
  195. package/skills/sonar-review/manifest.json +37 -0
  196. package/skills/sonar-review/reference.md +167 -0
  197. package/skills/sonar-review/templates/report.md +84 -0
  198. package/skills/strategy-analysis/SKILL.md +63 -0
  199. package/skills/strategy-analysis/evals/eval_queries.json +13 -0
  200. package/skills/strategy-analysis/evals/evals.json +36 -0
  201. package/skills/strategy-analysis/manifest.json +11 -0
  202. package/skills/success-metrics/SKILL.md +63 -0
  203. package/skills/success-metrics/evals/eval_queries.json +11 -0
  204. package/skills/success-metrics/evals/evals.json +27 -0
  205. package/skills/success-metrics/manifest.json +11 -0
  206. package/skills/success-metrics/templates/metrics-plan.md +55 -0
  207. package/skills/tech-comparison-matrix/SKILL.md +56 -0
  208. package/skills/tech-comparison-matrix/manifest.json +11 -0
  209. package/skills/tech-comparison-matrix/templates/matrix.md +45 -0
  210. package/skills/test-plan-generator/SKILL.md +59 -0
  211. package/skills/test-plan-generator/manifest.json +11 -0
  212. package/skills/test-plan-generator/templates/test-plan.md +83 -0
  213. package/skills/threat-model/SKILL.md +65 -0
  214. package/skills/threat-model/examples/document-upload.md +56 -0
  215. package/skills/threat-model/manifest.json +11 -0
  216. package/skills/threat-model/reference.md +69 -0
  217. package/skills/user-journey-map/SKILL.md +64 -0
  218. package/skills/user-journey-map/evals/eval_queries.json +12 -0
  219. package/skills/user-journey-map/evals/evals.json +30 -0
  220. package/skills/user-journey-map/examples/b2b-saas-onboarding.md +69 -0
  221. package/skills/user-journey-map/manifest.json +11 -0
  222. package/skills/user-journey-map/templates/journey-map.md +47 -0
  223. package/skills/user-story-splitter/SKILL.md +88 -0
  224. package/skills/user-story-splitter/examples/notifications-epic.md +123 -0
  225. package/skills/user-story-splitter/manifest.json +11 -0
  226. package/skills/user-story-splitter/templates/story.md +40 -0
@@ -0,0 +1,52 @@
1
+ # Lens 2 — Vulnerabilities
2
+
3
+ Sonar's **Vulnerability** category is code where **Sonar is confident an attacker can exploit it**: injection, weak crypto, hard-coded secrets, broken auth flows, unsafe deserialization. Different from **Hotspots** (lens 3) — Hotspots are "this *could* be unsafe, a human needs to look"; Vulnerabilities are "this *is* unsafe by the catalog's definition".
4
+
5
+ Every Vulnerability on new code is a **gate failure** under the default Sonar way. Treat as merge-blocking.
6
+
7
+ ## What you're looking at
8
+
9
+ Pull the issues list, filter to `type=VULNERABILITY`, intersect with changed files. Common rule families:
10
+
11
+ | Family | Example IDs | What it catches |
12
+ |---|---|---|
13
+ | SQL injection | `javascript:S3649`, `java:S3649`, `python:S3649` | String-concatenated queries |
14
+ | Command injection | `S2076`, `S4036` | `exec(\`tar ${user}\`)`, `Runtime.exec(userInput)` |
15
+ | Path traversal | `S2083`, `S6549` | `fs.readFile(userInput)` without normalization |
16
+ | XSS | `javascript:S5247`, `S5131` | `innerHTML = userInput`, unescaped template output |
17
+ | SSRF | `S5144` | HTTP client URL built from user input |
18
+ | Hard-coded secrets | `S6418`, `S2068` | API keys, passwords, tokens in source |
19
+ | Weak crypto | `S2278`, `S5547`, `S4790` | MD5/SHA1 for auth, ECB mode, deprecated TLS |
20
+ | Insecure cookie | `S2092`, `S3330` | `httpOnly: false`, missing `secure` flag |
21
+ | Open redirect | `javascript:S5146` | `res.redirect(userInput)` |
22
+ | Unsafe deserialization | `S5135` | `pickle.loads(network_bytes)`, Java `ObjectInputStream` |
23
+ | Permissive CORS | `S5122` | `Access-Control-Allow-Origin: *` with credentials |
24
+
25
+ Every Vulnerability rule is tagged with **CWE** and (where applicable) **OWASP Top 10** identifiers — surface these in the finding so the user can map to compliance frameworks.
26
+
27
+ ## How to phrase each finding
28
+
29
+ 1. **Where** — `file:line` + the offending expression. Quote enough to make the data flow obvious.
30
+ 2. **Rule + category + standards tags** — `[VULNERABILITY · javascriptsecurity:S3649 · CWE-89 · OWASP A03:2021] SQL injection`.
31
+ 3. **Why it matters** — describe the **exploit path**, not the rule. ✅ "`userId` flows from `req.params.id` into the SQL string at line 42 without escaping — an attacker can send `1 OR 1=1` and read every row of the table." ❌ "Possible SQL injection."
32
+ 4. **Fix** — concrete and **the right one**:
33
+ - SQL injection → parameterized query / prepared statement, with a code snippet using the project's existing DB client. Quote the right call from elsewhere in the codebase if available.
34
+ - Command injection → `execFile(cmd, [args])` not `exec(cmd + args)`; never `shell: true` with user data.
35
+ - XSS → contextual escaping (text vs attribute vs URL vs JS), or the framework's safe primitive (`.textContent` not `.innerHTML`; `{}` not `{{{}}}`).
36
+ - Hard-coded secret → move to env/secret manager, **rotate the leaked value**, and call out the rotation explicitly — finding it in source means it was committed and is in git history.
37
+ - Weak crypto → name the replacement algorithm (e.g. `SHA-256 + HMAC`, `bcrypt/argon2`, `AES-256-GCM`).
38
+
39
+ ## Calibration
40
+
41
+ - **BLOCKER vulnerability** — direct injection / hard-coded prod credential / known-broken crypto on auth. Stop the merge; in some cases stop the deploy (rotate creds, audit access).
42
+ - **CRITICAL vulnerability** — exploit requires a slightly less trivial path (chained, requires auth, narrow window). Fix before merge.
43
+ - **MAJOR vulnerability** — defense-in-depth issue (missing flag, weak default). Fix before merge if reasonable.
44
+
45
+ Do not down-grade these. If you think Sonar is wrong, mark it for the user to dispute via the Sonar UI (`Resolve as won't fix` / `false positive`) — don't silently drop it from the report.
46
+
47
+ ## Anti-patterns when reporting Vulnerabilities
48
+
49
+ - ❌ Suggesting input validation as the fix for injection. Validation is defense in depth; **parameterization** is the fix. ❌ "Validate the user ID looks like a number." ✅ "Use `db.query('SELECT * FROM users WHERE id = $1', [userId])` — never concatenate."
50
+ - ❌ Forgetting the rotation step on a leaked secret. If a key was in source, it leaked; "remove the line" without "rotate the value" leaves the exposure live.
51
+ - ❌ Listing the rule's CWE without using it. The CWE tag is for the user's report, not your decoration — include it so they can answer "is this our SOC 2 finding?".
52
+ - ❌ Recommending the user mark it "won't fix" to pass the gate. The gate is the point. If it's truly a false positive, the resolution path is via the Sonar UI's `false positive` workflow, with a comment — not a CI-bypass.
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "sonar-review",
3
+ "version": "0.1.0",
4
+ "description": "Run a Sonar scan against the just-changed code on the current branch and produce a structured compliance report — quality-gate verdict (PASS / FAIL), then severity-tagged findings (🟥 blocker / 🟧 critical / 🟨 major / ⚪ minor / ⚪ info) scoped to changed files, each with file:line, the Sonar rule ID, the category (bug / vulnerability / security hotspot / code smell), why it matters, and a concrete fix. Works against both **SonarQube server** (self-hosted) and **SonarCloud** (SaaS) — mode is detected from `sonar-project.properties`. Sister skill to `devils-advocate`, but enforces Sonar's rule catalog and the project's quality gate rather than a hand-rolled lens sweep. Use after writing code, before pushing or opening a PR, when the user says \"is this Sonar-compliant?\", \"run Sonar on this\", \"will the quality gate pass?\", or any pre-merge compliance check.",
5
+ "entrypoint": "SKILL.md",
6
+ "deps": {
7
+ "npm": [],
8
+ "pip": []
9
+ },
10
+ "env": {
11
+ "required": [
12
+ "SONAR_TOKEN"
13
+ ],
14
+ "optional": [
15
+ "SONAR_HOST_URL"
16
+ ]
17
+ },
18
+ "related": [
19
+ "devils-advocate",
20
+ "sonar-onboard"
21
+ ],
22
+ "tags": [
23
+ "sonarqube",
24
+ "sonarcloud",
25
+ "sonar",
26
+ "code-quality",
27
+ "review",
28
+ "quality-gate",
29
+ "compliance",
30
+ "security",
31
+ "dev-workflow"
32
+ ],
33
+ "model": {
34
+ "tier": "standard",
35
+ "rationale": "Formats Sonar API findings into a report. The hard analysis is Sonar's; this is synthesis. Escalates on very large diffs."
36
+ }
37
+ }
@@ -0,0 +1,167 @@
1
+ # sonar-review — reference
2
+
3
+ Long-form material that doesn't belong in `SKILL.md`.
4
+
5
+ ## SonarQube server vs SonarCloud — what changes for this skill
6
+
7
+ Almost nothing. The API endpoints used here (`/api/qualitygates/project_status`, `/api/issues/search`, `/api/hotspots/search`) are identical in shape on both, authenticated the same way (`Authorization: Bearer $SONAR_TOKEN` or basic auth with the token as username). Only the host differs:
8
+
9
+ | Mode | `$SONAR_HOST` |
10
+ |---|---|
11
+ | SonarQube server | `$SONAR_HOST_URL` (from env) |
12
+ | SonarCloud | `https://sonarcloud.io` (fixed) |
13
+
14
+ Mode is detected from `sonar-project.properties` — presence of `sonar.organization=<key>` means SonarCloud; absence means server. Don't ask the user; the properties file is canonical.
15
+
16
+ Two behaviors that *do* differ:
17
+
18
+ - **Branch analysis** — SonarCloud supports branch + PR analysis on all tiers. SonarQube Community Edition does not. If you set `sonar.branch.name` and the server returns `License not valid for branch analysis`, you're on Community Edition. Re-run without the flag; the scan will overwrite the default-branch history, which is acceptable for a local pre-merge check but not for CI.
19
+ - **PR decoration** — SonarCloud auto-decorates the PR with findings if `GITHUB_TOKEN` is in the workflow env. Self-hosted needs ALM integration set up server-side. This skill doesn't touch PR decoration, but if the user asks why findings aren't appearing on the PR even though the scan ran, it's usually this.
20
+
21
+ ## SonarQube API shapes you'll parse
22
+
23
+ ### `/api/qualitygates/project_status`
24
+
25
+ ```json
26
+ {
27
+ "projectStatus": {
28
+ "status": "ERROR", // or "OK"
29
+ "conditions": [
30
+ {
31
+ "status": "ERROR",
32
+ "metricKey": "new_coverage",
33
+ "comparator": "LT",
34
+ "errorThreshold": "80",
35
+ "actualValue": "71.4"
36
+ },
37
+ {
38
+ "status": "OK",
39
+ "metricKey": "new_bugs",
40
+ "comparator": "GT",
41
+ "errorThreshold": "0",
42
+ "actualValue": "0"
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ ```
48
+
49
+ `status` is the gate verdict (`OK` / `ERROR`). `conditions` is the per-rule breakdown — list the `ERROR` ones in the report's gate-conditions table.
50
+
51
+ ### `/api/issues/search`
52
+
53
+ ```json
54
+ {
55
+ "issues": [
56
+ {
57
+ "key": "AYz1...",
58
+ "rule": "javascript:S2259",
59
+ "severity": "CRITICAL",
60
+ "type": "BUG",
61
+ "component": "myorg_payments:src/api/checkout.ts",
62
+ "line": 47,
63
+ "message": "Refactor this code to not use null dereference.",
64
+ "status": "OPEN",
65
+ "tags": ["cwe"]
66
+ }
67
+ ],
68
+ "paging": { "total": 42, "pageIndex": 1, "pageSize": 100 }
69
+ }
70
+ ```
71
+
72
+ `component` includes the project key prefix — strip it to get the file path. `severity` is one of `BLOCKER` / `CRITICAL` / `MAJOR` / `MINOR` / `INFO`. `type` is one of `BUG` / `VULNERABILITY` / `CODE_SMELL` (hotspots come from a different endpoint).
73
+
74
+ ### `/api/hotspots/search`
75
+
76
+ ```json
77
+ {
78
+ "hotspots": [
79
+ {
80
+ "key": "AYz2...",
81
+ "component": "myorg_payments:src/jobs/export.ts",
82
+ "line": 28,
83
+ "ruleKey": "javascript:S2076",
84
+ "vulnerabilityProbability": "HIGH", // HIGH / MEDIUM / LOW — maps to review priority
85
+ "status": "TO_REVIEW", // TO_REVIEW / REVIEWED
86
+ "message": "Make sure that executing this OS command is safe here."
87
+ }
88
+ ]
89
+ }
90
+ ```
91
+
92
+ Hotspots **don't** appear in `/api/issues/search`. Forgetting to call this endpoint silently drops the security-hotspot lens.
93
+
94
+ ## Maven / Gradle / dotnet wrappers
95
+
96
+ If `sonar-project.properties` references the standalone scanner but the project has `pom.xml`, `build.gradle`, or a `.sln`, prefer the language-native wrapper — it hooks into the compile step and produces better analysis:
97
+
98
+ | Project type | Command |
99
+ |---|---|
100
+ | Maven | `mvn -B verify sonar:sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.token=$SONAR_TOKEN` |
101
+ | Gradle | `./gradlew build sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.token=$SONAR_TOKEN` |
102
+ | .NET | `dotnet sonarscanner begin /k:"<key>" /d:sonar.host.url=$SONAR_HOST_URL /d:sonar.token=$SONAR_TOKEN` → `dotnet build` → `dotnet sonarscanner end /d:sonar.token=$SONAR_TOKEN` |
103
+
104
+ The standalone `sonar-scanner` still works for these but won't see compile-time information (type resolution, framework attributes). Findings will be shallower.
105
+
106
+ ## Scoping to PR diff
107
+
108
+ The skill scopes the **report** to changed files, not the scan itself. To compute the changed files:
109
+
110
+ ```bash
111
+ # vs origin/main (most PRs)
112
+ git diff --name-only origin/main...HEAD
113
+
114
+ # vs the previous commit (just-pushed work)
115
+ git diff --name-only HEAD~1
116
+ ```
117
+
118
+ When filtering issues, normalize the Sonar `component` field (`<projectKey>:<path>`) against your diff list. Strip the project-key prefix; compare paths.
119
+
120
+ **Don't filter the scan**. `sonar-scanner` analyzes the whole project because cross-file analysis (call graphs, import resolution) requires it. You filter the *findings* on the way out.
121
+
122
+ ## Running against the SonarQube server with `branch` analysis
123
+
124
+ The SonarQube Developer Edition+ supports branch analysis natively — pass `-Dsonar.branch.name=<branch>`. Community Edition does **not**. If the Sonar server returns:
125
+
126
+ ```
127
+ ERROR: License not valid for branch analysis. Branches will not be analyzed.
128
+ ```
129
+
130
+ … the project is on Community Edition. Workarounds:
131
+
132
+ - Use the **`sonar.projectVersion`** trick — set `projectVersion=<branch>` to get separate histories per branch (crude but works on CE).
133
+ - Scan only on merge to `main` (PR-time scanning unavailable on CE).
134
+ - Upgrade to Developer Edition if branch analysis is required.
135
+
136
+ Document the edition limitation in the report — don't pretend the missing branch view is a configuration issue.
137
+
138
+ ## Polling the scan task
139
+
140
+ `sonar-scanner` returns once it uploads to the server, but the gate isn't computed until the server processes the task. After the scanner finishes:
141
+
142
+ ```bash
143
+ TASK_URL=$(grep '^ceTaskUrl=' .scannerwork/report-task.txt | cut -d= -f2-)
144
+
145
+ # Poll until status=SUCCESS (or FAILED)
146
+ while true; do
147
+ STATUS=$(curl -s -u "$SONAR_TOKEN:" "$TASK_URL" | jq -r '.task.status')
148
+ case "$STATUS" in
149
+ SUCCESS) break ;;
150
+ FAILED|CANCELED) echo "Scan task failed: $STATUS"; exit 1 ;;
151
+ *) sleep 5 ;;
152
+ esac
153
+ done
154
+ ```
155
+
156
+ Skipping this means the gate API returns stale data from the *previous* scan, not this one. Always poll.
157
+
158
+ ## Common false positives worth knowing
159
+
160
+ | Rule | Common false positive | What to do |
161
+ |---|---|---|
162
+ | `javascript:S2068` (hard-coded password) | Variable named `password` in a Zod/Joi schema definition | Mark `false positive` in Sonar UI |
163
+ | `python:S5689` (use of `eval`) | `ast.literal_eval` (safe) flagged alongside `eval` | Confirm `literal_eval`, ignore |
164
+ | `java:S3776` (cognitive complexity) | Big `switch` over an enum | Extract per-case handlers if it improves things; otherwise dispute |
165
+ | `csharpsquid:S1135` (TODO comment) | TODOs intentionally tracked in code | Roll up the count, don't list each |
166
+
167
+ These are dispositions to suggest, **not** to apply silently. The user marks them in Sonar UI; you surface them in the report so they know which to look at.
@@ -0,0 +1,84 @@
1
+ # Sonar review: {feature / PR title}
2
+ _Scope: {N changed files, M lines added/removed} · Branch: `{branch}` · Scanned: {YYYY-MM-DD HH:MM} · Scan duration: {Ns}_
3
+ _Sonar project: [`{project-key}`]({sonar-host}/dashboard?id={project-key}&branch={branch})_
4
+
5
+ ## Quality gate
6
+
7
+ **{✅ PASS / ❌ FAIL}** — {one-line reason — what failed (or "all conditions met")}
8
+
9
+ {2–3 sentence summary. Lead with what failed the gate. If PASS, say so plainly and call out the closest condition to the line.}
10
+
11
+ ### Gate conditions
12
+
13
+ | Condition | Actual | Threshold | Status |
14
+ |---|---|---|---|
15
+ | New bugs | {N} | 0 | ✅ / ❌ |
16
+ | New vulnerabilities | {N} | 0 | ✅ / ❌ |
17
+ | New security hotspots reviewed | {pct}% | 100% | ✅ / ❌ |
18
+ | Coverage on new code | {pct}% | ≥ 80% | ✅ / ❌ |
19
+ | Duplicated lines on new code | {pct}% | ≤ 3% | ✅ / ❌ |
20
+
21
+ (Drop rows the project's gate doesn't enforce.)
22
+
23
+ ## Findings on changed code
24
+
25
+ | Severity | Bugs | Vulnerabilities | Hotspots | Code smells |
26
+ |---|---|---|---|---|
27
+ | 🟥 Blocker | {N} | {N} | — | {N} |
28
+ | 🟧 Critical | {N} | {N} | {N} | {N} |
29
+ | 🟨 Major | {N} | {N} | {N} | {N} |
30
+ | ⚪ Minor | {N} | — | — | {N} |
31
+ | ⚪ Info | {N} | — | — | {N} |
32
+
33
+ ### 1. Bugs
34
+
35
+ {For each finding:}
36
+
37
+ #### 🟥 [`javascript:S2259`] TypeError on null dereference
38
+ - **Where:** `src/api/checkout.ts:47` — `discount.amount`
39
+ - **Why it matters:** When `discount=null` reaches line 47, `applyDiscount` throws `TypeError` — the request returns a 500, not a graceful "no discount applied".
40
+ - **Fix:** Add `if (discount == null) return 0;` at the top of `applyDiscount`, matching the pattern in `applyTax` at line 102.
41
+
42
+ {If no findings: "No bugs flagged on changed code."}
43
+
44
+ ### 2. Vulnerabilities
45
+ ### 3. Security hotspots
46
+
47
+ {Hotspots are review-required, not auto-fix. Each one:}
48
+
49
+ #### 🟧 [`javascript:S2076`] OS command construction from user input
50
+ - **Where:** `src/jobs/export.ts:28` — `exec(\`tar -czf ${userPath}\`)`
51
+ - **Why it matters:** `userPath` flows from the export API without escaping — if an attacker controls the export name, they can inject shell metacharacters.
52
+ - **Evidence for review:** `userPath` is validated upstream in `validateExportName` (`src/api/exports.ts:14`) to match `/^[a-zA-Z0-9_-]+$/` — that *should* make injection impossible, but the validation runs in a separate process and the variable name is reused.
53
+ - **Action:** Mark **Safe** if you confirm the upstream validation is enforced on every code path that hits this exec; otherwise mark **At Risk** and switch to `execFile` with an args array.
54
+
55
+ ### 4. Code smells
56
+ ### 5. Coverage + duplication
57
+
58
+ #### ❌ Coverage on new code: 71% (gate requires ≥ 80%)
59
+ - **Where:** `src/jobs/export.ts` — 47/82 new lines covered; `src/api/checkout.ts` — 31/40 new lines covered.
60
+ - **Why it matters:** The two uncovered branches in `export.ts` are the error paths (lines 55–62, 71–78) — exactly where regressions hide.
61
+ - **Fix:** Add three tests — happy path is covered; add cases for (a) upstream API 500, (b) empty result set, (c) `userPath` failing validation.
62
+
63
+ ## Pre-existing issues in touched files (FYI — not blocking)
64
+
65
+ {Issues that pre-date this branch but live in files you changed. For awareness; the gate doesn't enforce them.}
66
+
67
+ - ⚪ `src/api/checkout.ts:102` — [`typescript:S3776`] Cognitive complexity 18 > 15 (existing).
68
+ - ⚪ `src/api/checkout.ts:155` — [`typescript:S1192`] String literal `"USD"` duplicated 4 times (existing).
69
+
70
+ ## What's solid
71
+
72
+ - {2–4 things the change got right — patterns that survived the scan cleanly. Not flattery; signal for what to preserve.}
73
+ - New `parseDiscount` helper has 100% branch coverage and no findings — keep the test shape for the rest of the payment module.
74
+
75
+ ## Suggested order to address
76
+
77
+ 1. **Fix anything failing the quality gate** — blockers, new vulnerabilities, coverage shortfall. The PR can't merge until these are green.
78
+ 2. **Review the security hotspots** — mark each Safe / At Risk / Acknowledged in the Sonar UI. The gate counts them as unresolved until you do.
79
+ 3. **Major code smells**, prioritizing files in `src/api/` and `src/jobs/` over UI / config.
80
+ 4. **Minors and nits** if time permits, otherwise defer.
81
+
82
+ ---
83
+
84
+ Full report: {sonar-host}/dashboard?id={project-key}&branch={branch}
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: strategy-analysis
3
+ description: Run a strategy framework — SWOT/TOWS, Porter's Five Forces, or PESTLE — on a product, company, or market question, choosing the right framework for the question and forcing every cell to carry evidence and a so-what. Use when the user asks for a SWOT, a competitive/market analysis, "should we enter this market", "what's our position against X", or a macro-environment scan.
4
+ ---
5
+
6
+ # strategy-analysis
7
+
8
+ Runs the classic strategy frameworks the way a good strategist does and a bad deck doesn't: the framework is chosen to fit the question, every cell carries evidence and an implication, and the output ends in ranked, committal so-whats — not a filled-in grid. The grid is the working, never the deliverable. Sibling of `tech-comparison-matrix` (tech selection between named options) and `business-case` (a costed invest/defer decision); this skill is for the strategic question *before* options are named.
9
+
10
+ ## How to respond
11
+
12
+ 1. **Classify the question, then pick ONE framework** (two only when the question genuinely spans both, and say why):
13
+
14
+ | The question is about… | Framework |
15
+ |---|---|
16
+ | Our position: what to exploit, fix, or defend, feeding a near-term decision | **SWOT → TOWS** (SWOT alone is banned — see step 3) |
17
+ | Industry attractiveness / profit pressure: "should we enter", "why are margins thin", "can we defend" | **Porter's Five Forces** |
18
+ | Macro environment: regulation, technology shifts, demographics affecting a multi-year bet | **PESTLE** |
19
+
20
+ The user asked for a framework by name and it fits → run it. It doesn't fit → say so in one line and run the fitting framework instead — the quality bar treats a misfit framework as a category error, and a "SWOT" request that's really "should we enter this market" is Five Forces work; run the requested framework only if the user insists after the flag. Portfolio-allocation questions across many products (BCG-matrix territory) → name it, note it needs per-product market-share and growth data, and run it only if that data is supplied.
21
+
22
+ 2. **Collect the evidence base before filling anything.** Name what is known `[data: …]`, reported `[reported by …]`, drawn from general market knowledge `[market: …]`, and assumed `[assumption]`. The `[market: …]` tag exists because on a short prompt most cells are filled from the model's own market knowledge — that's legitimate, but it must stay distinguishable from the user's facts and from guesses. Ask at most 2 questions, spent on the decision the analysis feeds ("what decision does this inform, and by when?") and the competitive set ("who do customers actually compare you to?"). No decision named → the analysis has no ranking criterion; get one before proceeding. Non-interactive run (no user to ask): derive the most plausible decision from the input, state it as `[assumption]` at the top, and rank against it; none derivable → emit `BLOCKED: need the decision this analysis feeds` rather than an unranked survey.
23
+
24
+ 3. **Fill the framework with cells that pass the three tests.** Every entry must be (a) **specific** — a competitor, number, or named capability, not a category; (b) **evidenced** — carrying one of the step-2 tags; (c) **consequential** — with a one-line "so:" implication. ✅ *"S: 4,000 paying tenants' workflow data no rival can train on `[data: billing]` — so: the switching cost is the moat to invest in"* — ❌ *"S: strong team"*. Framework-specific rules:
25
+ - **SWOT** never ships alone — cross it into **TOWS** actions: S×O (attack), S×T (defend), W×O (fix to unlock), W×T (the exposed flank, named honestly). The TOWS quadrants are the output; the SWOT grid is scaffolding.
26
+ - **Five Forces**: each force gets a pressure rating (🟥 high / 🟧 medium / 🟨 low) *with the mechanism* — who holds the power and why (concentration, switching costs, differentiation, substitutes' price-performance). Rate all five; "N/A" is not a rating. Complements/platforms noted where they change the picture.
27
+ - **PESTLE**: only factors that plausibly move *this* decision within its time horizon, each with direction, timeframe, and the exposed asset. Six sections of filler is the classic failure — 3 sharp factors beat 18 generic ones; empty letters say "no material factor identified".
28
+
29
+ 4. **Rank the implications and commit.** End with **Implications, ranked** — 3–5 entries ordered by impact on the named decision, each an action-shaped sentence with an owner-shaped subject: ✅ *"Price the enterprise tier before Q3: supplier power is rising (🟥) and the S×O attack window closes when the incumbent's contract cycle renews"*. Then a one-paragraph **verdict** answering the user's actual question, taking a side, and naming what evidence would change it.
30
+
31
+ 5. **Emit in one message**: evidence base (tag summary), the framework grid(s), ranked implications, verdict. Flag every `[assumption]` that appears in a top-3 implication — those are the validation targets. Hand off: options now named and comparable → `tech-comparison-matrix`; investment decision to cost → `business-case`; product direction to test → `prfaq`.
32
+
33
+ ## Quality bar
34
+
35
+ - **The framework fits the question**, and the doc says why in one line. A SWOT that should have been Five Forces is a category error, not a style choice.
36
+ - **Every cell passes specific/evidenced/consequential.** One untagged, implication-free cell is a defect; a grid of them is a horoscope.
37
+ - **SWOT always arrives as TOWS.** Four lists with no crossings is inventory, not strategy.
38
+ - **Every Five Forces rating names the mechanism.** "Rivalry: high" without who/why is a vibe with a color.
39
+ - **The implications are ranked and action-shaped**, tied to the named decision — not "consider monitoring the competitive landscape".
40
+ - **The verdict takes a side** and names what would change it. An analysis that ends "it depends" has refused its job.
41
+
42
+ ## When to use this skill
43
+
44
+ - ✅ "Run a SWOT on our developer-tools product" (arrives as SWOT→TOWS)
45
+ - ✅ "Should we enter the SMB payroll market?" / "why are margins compressing?"
46
+ - ✅ "What macro trends threaten this 3-year platform bet?"
47
+ - ✅ A strategy offsite needs a rigorous pre-read instead of a brainstorm
48
+
49
+ ## When NOT to use this skill
50
+
51
+ - ❌ Choosing between named technologies or vendors — `tech-comparison-matrix`
52
+ - ❌ A costed build/buy/defer decision — `business-case`
53
+ - ❌ Testing a specific product concept — `prfaq`
54
+ - ❌ Quarterly goal-setting — `okr-cascade`
55
+
56
+ ## Anti-patterns to avoid
57
+
58
+ - ❌ **Framework theater.** Running all three frameworks "for completeness" — each unfits the others' question, and the reader drowns. One question, one framework, one verdict.
59
+ - ❌ **Horoscope cells.** "Strength: experienced team. Weakness: limited resources. Opportunity: growing market." True of every company that ever existed, therefore informative about none.
60
+ - ❌ **SWOT as the deliverable.** The four quadrants are raw material; the TOWS crossings are where a decision lives. Shipping the grid alone ships the homework, not the answer.
61
+ - ❌ **Unranked implications.** Ten equal-weight bullets delegate the actual judgment to the reader — the ranking *is* the analysis.
62
+ - ❌ **Threat inflation.** Every macro trend rated critical so nothing is. Severity must be calibrated to the named decision's time horizon and exposed assets.
63
+ - ❌ **Evidence-free confidence.** A verdict resting on untagged claims. The tag discipline exists so the reader can see exactly which legs are load-bearing guesses.
@@ -0,0 +1,13 @@
1
+ [
2
+ { "query": "Run a SWOT analysis on our product", "should_trigger": true },
3
+ { "query": "Should we enter the SMB payroll market?", "should_trigger": true },
4
+ { "query": "Do a Porter's Five Forces on the ride-sharing industry", "should_trigger": true },
5
+ { "query": "What macro trends could threaten our 3-year platform bet?", "should_trigger": true },
6
+ { "query": "Why are our margins compressing — analyze the competitive pressure", "should_trigger": true },
7
+ { "query": "I need a PESTLE analysis for the board offsite", "should_trigger": true },
8
+
9
+ { "query": "Compare Postgres vs DynamoDB for our new service", "should_trigger": false },
10
+ { "query": "Write a business case for acquiring this tooling vendor", "should_trigger": false },
11
+ { "query": "Write a PRFAQ for our new product idea", "should_trigger": false },
12
+ { "query": "Cascade our company OKRs down to the platform team", "should_trigger": false }
13
+ ]
@@ -0,0 +1,36 @@
1
+ {
2
+ "skill_name": "strategy-analysis",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Run a SWOT on our product: a developer-tools startup with 4,000 paying tenants, strong CI/CD integration data, a small sales team, and a well-funded incumbent (CircleCI) moving into our niche. The decision this feeds: where to focus the next two quarters.",
7
+ "assertions": [
8
+ "SWOT is crossed into TOWS quadrants (S×O, S×T, W×O, W×T) — the four raw lists are not the final output",
9
+ "Every cell is specific (names a competitor, number, or capability), carries an evidence tag ([data]/[reported]/[assumption]), and has a 'so:' implication",
10
+ "No horoscope cells like 'strong team' or 'growing market' without specifics",
11
+ "Implications section is ranked (3-5 entries) and each is action-shaped, tied to the two-quarter focus decision",
12
+ "A verdict paragraph takes a side and names what evidence would change it",
13
+ "Assumptions appearing in top-ranked implications are flagged as validation targets",
14
+ "A hand-off to tech-comparison-matrix, business-case, or prfaq is offered where apt"
15
+ ]
16
+ },
17
+ {
18
+ "id": 2,
19
+ "prompt": "Give me a SWOT to decide whether we should enter the SMB payroll market in Germany.",
20
+ "assertions": [
21
+ "The skill flags that market-entry attractiveness is a Five Forces question and suggests it before or instead of SWOT",
22
+ "If Five Forces is run, all five forces get a pressure rating with the mechanism (who holds power and why) — no force rated 'N/A'",
23
+ "The output ends with a committal verdict on entering, not 'it depends'"
24
+ ]
25
+ },
26
+ {
27
+ "id": 3,
28
+ "prompt": "[Non-interactive run — no user available to answer questions] Run a Porter's Five Forces on the European ride-sharing market. This feeds our decision on whether to expand our driver-scheduling SaaS into that segment next year.",
29
+ "assertions": [
30
+ "The skill proceeds (the decision IS named in the input) instead of blocking",
31
+ "Assumptions replacing the capped clarifying questions (e.g. competitive set) are tagged [assumption] and stated at the top",
32
+ "Market facts drawn from general knowledge are tagged [market: ...], distinguishable from user-supplied facts and assumptions"
33
+ ]
34
+ }
35
+ ]
36
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "strategy-analysis",
3
+ "version": "0.1.0",
4
+ "description": "Run a strategy framework — SWOT/TOWS, Porter's Five Forces, or PESTLE — on a product, company, or market question, choosing the right framework for the question and forcing every cell to carry evidence and a so-what. Use when the user asks for a SWOT, a competitive/market analysis, \"should we enter this market\", \"what's our position against X\", or a macro-environment scan.",
5
+ "entrypoint": "SKILL.md",
6
+ "deps": { "npm": [], "pip": [] },
7
+ "env": { "required": [], "optional": [] },
8
+ "related": ["business-case", "okr-cascade", "prfaq", "tech-comparison-matrix"],
9
+ "tags": ["strategy", "swot", "tows", "five-forces", "pestle", "competitive-analysis", "market-analysis"],
10
+ "model": { "tier": "heavy", "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." }
11
+ }
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: success-metrics
3
+ description: Define how a feature's success will be measured before it's built — one primary metric with target, timeframe, and baseline; guardrail and counter-metrics; an instrumentation plan naming every event; and a pre-committed decision rule for what happens if the target is missed. Use when the user asks "how do we know this worked", needs KPIs or success criteria for a feature, or wants a measurement/instrumentation plan before launch.
4
+ ---
5
+
6
+ # success-metrics
7
+
8
+ Answers "how will we know it worked?" *before* build, when the answer can still change what gets built — and makes the measurement honest by pre-committing the decision rule, naming the counter-metric that catches gaming, and writing the instrumentation plan so launch day isn't the day someone discovers no event fires. Expands the one-line success criteria in a `prd-draft` into the full measurement design.
9
+
10
+ ## How to respond
11
+
12
+ 1. **Extract the goal** from the PRD, brief, or conversation. Ask at most 2 questions, spent on **baseline** ("what's the number today, and where does it live?") and **decision authority** ("who acts if the target is missed?"). No goal articulated yet → stop and route to `prd-draft`; metrics for an unstated goal measure noise. Non-interactive run (no user to ask): a stated-but-vague goal gets sharpened and tagged `[assumption]`; no goal at all → emit `BLOCKED: need the feature's goal` — never invent one.
13
+
14
+ 2. **Pick exactly one primary metric.** More than one primary means none — when they diverge, nobody pre-agreed which wins. The primary is an **outcome the user experiences or the business banks**, not an output the team ships. ✅ *"Median support-ticket handle time"* — ❌ *"Number of dashboard features launched"* — ❌ *"Dashboard page views"* (attention is not outcome). Every other contender becomes a secondary, guardrail, or gets cut.
15
+
16
+ 3. **Give the primary its three numbers**: **baseline** (today's value + source; if unknown, the first milestone of the plan is *measuring it* — a target without a baseline is a guess about a guess), **target** (the value that means "worked"), **timeframe** (when judged, plus the patience window — how long after launch before the data is trusted: novelty effects, weekly cycles, cohort maturity).
17
+
18
+ 4. **Add leading indicators** — 2–3 metrics that move within days and plausibly predict the primary, each with its causal sentence: ✅ *"% of tickets where the agent opens the unified view — if agents don't adopt it, handle time can't drop"*. Leading indicators are for steering mid-flight; only the primary decides success.
19
+
20
+ 5. **Set guardrails and the counter-metric.** Guardrails: 2–4 things the feature must **not** degrade (error rate, page latency, adjacent-flow conversion, support volume), each with its current value and an alert threshold. For a **brand-new surface with no prior value** (e.g. the feature's own latency), the guardrail says "baseline measured in week 1, threshold set then" — the same escape hatch the primary metric gets; don't invent a current number that can't exist pre-launch. Counter-metric: the specific way the primary could be gamed, and the metric that catches it — ✅ *"Handle time could drop via premature ticket closure → watch reopen rate"*. A primary without a counter-metric invites exactly the behavior it can't see.
21
+
22
+ 6. **Write the instrumentation plan** — for every metric: the event name (consistent scheme, e.g. `domain.object.action`), its properties (incl. the dimensions you'll slice by: tenant, plan, platform), where it fires, and whether it **exists today or must be built**. The must-build list is a launch dependency, not a fast-follow: shipped-then-instrumented features have no week-one data and a contaminated baseline. Dashboard owner and review cadence named.
23
+
24
+ 7. **Pre-commit the decision rule.** One sentence, agreed before launch, naming the action: ✅ *"If primary improvement < 10% at day 60 with ≥70% agent adoption, we run the iteration review; < 10% with low adoption, we fix adoption first; guardrail breach at any point pauses rollout"*. Without it, every result becomes an argument and every miss becomes "directionally positive."
25
+
26
+ 8. **Emit with [`templates/metrics-plan.md`](templates/metrics-plan.md)** in one message: metric tree (primary → leading → guardrails/counter), the three numbers, instrumentation table, decision rule, and review cadence.
27
+
28
+ ## Useful references in this skill
29
+
30
+ - [`templates/metrics-plan.md`](templates/metrics-plan.md) — the metric tree, instrumentation table, and decision-rule skeleton
31
+
32
+ ## Quality bar
33
+
34
+ - **Exactly one primary metric**, and it's an outcome, not an output or a vanity count. The doc states why it was chosen over the runner-up.
35
+ - **Baseline, target, timeframe all present** — or "measure baseline" is explicitly milestone 1. No target hangs in the air.
36
+ - **Every metric maps to a named event** marked exists/must-build. A metric without an event is fiction with a chart placeholder.
37
+ - **The counter-metric names the gaming path.** "Could this number improve while the user's life gets worse?" has a written answer.
38
+ - **The decision rule is action-shaped and pre-committed** — who does what at which threshold — not "we'll review the data".
39
+ - **Guardrails have current values and alert thresholds**, so "don't degrade X" is checkable, not sentimental.
40
+
41
+ ## When to use this skill
42
+
43
+ - ✅ A PRD's goals need their full measurement design
44
+ - ✅ "How do we know this feature worked?" / "define the KPIs for X"
45
+ - ✅ Pre-launch instrumentation planning — what events must exist on day one
46
+ - ✅ Retro-fitting honest metrics onto a feature that shipped without any
47
+
48
+ ## When NOT to use this skill
49
+
50
+ - ❌ No goal exists yet — `prd-draft` first; metrics can't rescue an unstated goal
51
+ - ❌ Org/quarterly OKR setting — this skill measures one feature, not a company
52
+ - ❌ Analyzing results after the fact — this designs the measurement; analysis is a conversation with the data
53
+ - ❌ A/B-test statistics (power, sample size) — name the need, hand to the data team; don't improvise math
54
+
55
+ ## Anti-patterns to avoid
56
+
57
+ - ❌ **Twelve "key" metrics.** A dashboard where everything is key lets every outcome be declared a win. One primary; the rest serve it.
58
+ - ❌ **Targets without baselines.** "Increase activation to 40%" — from what? If today is 38%, the feature is a rounding error wearing a goal.
59
+ - ❌ **Vanity metrics as primary.** Page views, sign-ups, sessions — countable, reportable, and silent on whether anyone's life improved.
60
+ - ❌ **Instrumentation as fast-follow.** "We'll add tracking next sprint" = no week-one data, contaminated baseline, and a success debate held on vibes.
61
+ - ❌ **Post-hoc decision rules.** Deciding what the numbers must show *after* seeing them — the moment measurement becomes marketing.
62
+ - ❌ **Ignoring the patience window.** Judging at day 7 what needs a 60-day cohort — novelty spikes and weekly cycles read as signal.
63
+ - ❌ **Proxy laundering.** Using clicks as a proxy for value and then forgetting it's a proxy — label proxies as proxies, every time they're cited.
@@ -0,0 +1,11 @@
1
+ [
2
+ { "query": "How do we know this feature worked? Define the KPIs", "should_trigger": true },
3
+ { "query": "Set up success criteria and an instrumentation plan before we launch", "should_trigger": true },
4
+ { "query": "What should we measure to judge the new onboarding flow?", "should_trigger": true },
5
+ { "query": "Define the success metrics for this PRD's goals", "should_trigger": true },
6
+
7
+ { "query": "Cascade company OKRs down to the teams", "should_trigger": false },
8
+ { "query": "Analyze last month's launch results", "should_trigger": false },
9
+ { "query": "Design the eval harness for our LLM feature", "should_trigger": false },
10
+ { "query": "Calculate the sample size for this A/B test", "should_trigger": false }
11
+ ]
@@ -0,0 +1,27 @@
1
+ {
2
+ "skill_name": "success-metrics",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Define success metrics for this feature: a unified customer view for our support agents, merging tickets, orders, and chat history into one screen. Goal from the PRD: cut median ticket handle time. Current handle time lives in our Zendesk dashboard.",
7
+ "assertions": [
8
+ "Exactly one primary metric, and it is an outcome (handle time), not an output or vanity count — with the runner-up named and the choice justified",
9
+ "The primary has baseline (with source), target, and timeframe including a patience window — or measuring the baseline is explicitly milestone 1",
10
+ "2-3 leading indicators, each with a causal sentence",
11
+ "2-4 guardrails with current values and alert thresholds (or a week-1 baseline plan for brand-new surfaces)",
12
+ "A counter-metric names the specific gaming path (e.g. premature ticket closure → reopen rate)",
13
+ "Every metric maps to a named event marked exists/must-build, and must-build events are launch blockers",
14
+ "A pre-committed, action-shaped decision rule names who does what at which threshold"
15
+ ]
16
+ },
17
+ {
18
+ "id": 2,
19
+ "prompt": "[Non-interactive run — no user available to answer questions] Define success metrics.",
20
+ "assertions": [
21
+ "No metrics are invented — with no goal stated, the output is BLOCKED: need the feature's goal",
22
+ "The BLOCKED output routes to prd-draft (or names the goal as what to rerun with)",
23
+ "No primary metric, instrumentation table, or decision rule appears"
24
+ ]
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "success-metrics",
3
+ "version": "0.1.0",
4
+ "description": "Define how a feature's success will be measured before it's built — one primary metric with target, timeframe, and baseline; guardrail and counter-metrics; an instrumentation plan naming every event; and a pre-committed decision rule for what happens if the target is missed. Use when the user asks \"how do we know this worked\", needs KPIs or success criteria for a feature, or wants a measurement/instrumentation plan before launch.",
5
+ "entrypoint": "SKILL.md",
6
+ "deps": { "npm": [], "pip": [] },
7
+ "env": { "required": [], "optional": [] },
8
+ "related": ["prd-draft"],
9
+ "tags": ["metrics", "kpi", "instrumentation", "measurement", "analytics", "success-criteria"],
10
+ "model": { "tier": "standard", "rationale": "Structured measurement design; the primary-metric and counter-metric choices need judgment but the template bounds it. Escalate via ambiguous-input when the goal itself is contested." }
11
+ }