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,49 @@
1
+ ---
2
+ name: design-doc
3
+ description: Generate a Google-style engineering design doc (problem, goals/non-goals, options considered, recommended approach, risks, rollout) from a feature brief or short description. Use when the user wants to draft a design doc, technical proposal, or one-pager for an engineering review.
4
+ ---
5
+
6
+ # design-doc
7
+
8
+ You help the user turn a feature brief into a structured design doc that an engineering team can review and approve.
9
+
10
+ ## How to respond
11
+
12
+ 1. **Understand the brief.** Make sure you know:
13
+ - **What we're building** (one sentence)
14
+ - **Who's affected** (users, callers, teams)
15
+ - **Why now** (the forcing function — outage, regulatory, competitor, scaling cliff)
16
+
17
+ If any of these are missing, ask. Don't draft a design doc without a *why now*.
18
+
19
+ 2. **Default to the standard structure** in [`templates/design-doc.md`](templates/design-doc.md):
20
+ 1. Title + status (Draft / In Review / Approved) + author + date
21
+ 2. **TL;DR** — three bullets, readable in 30 seconds
22
+ 3. **Context** — why is this being proposed
23
+ 4. **Goals / Non-goals** — explicit non-goals matter as much as goals
24
+ 5. **Proposal** — the actual design (this is the longest section)
25
+ 6. **Alternatives considered** — at least 2 alternatives with why-not
26
+ 7. **Risks & mitigations**
27
+ 8. **Rollout plan** — staged rollout, feature flag, rollback criteria
28
+ 9. **Open questions**
29
+
30
+ 3. **Length discipline.** A good design doc is **2–5 pages** rendered. If you blow past that, you're either solving too many problems in one doc or writing reference material that belongs elsewhere.
31
+
32
+ 4. **Show, don't tell.** Where the design is structural, embed a Mermaid diagram (use the `architecture-diagrams` skill if needed). Where it's about flows, embed a sequence diagram. Where it's about API shape, embed a small example request/response.
33
+
34
+ 5. **End with explicit asks.** The "Open questions" section is where the doc earns its keep — list the *real* unresolved questions, with the names of people who should answer them.
35
+
36
+ ## Quality bar
37
+
38
+ - **Non-goals are real, not throat-clearing.** If your non-goals list reads "we're not solving world hunger", delete it. Good non-goals are things a reasonable reader might assume you *are* doing ("not migrating existing customers in v1").
39
+ - **Alternatives have a why-not, not just a description.** Two sentences each: what is it, why didn't we pick it.
40
+ - **Risks have mitigations.** A bare list of "things that could go wrong" is anxiety, not engineering.
41
+ - **Rollout criteria are concrete.** "We'll monitor closely" is not a criterion. "Roll forward to 100% if p99 < 80ms for 48h after 10% rollout" is.
42
+
43
+ ## Anti-patterns to avoid
44
+
45
+ - ❌ Starting with implementation detail before establishing the problem.
46
+ - ❌ "Future work" sections that double the doc length with hypotheticals.
47
+ - ❌ Using passive voice to avoid naming who owns what ("it will be deployed" — by whom?).
48
+ - ❌ Skipping the alternatives section because "we already know what to do" — this is *exactly* when a design review catches blind spots.
49
+ - ❌ More than ~5 pages. Cut, link out, or split into multiple docs.
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "design-doc",
3
+ "version": "0.1.0",
4
+ "description": "Generate a Google-style engineering design doc (problem, goals/non-goals, options considered, recommended approach, risks, rollout) from a feature brief or short description. Use when the user wants to draft a design doc, technical proposal, or one-pager for an engineering review.",
5
+ "entrypoint": "SKILL.md",
6
+ "deps": { "npm": [], "pip": [] },
7
+ "env": { "required": [], "optional": [] },
8
+ "related": ["architecture-diagrams"],
9
+ "tags": ["design-doc", "documentation", "engineering", "review"],
10
+ "model": { "tier": "standard", "rationale": "Synthesizes a design doc from a brief. Escalates to opus on big or genuinely contested inputs." }
11
+ }
@@ -0,0 +1,98 @@
1
+ # {Title — what we're building, as a noun phrase}
2
+
3
+ | Field | Value |
4
+ |---|---|
5
+ | Status | {Draft / In Review / Approved / Implemented} |
6
+ | Author(s) | {Names} |
7
+ | Reviewers | {Names — list the people whose approval you need} |
8
+ | Date | {YYYY-MM-DD} |
9
+ | Related | {Links to ADRs, prior design docs, tickets} |
10
+
11
+ ## TL;DR
12
+
13
+ - {One bullet — what we're doing}
14
+ - {One bullet — why now}
15
+ - {One bullet — what changes for callers / users}
16
+
17
+ ## Context
18
+
19
+ {Two or three paragraphs. What's the current state? What's the forcing function? Why is this design doc happening *now* rather than 6 months ago or in 6 months?}
20
+
21
+ ## Goals
22
+
23
+ - {Goal — measurable where possible: "p99 latency under 100ms"}
24
+ - {Goal}
25
+ - {Goal}
26
+
27
+ ## Non-goals
28
+
29
+ - {Non-goal — something a reasonable reader might assume is in scope but isn't, e.g. "migrating existing customers' historical data"}
30
+ - {Non-goal}
31
+
32
+ ## Proposal
33
+
34
+ {The actual design. This is the largest section. Cover:}
35
+
36
+ ### High-level architecture
37
+
38
+ {Embed a Mermaid or PlantUML diagram showing the major components and data flow. Keep it under 15 nodes.}
39
+
40
+ ```mermaid
41
+ flowchart LR
42
+ A[Component A] --> B[Component B]
43
+ B --> C[(Store)]
44
+ ```
45
+
46
+ ### Key design decisions
47
+
48
+ - **{Decision 1}:** {What we chose and the one-line why.}
49
+ - **{Decision 2}:** {What we chose and the one-line why.}
50
+ - **{Decision 3}:** {What we chose and the one-line why.}
51
+
52
+ ### API / interface
53
+
54
+ {For each new or changed endpoint, show a small example. Don't dump the OpenAPI spec — point to it instead.}
55
+
56
+ ### Data model changes
57
+
58
+ {Schema changes, migrations needed, backfill plan.}
59
+
60
+ ## Alternatives considered
61
+
62
+ ### {Alternative 1}
63
+
64
+ {2–3 sentences: what it is, why we didn't pick it.}
65
+
66
+ ### {Alternative 2}
67
+
68
+ {2–3 sentences.}
69
+
70
+ ## Risks & mitigations
71
+
72
+ | Risk | Likelihood | Impact | Mitigation |
73
+ |---|---|---|---|
74
+ | {Risk — e.g. "migration script takes longer than the maintenance window"} | M | H | {Mitigation — e.g. "rehearse on prod-shape staging; have a no-op rollback path"} |
75
+ | {Risk} | L | H | {Mitigation} |
76
+
77
+ ## Rollout plan
78
+
79
+ 1. **{Phase} — {behind feature flag, internal only}:** {Concrete criteria for advancing to next phase, e.g., "no new errors in error budget for 48h"}
80
+ 2. **{Phase} — {1% of traffic}:** {Criteria}
81
+ 3. **{Phase} — {10% / 50% / 100%}:** {Criteria}
82
+
83
+ **Rollback criteria:** {When do we revert? Be specific.}
84
+
85
+ ## Observability
86
+
87
+ - **New metrics:** {what we'll instrument}
88
+ - **New alerts:** {pages on what conditions}
89
+ - **Dashboard:** {link, or "TBD before launch"}
90
+
91
+ ## Open questions
92
+
93
+ - **{Question}** — owner: {name}, due: {date}
94
+ - **{Question}** — owner: {name}, due: {date}
95
+
96
+ ## Appendix
97
+
98
+ {Optional — link out to longer materials. Don't inline. Common contents: benchmarks, full schema diffs, security review notes.}
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: devils-advocate
3
+ description: Adversarial review of just-generated code, run *after* an agent (or human) declares a feature done. Challenges the implementation through four lenses — edge cases the first pass missed, baked-in assumptions that won't survive future requirements, what a staff engineer would push back on in code review, and test-coverage gaps for the new code paths. Produces severity-tagged findings (blocker / major / minor / nit) with file:line evidence and concrete fixes or missing test cases. Use immediately after a feature implementation or generation pass — before merging, before declaring "done", before moving to the next ticket.
4
+ ---
5
+
6
+ # devils-advocate
7
+
8
+ You play the role of a **senior engineer in code review who is trying to find what the implementation missed**. Code that "works on the happy path" is the default state of newly-generated code — your job is to challenge it through four lenses and surface what the first pass didn't think about.
9
+
10
+ This skill is the **code counterpart to [`doc-critique`](../doc-critique/SKILL.md)** — same adversarial framing, applied to code instead of artifacts.
11
+
12
+ ## When this skill runs
13
+
14
+ The trigger is **right after an agent (or human) has declared a feature done**. The implementation exists, the happy path likely works, tests may even pass — and that's exactly the moment the skill is most useful, because that's the moment everyone stops looking.
15
+
16
+ Specifically:
17
+ - ✅ After AI code generation for a feature ("here's the implementation")
18
+ - ✅ Before opening a PR / before requesting human review
19
+ - ✅ Before merging
20
+ - ✅ When the user asks "anything I might have missed?" or "is this ready to ship?"
21
+ - ❌ For a one-line fix or trivial change — overkill
22
+ - ❌ For greenfield exploration / spikes — adversarial review wastes effort on code that will be thrown away
23
+ - ❌ As a substitute for actual code review by a human — this is a *pre-pass*, not a replacement
24
+
25
+ ## How to respond
26
+
27
+ 1. **Identify the change under review.** In order of preference:
28
+ - The agent / user has just shown you a diff — review that diff.
29
+ - Git working tree has unstaged changes — `git diff` is the scope.
30
+ - User points to specific files / a PR / a recent commit — that's the scope.
31
+ - User says "the feature I just built" with no diff — ask which files, or run `git diff HEAD~1` if a commit was just made.
32
+
33
+ **Don't review the whole repo.** The scope is the *just-generated* code. Touched files only.
34
+
35
+ 2. **Classify the code shape.** What you challenge depends on what was built. Map to one or more:
36
+
37
+ | Shape | Lens emphasis |
38
+ |---|---|
39
+ | HTTP / RPC endpoint, API handler | edge-cases (input validation, auth), adversarial (rate limit, error mapping) |
40
+ | Async handler / queue consumer | edge-cases (retries, idempotency, poison messages), future-proofing (ordering) |
41
+ | DB migration / schema change | future-proofing (rollback, online-safe), adversarial (locking, big-table risk) |
42
+ | State machine / workflow | edge-cases (impossible transitions, concurrent updates) |
43
+ | Parser / data transformation | edge-cases (malformed, encoding, huge inputs) |
44
+ | CLI tool / script | edge-cases (missing flags, env, partial runs) |
45
+ | UI component | edge-cases (loading/empty/error states, a11y) |
46
+ | Background job / cron | edge-cases (overlap, missed runs, partial completion) |
47
+ | Library / pure function | edge-cases (boundary inputs), future-proofing (API stability) |
48
+ | Config / infra change | adversarial (blast radius), future-proofing (drift) |
49
+
50
+ Multiple shapes is common — a PR can be "endpoint + migration + UI." Apply each lens to the right slice.
51
+
52
+ 3. **Sweep the four lenses in order.** Each lens has its own checklist — read it, apply it, write findings. Don't merge lenses; each surfaces a different category of risk.
53
+
54
+ | Lens | File | Asks |
55
+ |---|---|---|
56
+ | 1. Edge cases | [`lenses/edge-cases.md`](lenses/edge-cases.md) | What inputs / states / timings break this? |
57
+ | 2. Future-proofing | [`lenses/future-proofing.md`](lenses/future-proofing.md) | What assumptions won't survive the next 6 months? |
58
+ | 3. Adversarial review | [`lenses/adversarial-review.md`](lenses/adversarial-review.md) | What would a staff engineer push back on in review? |
59
+ | 4. Test coverage | [`lenses/test-coverage.md`](lenses/test-coverage.md) | Which new code paths have no test, and which scenarios are missing tests? |
60
+
61
+ 4. **Categorize every finding by severity:**
62
+
63
+ | Severity | Meaning |
64
+ |---|---|
65
+ | 🟥 **Blocker** | This will ship a bug or a security issue. Examples: SQL injection, unhandled `null`, race condition on shared state, migration that locks a 10M-row table, missing auth check, infinite retry loop. |
66
+ | 🟧 **Major** | This will hurt within months. Examples: hard-coded limits that 2× growth will hit, no idempotency on a retryable operation, error swallowed silently, no observability for a load-bearing path, magic constants. |
67
+ | 🟨 **Minor** | Good craft. Examples: missing edge-case test, suboptimal log level, naming that won't age well, a comment that explains *what* instead of *why*. |
68
+ | ⚪ **Nit** | Style, formatting, micro-preference. Optional. |
69
+
70
+ When in doubt between two severities, **downgrade**. Inflated severity makes the report unreadable. If your output has more blockers than major findings, you're inflating.
71
+
72
+ 5. **For every finding, write four parts:**
73
+
74
+ - **Where:** `file:line` (e.g. `src/api/checkout.ts:47`) — and quote 5–15 chars of the offending line.
75
+ - **What's wrong:** one sentence — which lens fired and why.
76
+ - **Concrete scenario:** ✅ "When `discount=null` reaches line 47, `applyDiscount` throws `TypeError`." — ❌ "Doesn't handle null." A scenario the first pass can reproduce.
77
+ - **Fix:** ✅ "Add `if (discount == null) return 0;` at the top of `applyDiscount` — or thread the null through to skip the line item entirely (preferred — see how `applyTax` handles it at line 102)." — ❌ "Add null handling."
78
+
79
+ 6. **Open with a verdict, not the findings.** First thing the user sees:
80
+
81
+ ```
82
+ Verdict: SHIP WITH FIXES — 2 blockers, 5 major, 4 minor, 3 nits.
83
+
84
+ The endpoint validates auth and the happy path but doesn't bound the request body (blocker — DoS via 1GB payload), and the new migration adds a NOT NULL column without a default on a table the migration script doesn't backfill (blocker — will fail on first deploy). Of the 5 major findings, 3 are around idempotency on the retry path. Test coverage misses the new error branches at api/checkout.ts:71–88 entirely.
85
+ ```
86
+
87
+ Verdicts: `SHIP IT` · `SHIP WITH FIXES` · `DO NOT MERGE` · `RECONSIDER APPROACH`. The last is for when the implementation works but solved the wrong problem (e.g. building a custom retry queue when the framework already has one).
88
+
89
+ 7. **Output structure** — use [`templates/challenge.md`](templates/challenge.md):
90
+
91
+ ```markdown
92
+ # Devil's advocate: {feature name / PR title}
93
+ _Scope: {N files, M lines changed} · Reviewed: {YYYY-MM-DD}_
94
+
95
+ ## Verdict
96
+ {one-liner} — {N} blocker · {N} major · {N} minor · {N} nit
97
+ {3-sentence summary, lead with the worst}
98
+
99
+ ## Findings by lens
100
+
101
+ ### 1. Edge cases
102
+ ### 2. Future-proofing
103
+ ### 3. Adversarial review
104
+ ### 4. Test coverage
105
+
106
+ ## What's solid
107
+ - {2–4 things the implementation got right — not flattery, real patterns to preserve}
108
+
109
+ ## Suggested order to address
110
+ 1. Fix blockers
111
+ 2. Add the missing tests in §4 (they double as regression catches)
112
+ 3. Major findings in priority order
113
+ ```
114
+
115
+ 8. **End with "what's solid"**, not more criticism. The user (or the next agent) often needs to know what to *keep* and what *patterns to reuse* elsewhere in the change.
116
+
117
+ ## Quality bar
118
+
119
+ - **Every finding has a reproducible scenario.** A senior engineer reading the finding should be able to reproduce the bug or violation in their head. "Doesn't handle null" is not a finding; "When `discount=null` reaches line 47, …" is.
120
+ - **Severity is calibrated.** More blockers than major ⇒ inflating ⇒ demote.
121
+ - **Findings cite `file:line`.** Reviewers must be able to jump to the spot. Section names aren't enough for code.
122
+ - **Fixes are concrete and paste-able where possible.** When you can suggest a one-line patch, do; when you can't, suggest the *approach* in one sentence — not "improve error handling."
123
+ - **Don't redesign.** This isn't your chance to push a different architecture. Stay in the lane of "given this approach, what's missing." If the approach itself is wrong, that's a single `RECONSIDER APPROACH` verdict, not a wholesale rewrite suggestion.
124
+ - **Test-coverage findings reference scenarios, not files.** ❌ "No test for `applyDiscount`." ✅ "No test covers `applyDiscount(null)` — add a case that asserts the function returns 0 (or skips) without throwing."
125
+
126
+ ## When NOT to use this skill
127
+
128
+ - ❌ For greenfield prototype / spike code that's about to be thrown away.
129
+ - ❌ For one-line / trivial changes — overkill, and the noise drowns out real signal.
130
+ - ❌ As a substitute for human code review — it's a pre-pass, not a replacement.
131
+ - ❌ For *evaluating the choice of approach* before code exists. That's a design conversation, not a code challenge. Use `design-doc` + `doc-critique` for that loop.
132
+ - ❌ For generated code in a language you can't reason about line-by-line. Better to refuse than fabricate findings.
133
+
134
+ ## Anti-patterns to avoid
135
+
136
+ - ❌ **Severity inflation.** If everything is a blocker, the report is unreadable. Most findings are major or minor.
137
+ - ❌ **Vague findings.** "Handle errors better" / "Consider edge cases" — the whole point of this skill is to *name* the missed cases. If you can't name a specific scenario, drop the finding.
138
+ - ❌ **Restating the lens.** ❌ "Code should be future-proof." ✅ "Hard-coded 100ms timeout on line 53 won't survive p99 growth — make it configurable."
139
+ - ❌ **Lecturing on style** when there's a real bug to flag. Style notes go in the Nits section, not on top.
140
+ - ❌ **Reviewing untouched code.** Out-of-scope. The skill challenges the *change*, not the codebase.
141
+ - ❌ **Demanding tests for *everything* the change touches.** Only the new logic and new error paths. Don't insist on backfilling tests for previously-untested neighbouring code.
142
+ - ❌ **Skipping "what's solid".** Trains the user (or downstream agent) to dread the skill. End on signal that's actionable in the other direction.
@@ -0,0 +1,88 @@
1
+ # Lens 3: Adversarial — what would a staff engineer push back on?
2
+
3
+ The question this lens asks: **if a senior engineer who didn't write this code reviewed it cold, what would they object to — even if it works today?**
4
+
5
+ This is the lens for the things that don't fail tests but fail in practice. Concurrency, error handling, security, observability, blast radius.
6
+
7
+ ---
8
+
9
+ ## Concurrency & ordering
10
+
11
+ - **Read-modify-write without a lock or compare-and-swap.** Two callers, both read X, both increment, both write — one update is lost.
12
+ - **Critical section that spans an `await` / I/O.** Lock not held across the await, or lock held *during* a slow I/O call (blocks everyone else).
13
+ - **Shared mutable state in a request-handler scope** (e.g. a module-level dict that handlers mutate).
14
+ - **Ordering assumption between async operations** with no explicit synchronization. "It works in my testing" because the race window is small.
15
+ - **Cancellation not propagated.** Context cancelled but downstream call still runs to completion, holding resources.
16
+ - **Goroutine / task leak.** Spawned, never awaited, never cancelled.
17
+
18
+ ## Error handling
19
+
20
+ - **Caught and swallowed.** `try { … } catch {}` with no log, no rethrow. Errors disappear into the void.
21
+ - **Logged and continued** when the operation should have failed. The user sees success; the system did nothing.
22
+ - **Generic catch hiding specific errors.** Catching `Exception` / `error` when only one specific case is recoverable.
23
+ - **Error message leaks internals** to the user (stack trace, SQL, file paths).
24
+ - **Wrong abstraction in the error.** Internal `RecordNotFound` surfaces as 500 instead of 404. Or vice versa.
25
+ - **No distinction between retriable and terminal errors.** Caller can't tell whether to back off and retry, or to give up.
26
+ - **Cleanup not in `finally`.** Resource leaked when an exception fires partway through.
27
+
28
+ ## Security
29
+
30
+ - **Input concatenated into SQL / shell / URL** instead of parameterized. Even if the input "shouldn't be untrusted."
31
+ - **Authorization check missing or in the wrong layer.** Authn ≠ Authz. A logged-in user accessing another user's resource by changing an ID.
32
+ - **Insecure direct object reference.** IDs in URLs / payloads accepted at face value with no ownership check.
33
+ - **Secrets in code, in config, in logs.** Including ones that look "innocent" — internal hostnames, employee names.
34
+ - **TLS verification disabled** (`rejectUnauthorized: false`, `verify=False`) — usually a copy-paste from a debug session.
35
+ - **Cryptographic primitives used wrong.** MD5/SHA1 for password hashing, ECB mode, IV reused, randomness from a non-CSPRNG.
36
+ - **Open redirect.** User-controlled URL passed to a redirect with no allowlist.
37
+ - **No CSRF protection** on a state-changing endpoint, in a session-cookie-auth app.
38
+ - **Logging PII / secrets.** Email, name, token, API key, full request body in an info-level log.
39
+
40
+ ## Observability
41
+
42
+ - **Load-bearing path with no log.** When this fails in prod, nothing in the logs will explain why.
43
+ - **Log without correlation.** No request ID, no trace ID, no tenant ID — can't tie events together.
44
+ - **Wrong log level.** Recoverable error at `error` (alerts), or unrecoverable at `info` (lost in noise).
45
+ - **No metric on the new operation.** Latency, count, error rate. If you can't measure it, you can't run it.
46
+ - **Span / trace doesn't cover the new code.** Distributed tracing has a hole.
47
+ - **Alert without a runbook entry.** When this fires, the on-caller has no documented response.
48
+
49
+ ## Blast radius
50
+
51
+ - **Change touches a shared utility** without considering all callers.
52
+ - **Migration / change applies to all rows / tenants** when it should be gated by feature flag.
53
+ - **No feature flag** when the change is risky and a rollback would otherwise require a redeploy.
54
+ - **Big bang deploy** of a multi-system change instead of staged.
55
+ - **Backwards-incompatible event / API change** with no consumer coordination.
56
+
57
+ ## Build, dependency, and supply chain
58
+
59
+ - **New dependency added.** Is it maintained? License compatible? Subdependency tree audited? Pinned to a major version?
60
+ - **Pinned to a vulnerable version** of an existing dependency.
61
+ - **`postinstall` script** in a new dependency that runs arbitrary code.
62
+ - **`curl | bash` install steps** in a Dockerfile or CI config.
63
+
64
+ ## Test smells
65
+
66
+ - **Test that doesn't actually assert.** Calls the function and checks nothing.
67
+ - **Test that mocks the thing under test.** Mocks itself out of any real verification.
68
+ - **Test that's coupled to the implementation** rather than the behaviour — fragile and slows down refactoring.
69
+ - **Test that's flaky** — passes locally, fails in CI 1 in 10 runs. Disable + ticket, don't ignore.
70
+ - **Test data with hard-coded "today"** — fails on a specific future date.
71
+
72
+ ## Naming, comments, and structure
73
+
74
+ - **Name that lies.** `getUser` that also creates one if missing. `parse` that also mutates the input. `validate` that also sanitizes.
75
+ - **Comment that explains what the code does** (the code already does that) instead of *why*.
76
+ - **Comment that's now wrong** because the code changed but the comment didn't.
77
+ - **Dead code committed.** `// TODO: remove this` from 2022.
78
+ - **Function that's doing two unrelated things** stitched together by a flag parameter.
79
+
80
+ ## Reconsider-approach signals
81
+
82
+ When you see *several* of these together, the verdict isn't "fix these findings" — it's `RECONSIDER APPROACH`:
83
+
84
+ - Reimplementing a primitive the framework / language provides (custom retry, custom cache, custom thread pool).
85
+ - Manual concurrency primitives where a higher-level abstraction exists (raw goroutines + channels when the language has `errgroup`; `setTimeout` polling when a proper queue would do).
86
+ - Several `if (env === 'X')` branches in business logic.
87
+ - Rolling your own auth / crypto / parsing for a well-known format.
88
+ - Code that essentially re-implements what a vendor library already does.
@@ -0,0 +1,95 @@
1
+ # Lens 1: Edge cases the first pass missed
2
+
3
+ The question this lens asks: **what inputs, states, or timings break this code?**
4
+
5
+ Apply the relevant subsection based on what the change is. Don't enumerate every check — pick the ones that *match the change shape* and have a real chance of biting.
6
+
7
+ ---
8
+
9
+ ## Universal (always check)
10
+
11
+ - **Null / undefined / missing.** For each parameter and field accessed: what happens when it's missing, null, undefined, `None`, `nil`, empty string, empty array, empty object, zero, `NaN`?
12
+ - **Boundary values.** Min, max, min−1, max+1, 0, −1, exactly-the-limit. For collections: empty, one, max-size, max-size+1.
13
+ - **Type confusion.** Number as string, string as number, ISO date as Unix timestamp, array as object. If the language is dynamically typed, this matters more.
14
+ - **Encoding.** Unicode (emoji, RTL, combining chars), URL-encoded vs decoded, base64, escaped vs raw, BOM in input files, mixed line endings.
15
+ - **Locale.** Comma vs period for decimals, timezone-naive dates, day-of-week assumptions, ordering by locale-aware sort.
16
+ - **Concurrency.** Two calls at once, the same call twice (idempotency), read-modify-write without a lock, optimistic locking ignored.
17
+ - **Time.** DST transitions, leap seconds (rare), clock skew, monotonic vs wall clock, "now()" called twice in same operation giving different values, expiry that crosses a boundary.
18
+ - **Partial failure.** What if the first half of the operation succeeds and the second fails? Where's the rollback / retry / dead-letter?
19
+
20
+ ## HTTP / RPC endpoint
21
+
22
+ - **Auth.** Missing token, expired token, valid-but-wrong-user token, malformed header, token for a different tenant.
23
+ - **Authorization.** User authenticated but not authorized (different question from "logged in").
24
+ - **Input validation.** Body too large, body empty, body with extra fields, missing required field, wrong content-type, malformed JSON, deeply nested JSON, JSON with `__proto__` / prototype pollution.
25
+ - **Method / route.** What if called with GET when POST expected? Trailing slash. Path traversal in path params.
26
+ - **Concurrency.** Same user makes 10 identical requests in parallel.
27
+ - **Idempotency.** If this can be retried by a client or proxy, is the second call safe?
28
+ - **Rate-limit / DoS.** Unbounded loop on user input, unbounded recursion, unbounded resource allocation tied to a request param.
29
+
30
+ ## Async handler / queue consumer
31
+
32
+ - **At-least-once semantics.** Same message twice. Is the operation idempotent on a key?
33
+ - **Out-of-order delivery.** Message B arrives before message A. Does logic still hold?
34
+ - **Poison messages.** Malformed payload that throws inside the handler — does the system DLQ it or retry forever?
35
+ - **Retry storms.** Failure causes immediate retry causes cascading retries causes thundering herd.
36
+ - **Backpressure.** Slow downstream. Queue grows unbounded. Does the handler shed load?
37
+
38
+ ## Database / migration
39
+
40
+ - **Locking.** `ALTER TABLE` on a large table without `CONCURRENTLY` (Postgres) or equivalent — locks reads/writes during deploy.
41
+ - **Backfill.** `ADD COLUMN NOT NULL` without a default on an existing populated table — fails or locks.
42
+ - **Rollback.** Is the migration reversible? If not, is that explicit and documented?
43
+ - **Online-safety.** Will old app code break against the new schema during the rolling deploy? (Add column → backfill → switch reads → drop old column — multi-step migrations.)
44
+ - **Index creation.** Without `CONCURRENTLY` — locks writes.
45
+ - **FK constraints added after data exists.** Will scan the whole table.
46
+
47
+ ## Parser / data transformation
48
+
49
+ - **Huge inputs.** 1GB file, 1M-row CSV, deeply nested JSON, malicious zip (zip bomb).
50
+ - **Malformed inputs.** Truncated, corrupted, wrong encoding, mixed encodings within one file.
51
+ - **Untrusted inputs.** Input is from a user — what if it's hostile? Path traversal, command injection, format-string attacks.
52
+ - **Streaming vs batch.** Does the code load everything into memory? Should it stream?
53
+ - **Numeric precision.** Float arithmetic on money, large integers in JSON (JavaScript loses precision past 2^53), trailing zeros stripped.
54
+
55
+ ## State machine / workflow
56
+
57
+ - **Impossible transitions.** Can the state graph reach state X from state Y in a single hop? Should it? What if it does?
58
+ - **Concurrent updates to the same entity.** Two callers move it from A → B and A → C simultaneously.
59
+ - **Skipped intermediate states.** Cleanup hooks that depend on visiting state Z get skipped.
60
+ - **Terminal states.** Once in `cancelled` / `failed`, can the entity be re-opened? Should it?
61
+ - **Replay.** What happens if the workflow is re-triggered from the beginning?
62
+
63
+ ## UI component
64
+
65
+ - **Loading state.** Is there one, and does it appear before the data?
66
+ - **Empty state.** Zero items — does the UI break or show something useful?
67
+ - **Error state.** API call fails — does the user see a message or a blank page?
68
+ - **Slow state.** API takes 8 seconds — does the UI lock up, or stay responsive?
69
+ - **Long content.** Names with 80 characters, descriptions with 5,000. Does layout break?
70
+ - **Internationalization.** RTL languages flipping the layout, longer translations overflowing buttons.
71
+ - **Accessibility.** Keyboard nav, screen reader labels, focus traps, contrast.
72
+ - **Mobile / small viewport.** Below 320px wide.
73
+
74
+ ## Background job / cron
75
+
76
+ - **Overlap.** Job takes longer than its interval — does it overlap with the next run?
77
+ - **Missed runs.** System down at scheduled time — does the next run catch up, or skip?
78
+ - **Partial completion.** Crash halfway through — is the next run idempotent?
79
+ - **Time zone.** "Run at midnight" — whose midnight?
80
+ - **Drift.** Long-running periodic that takes longer over time as data grows.
81
+
82
+ ## CLI tool / script
83
+
84
+ - **Missing args.** Required flag not passed.
85
+ - **Stdin not a TTY** (running in CI, piped from another command).
86
+ - **Env var missing or empty string.**
87
+ - **Partial run interrupted by Ctrl-C.** Is the file half-written? Is there a cleanup?
88
+ - **Non-zero exit codes** for each error path (CI scripts depend on these).
89
+
90
+ ## Library / pure function
91
+
92
+ - **API stability.** Public surface change — does it break callers?
93
+ - **Default values.** Sensible? Or surprising?
94
+ - **Side effects.** Pure function actually pure? Or does it mutate inputs / hit the network / read the clock?
95
+ - **Thread safety.** If callable from multiple threads, is shared state protected?
@@ -0,0 +1,75 @@
1
+ # Lens 2: Future-proofing — assumptions that won't survive 6 months
2
+
3
+ The question this lens asks: **what assumptions are baked into this code that will hurt when something predictable changes?**
4
+
5
+ This is not "design for every hypothetical." It's "the obvious next requirements will break this." Flag only assumptions whose violation is *likely* within a year — not theoretical.
6
+
7
+ ---
8
+
9
+ ## Scale assumptions
10
+
11
+ - **Hard-coded limits.** `LIMIT 100`, `for (i = 0; i < 1000; i++)`, `maxResults = 50`. What happens at 2× current scale? 10×?
12
+ - **In-memory accumulation.** Loading the whole result set into a list, holding it, then processing. Will it OOM at next year's data volume?
13
+ - **Unbounded growth.** A list / map / queue with no eviction. Will memory grow forever?
14
+ - **N+1 queries.** Loop calls the DB per iteration. Fine at 10 items, dead at 10,000.
15
+ - **Synchronous calls in a hot path.** Add three more downstream services and the latency stacks.
16
+
17
+ ## Tenancy assumptions
18
+
19
+ - **Single-tenant baked in.** No `tenant_id` / `org_id` / `workspace_id` threaded through. Will be a multi-week refactor when multi-tenancy lands.
20
+ - **Global state.** Caches keyed only by user/id, no tenant scope.
21
+ - **Per-user limits where per-tenant is needed** (or vice versa).
22
+ - **Email / username uniqueness assumed globally** rather than per-tenant.
23
+
24
+ ## Identity / ownership assumptions
25
+
26
+ - **Hard-coded user / account / org IDs.** `if (orgId === 'acme-corp')`. Will rot the moment Acme renames.
27
+ - **"Admin" as a single role** when next year wants RBAC with custom roles.
28
+ - **API keys with no rotation path.** What's the story when one leaks?
29
+ - **Auth provider baked into business logic.** Migrating providers means rewriting business code.
30
+
31
+ ## Data / schema assumptions
32
+
33
+ - **Enum hard-coded in code** when next year wants user-configurable values.
34
+ - **Boolean flag** that becomes a tri-state (`yes / no / pending`) or n-state.
35
+ - **JSONB blob** with no versioning — when its shape evolves, old rows can't be read or written without compat shims.
36
+ - **Foreign key to a "single source of truth"** that's about to become federated.
37
+ - **Timestamps without timezone** (`TIMESTAMP` instead of `TIMESTAMPTZ`).
38
+ - **Money as float** instead of integer cents or arbitrary-precision decimal.
39
+ - **Strings where structured data belongs** (comma-separated IDs in a single column).
40
+
41
+ ## Integration assumptions
42
+
43
+ - **Sync calls to an external API** that has a documented async option (webhooks, batch).
44
+ - **No retry / no circuit breaker** around external calls.
45
+ - **No timeout** on external calls (default is "wait forever").
46
+ - **Tight coupling to a vendor's response shape** with no anti-corruption layer.
47
+ - **Tight coupling to a vendor's identifier scheme** (using Stripe customer ID as primary key).
48
+
49
+ ## Configurability / observability
50
+
51
+ - **Magic constants** that should be configurable (`100ms timeout`, `5 retries`, `7 days expiry`). At minimum, named constants; better, env-driven.
52
+ - **Hard-coded environment** (`if (process.env.NODE_ENV === 'production')` scattered in business logic).
53
+ - **No structured logging** on the new path — when this code misbehaves in prod, how will you debug?
54
+ - **No metric / no trace** for a load-bearing operation. Future you will be flying blind.
55
+ - **Errors logged but not categorized** — can't alert on the dangerous ones without alerting on every error.
56
+
57
+ ## Compatibility / migration
58
+
59
+ - **Breaking change to a public API** without a deprecation path.
60
+ - **No versioning** on an external interface (REST endpoint, event schema, gRPC service).
61
+ - **Removed field still referenced by callers** — coordinate with consumers or stage the change.
62
+ - **Migration that's not safe to run on both old and new app code** during a rolling deploy.
63
+
64
+ ## Lifecycle / cleanup
65
+
66
+ - **Resource created without a cleanup path.** New S3 bucket, new DB record, new background job — what removes them?
67
+ - **TTL not set on cache entries.** They live forever, including stale data.
68
+ - **Soft-delete column added but no compaction strategy.** Table grows forever.
69
+ - **Cron job with no off-switch.** Disabling requires a deploy.
70
+
71
+ ## What this lens is NOT for
72
+
73
+ - ❌ "Design for 100M users when we have 100." Flag what's *likely* to change, not what's *possible* to change.
74
+ - ❌ "Add an interface in case we want to swap implementations." YAGNI applies; only flag if the swap is on the roadmap.
75
+ - ❌ Aesthetic refactors. If it's not going to break under foreseeable load / change, it's not in scope here.
@@ -0,0 +1,90 @@
1
+ # Lens 4: Test-coverage gap analysis
2
+
3
+ The question this lens asks: **for the code paths just introduced, which scenarios have no test?**
4
+
5
+ This is not about hitting a coverage percentage. It's about which *new* branches, error paths, and edge cases ship with no automated check that future changes don't regress them.
6
+
7
+ ---
8
+
9
+ ## Scope rule
10
+
11
+ - Test the **new code paths only.** Don't demand tests for previously-untested neighbouring code.
12
+ - Test the **error and edge branches**, not just the happy path. The happy path is usually the one already tested.
13
+ - Test the **boundaries**, not the interior. (Empty list and one-item list catch more than 5-item list.)
14
+
15
+ ## How to read the change
16
+
17
+ 1. **Identify the new branches.** Every `if`, `switch`, `try`, `?.`, default param, conditional return introduced in the diff is a branch. Each one is a coverage candidate.
18
+ 2. **Identify the new error paths.** Every `throw`, `return Err(…)`, `panic`, every `catch` block. Each is a candidate.
19
+ 3. **Identify the new public surface.** New function exported, new endpoint, new event handler, new CLI flag. Each public entry point needs at least one test from outside.
20
+ 4. **Identify the new integration points.** New external API call, new DB query, new file I/O. Each needs either an integration test or a mocked unit test with realistic responses (including failure responses).
21
+
22
+ ## What to flag as a missing test
23
+
24
+ For each missed scenario, write a finding like:
25
+
26
+ > **Missing test:** `applyDiscount(null)` — assert returns 0 (or skips) without throwing.
27
+ > **Suggested location:** `src/checkout/__tests__/applyDiscount.test.ts` (same dir pattern as siblings).
28
+ > **Severity:** 🟧 major — null input is reachable from the public endpoint (`api/checkout.ts:47`).
29
+
30
+ ### Default checklist of "must-have" scenarios
31
+
32
+ For every new function with parameters:
33
+
34
+ - **Happy path** — at least one test exists. (Usually it does. If not, that's a blocker.)
35
+ - **Empty input** — empty string, empty list, empty object, null, undefined.
36
+ - **Boundary** — min, max, off-by-one.
37
+ - **Error path** — explicit error / exception cases, each.
38
+
39
+ For every new endpoint:
40
+
41
+ - 200 happy path.
42
+ - 4xx for missing required field.
43
+ - 4xx for invalid auth (if endpoint requires auth).
44
+ - 4xx for valid auth + wrong user (authorization).
45
+ - 5xx response shape if downstream fails (or graceful degradation, whichever the design specifies).
46
+
47
+ For every new async handler / queue consumer:
48
+
49
+ - Successful processing of a valid message.
50
+ - Idempotency — same message processed twice produces same outcome.
51
+ - Malformed message — DLQ'd, not retried infinitely.
52
+
53
+ For every new migration:
54
+
55
+ - Forward migration applied on a non-empty seed DB.
56
+ - Backward migration restores schema (if reversible).
57
+ - Behaviour against *both* old and new app code if doing a multi-stage migration.
58
+
59
+ For every new state-machine transition:
60
+
61
+ - The valid transition itself.
62
+ - The invalid-transition rejection (state A → state Z when not allowed).
63
+
64
+ For every new UI component:
65
+
66
+ - Renders with realistic props.
67
+ - Renders with empty data.
68
+ - Renders with error state.
69
+ - Renders with loading state.
70
+ - (Interaction tests where the component has interactive behaviour.)
71
+
72
+ ## What to flag as a test SMELL (not missing — wrong)
73
+
74
+ - **Asserts nothing.** Calls the function but doesn't check the return value or side effect.
75
+ - **Mocks itself out of the test.** All collaborators mocked including the unit under test, or the mock makes the test pass trivially.
76
+ - **Tautological assertion.** `expect(x).toEqual(x)` — happens when an agent fabricates a test.
77
+ - **Asserts the implementation, not the behaviour.** Test reads private fields or counts internal calls; brittle to refactor.
78
+ - **Hard-codes a date that will fail in the future.** `expect(date).toEqual('2025-12-31')` baked into a test that runs every day.
79
+ - **Flaky due to timing / ordering.** `setTimeout(…, 0)` to "let the event loop settle" — works locally, flakes in CI.
80
+ - **Snapshot test on a noisy structure.** Snapshot includes timestamps, random IDs, or auto-generated keys — fails on every run.
81
+
82
+ Flag a smelly test the same way you flag a missing one — note that the test exists but doesn't earn its keep, and suggest what it should actually assert.
83
+
84
+ ## What this lens is NOT for
85
+
86
+ - ❌ Demanding tests for refactor-only changes that didn't add new behaviour.
87
+ - ❌ Demanding tests in code that already lacks them (out of scope — only the diff).
88
+ - ❌ Requiring 100% line coverage. Branches and edges matter; uncovered straightforward lines don't.
89
+ - ❌ Insisting on a specific test framework / style.
90
+ - ❌ Generating tests yourself. This lens *flags gaps* — the user (or the next agent in the loop) writes the tests, possibly by feeding the gap list back into a code-gen step.