@ketecode/loom 0.0.0-stage → 0.1.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 (656) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +516 -2
  3. package/agents/accessibility-reviewer/AGENT.md +70 -0
  4. package/agents/accessibility-reviewer/evals/triggers.json +15 -0
  5. package/agents/agent-evaluator/AGENT.md +74 -0
  6. package/agents/agent-evaluator/evals/triggers.json +15 -0
  7. package/agents/architect/AGENT.md +82 -0
  8. package/agents/architect/evals/triggers.json +17 -0
  9. package/agents/billing-reviewer/AGENT.md +68 -0
  10. package/agents/billing-reviewer/evals/triggers.json +16 -0
  11. package/agents/code-reviewer/AGENT.md +51 -0
  12. package/agents/code-reviewer/evals/triggers.json +14 -0
  13. package/agents/code-simplifier/AGENT.md +74 -0
  14. package/agents/code-simplifier/evals/triggers.json +15 -0
  15. package/agents/cpp-build-resolver/AGENT.md +73 -0
  16. package/agents/cpp-build-resolver/evals/triggers.json +16 -0
  17. package/agents/cpp-reviewer/AGENT.md +59 -0
  18. package/agents/cpp-reviewer/evals/triggers.json +16 -0
  19. package/agents/csharp-build-resolver/AGENT.md +84 -0
  20. package/agents/csharp-build-resolver/evals/triggers.json +17 -0
  21. package/agents/csharp-reviewer/AGENT.md +88 -0
  22. package/agents/csharp-reviewer/evals/triggers.json +17 -0
  23. package/agents/dart-build-resolver/AGENT.md +80 -0
  24. package/agents/dart-build-resolver/evals/triggers.json +17 -0
  25. package/agents/dart-reviewer/AGENT.md +66 -0
  26. package/agents/dart-reviewer/evals/triggers.json +17 -0
  27. package/agents/database-reviewer/AGENT.md +72 -0
  28. package/agents/database-reviewer/evals/triggers.json +16 -0
  29. package/agents/django-reviewer/AGENT.md +61 -0
  30. package/agents/django-reviewer/evals/triggers.json +15 -0
  31. package/agents/doc-updater/AGENT.md +92 -0
  32. package/agents/doc-updater/evals/triggers.json +14 -0
  33. package/agents/e2e-runner/AGENT.md +88 -0
  34. package/agents/e2e-runner/evals/triggers.json +16 -0
  35. package/agents/fastapi-reviewer/AGENT.md +63 -0
  36. package/agents/fastapi-reviewer/evals/triggers.json +15 -0
  37. package/agents/flutter-reviewer/AGENT.md +70 -0
  38. package/agents/flutter-reviewer/evals/triggers.json +15 -0
  39. package/agents/fsharp-build-resolver/AGENT.md +81 -0
  40. package/agents/fsharp-build-resolver/evals/triggers.json +15 -0
  41. package/agents/fsharp-reviewer/AGENT.md +77 -0
  42. package/agents/fsharp-reviewer/evals/triggers.json +15 -0
  43. package/agents/go-build-resolver/AGENT.md +85 -0
  44. package/agents/go-build-resolver/evals/triggers.json +16 -0
  45. package/agents/go-reviewer/AGENT.md +66 -0
  46. package/agents/go-reviewer/evals/triggers.json +16 -0
  47. package/agents/healthcare-reviewer/AGENT.md +65 -0
  48. package/agents/healthcare-reviewer/evals/triggers.json +16 -0
  49. package/agents/i18n-reviewer/AGENT.md +64 -0
  50. package/agents/i18n-reviewer/evals/triggers.json +16 -0
  51. package/agents/infra-reviewer/AGENT.md +93 -0
  52. package/agents/infra-reviewer/evals/triggers.json +15 -0
  53. package/agents/java-build-resolver/AGENT.md +82 -0
  54. package/agents/java-build-resolver/evals/triggers.json +16 -0
  55. package/agents/java-reviewer/AGENT.md +64 -0
  56. package/agents/java-reviewer/evals/triggers.json +16 -0
  57. package/agents/kotlin-build-resolver/AGENT.md +89 -0
  58. package/agents/kotlin-build-resolver/evals/triggers.json +16 -0
  59. package/agents/kotlin-reviewer/AGENT.md +75 -0
  60. package/agents/kotlin-reviewer/evals/triggers.json +16 -0
  61. package/agents/mle-reviewer/AGENT.md +68 -0
  62. package/agents/mle-reviewer/evals/triggers.json +16 -0
  63. package/agents/network-config-reviewer/AGENT.md +68 -0
  64. package/agents/network-config-reviewer/evals/triggers.json +17 -0
  65. package/agents/payments-reviewer/AGENT.md +64 -0
  66. package/agents/payments-reviewer/evals/triggers.json +16 -0
  67. package/agents/performance-optimizer/AGENT.md +86 -0
  68. package/agents/performance-optimizer/evals/triggers.json +16 -0
  69. package/agents/perl-build-resolver/AGENT.md +84 -0
  70. package/agents/perl-build-resolver/evals/triggers.json +15 -0
  71. package/agents/perl-reviewer/AGENT.md +77 -0
  72. package/agents/perl-reviewer/evals/triggers.json +15 -0
  73. package/agents/php-build-resolver/AGENT.md +88 -0
  74. package/agents/php-build-resolver/evals/triggers.json +16 -0
  75. package/agents/php-reviewer/AGENT.md +61 -0
  76. package/agents/php-reviewer/evals/triggers.json +15 -0
  77. package/agents/planner/AGENT.md +75 -0
  78. package/agents/planner/evals/triggers.json +17 -0
  79. package/agents/pr-test-analyzer/AGENT.md +82 -0
  80. package/agents/pr-test-analyzer/evals/triggers.json +16 -0
  81. package/agents/python-build-resolver/AGENT.md +87 -0
  82. package/agents/python-build-resolver/evals/triggers.json +16 -0
  83. package/agents/python-reviewer/AGENT.md +63 -0
  84. package/agents/python-reviewer/evals/triggers.json +15 -0
  85. package/agents/rag-reviewer/AGENT.md +71 -0
  86. package/agents/rag-reviewer/evals/triggers.json +16 -0
  87. package/agents/react-reviewer/AGENT.md +70 -0
  88. package/agents/react-reviewer/evals/triggers.json +16 -0
  89. package/agents/refactor-cleaner/AGENT.md +82 -0
  90. package/agents/refactor-cleaner/evals/triggers.json +16 -0
  91. package/agents/ruby-build-resolver/AGENT.md +93 -0
  92. package/agents/ruby-build-resolver/evals/triggers.json +16 -0
  93. package/agents/ruby-reviewer/AGENT.md +62 -0
  94. package/agents/ruby-reviewer/evals/triggers.json +16 -0
  95. package/agents/rust-build-resolver/AGENT.md +98 -0
  96. package/agents/rust-build-resolver/evals/triggers.json +16 -0
  97. package/agents/rust-reviewer/AGENT.md +78 -0
  98. package/agents/rust-reviewer/evals/triggers.json +15 -0
  99. package/agents/security-reviewer/AGENT.md +84 -0
  100. package/agents/security-reviewer/evals/triggers.json +16 -0
  101. package/agents/silent-failure-hunter/AGENT.md +66 -0
  102. package/agents/silent-failure-hunter/evals/triggers.json +16 -0
  103. package/agents/solidity-reviewer/AGENT.md +70 -0
  104. package/agents/solidity-reviewer/evals/triggers.json +16 -0
  105. package/agents/swift-build-resolver/AGENT.md +85 -0
  106. package/agents/swift-build-resolver/evals/triggers.json +15 -0
  107. package/agents/swift-reviewer/AGENT.md +75 -0
  108. package/agents/swift-reviewer/evals/triggers.json +15 -0
  109. package/agents/typescript-build-resolver/AGENT.md +76 -0
  110. package/agents/typescript-build-resolver/evals/triggers.json +15 -0
  111. package/agents/typescript-reviewer/AGENT.md +76 -0
  112. package/agents/typescript-reviewer/evals/triggers.json +15 -0
  113. package/agents/vue-reviewer/AGENT.md +75 -0
  114. package/agents/vue-reviewer/evals/triggers.json +15 -0
  115. package/bin/kete-loom.js +683 -0
  116. package/commands/aside.md +19 -0
  117. package/commands/build-fix.md +26 -0
  118. package/commands/campaign.md +19 -0
  119. package/commands/changelog.md +36 -0
  120. package/commands/checkpoint.md +26 -0
  121. package/commands/codemap.md +25 -0
  122. package/commands/commit.md +26 -0
  123. package/commands/deps-audit.md +32 -0
  124. package/commands/epic-decompose.md +21 -0
  125. package/commands/explain.md +37 -0
  126. package/commands/feature-dev.md +22 -0
  127. package/commands/hookify.md +23 -0
  128. package/commands/i18n-check.md +39 -0
  129. package/commands/issue-sync.md +22 -0
  130. package/commands/jira.md +19 -0
  131. package/commands/learn.md +23 -0
  132. package/commands/loom.md +21 -0
  133. package/commands/loop.md +20 -0
  134. package/commands/model-route.md +27 -0
  135. package/commands/onboard.md +35 -0
  136. package/commands/orchestrate.md +21 -0
  137. package/commands/plan-feature.md +36 -0
  138. package/commands/postmortem.md +42 -0
  139. package/commands/pr-describe.md +39 -0
  140. package/commands/pr.md +22 -0
  141. package/commands/prd.md +41 -0
  142. package/commands/project-init.md +21 -0
  143. package/commands/refactor-clean.md +24 -0
  144. package/commands/resume-session.md +22 -0
  145. package/commands/review.md +35 -0
  146. package/commands/save-session.md +37 -0
  147. package/commands/security-scan.md +32 -0
  148. package/commands/sessions.md +21 -0
  149. package/commands/skill-create.md +21 -0
  150. package/commands/tdd.md +36 -0
  151. package/commands/test-coverage.md +24 -0
  152. package/commands/threat-model.md +36 -0
  153. package/commands/update-docs.md +25 -0
  154. package/commands/verify.md +21 -0
  155. package/hooks/block-dangerous-commands/HOOK.md +30 -0
  156. package/hooks/block-dangerous-commands/cases.json +50 -0
  157. package/hooks/block-dangerous-commands/hook.js +75 -0
  158. package/hooks/block-no-verify/HOOK.md +25 -0
  159. package/hooks/block-no-verify/cases.json +30 -0
  160. package/hooks/block-no-verify/hook.js +43 -0
  161. package/hooks/format-on-edit/HOOK.md +24 -0
  162. package/hooks/format-on-edit/hook.js +89 -0
  163. package/hooks/guard-secrets/HOOK.md +19 -0
  164. package/hooks/guard-secrets/cases.json +110 -0
  165. package/hooks/guard-secrets/hook.js +44 -0
  166. package/hooks/load-session-context/HOOK.md +20 -0
  167. package/hooks/load-session-context/hook.js +56 -0
  168. package/hooks/protect-files/HOOK.md +24 -0
  169. package/hooks/protect-files/cases.json +27 -0
  170. package/hooks/protect-files/hook.js +39 -0
  171. package/hooks/run.js +132 -0
  172. package/mcp/atlassian.json +11 -0
  173. package/mcp/chrome-devtools.json +18 -0
  174. package/mcp/cloudflare.json +11 -0
  175. package/mcp/context7.json +11 -0
  176. package/mcp/fetch.json +17 -0
  177. package/mcp/figma.json +11 -0
  178. package/mcp/git.json +17 -0
  179. package/mcp/github.json +11 -0
  180. package/mcp/linear.json +11 -0
  181. package/mcp/memory.json +18 -0
  182. package/mcp/notion.json +11 -0
  183. package/mcp/playwright.json +18 -0
  184. package/mcp/sentry.json +11 -0
  185. package/mcp/stripe.json +11 -0
  186. package/mcp/supabase.json +11 -0
  187. package/mcp/time.json +17 -0
  188. package/package.json +59 -4
  189. package/profiles.json +165 -0
  190. package/rules/common.md +21 -0
  191. package/rules/cpp.md +29 -0
  192. package/rules/csharp.md +25 -0
  193. package/rules/dart.md +29 -0
  194. package/rules/fsharp.md +28 -0
  195. package/rules/git.md +26 -0
  196. package/rules/go.md +29 -0
  197. package/rules/java.md +29 -0
  198. package/rules/kotlin.md +27 -0
  199. package/rules/perl.md +26 -0
  200. package/rules/php.md +28 -0
  201. package/rules/python.md +30 -0
  202. package/rules/ruby.md +27 -0
  203. package/rules/rust.md +26 -0
  204. package/rules/security.md +29 -0
  205. package/rules/swift.md +28 -0
  206. package/rules/testing.md +25 -0
  207. package/rules/typescript.md +29 -0
  208. package/schemas/skill-frontmatter.schema.json +52 -0
  209. package/scripts/lib/audit.js +96 -0
  210. package/scripts/lib/frontmatter.js +65 -0
  211. package/scripts/lib/hooks-install.js +292 -0
  212. package/scripts/lib/i18n.js +51 -0
  213. package/scripts/lib/inventory.js +85 -0
  214. package/scripts/lib/lint.js +158 -0
  215. package/scripts/lib/mcp-install.js +284 -0
  216. package/scripts/lib/profiles.js +128 -0
  217. package/scripts/lib/render.js +86 -0
  218. package/scripts/lib/rules-install.js +118 -0
  219. package/scripts/lib/skills.js +86 -0
  220. package/scripts/lib/targets.js +113 -0
  221. package/skills/accounting-api-integration/SKILL.md +81 -0
  222. package/skills/accounting-api-integration/evals/triggers.json +17 -0
  223. package/skills/accounting-api-integration/references/quickbooks.md +48 -0
  224. package/skills/accounting-api-integration/references/xero.md +45 -0
  225. package/skills/agent-harness-design/SKILL.md +125 -0
  226. package/skills/agent-harness-design/evals/triggers.json +21 -0
  227. package/skills/ai-media-generation/SKILL.md +89 -0
  228. package/skills/ai-media-generation/evals/triggers.json +16 -0
  229. package/skills/ai-media-generation/references/job-pipeline.md +76 -0
  230. package/skills/angular-patterns/SKILL.md +122 -0
  231. package/skills/angular-patterns/evals/triggers.json +16 -0
  232. package/skills/api-design/SKILL.md +96 -0
  233. package/skills/api-design/evals/triggers.json +18 -0
  234. package/skills/api-design/references/conventions.md +133 -0
  235. package/skills/architecture-decision-records/SKILL.md +98 -0
  236. package/skills/architecture-decision-records/evals/triggers.json +17 -0
  237. package/skills/article-writing/SKILL.md +108 -0
  238. package/skills/article-writing/evals/triggers.json +16 -0
  239. package/skills/aspnet-core-patterns/SKILL.md +149 -0
  240. package/skills/aspnet-core-patterns/evals/triggers.json +16 -0
  241. package/skills/auth-patterns/SKILL.md +104 -0
  242. package/skills/auth-patterns/evals/triggers.json +17 -0
  243. package/skills/auth-patterns/references/oauth-oidc.md +64 -0
  244. package/skills/autonomous-loops/SKILL.md +99 -0
  245. package/skills/autonomous-loops/evals/triggers.json +14 -0
  246. package/skills/aws-patterns/SKILL.md +91 -0
  247. package/skills/aws-patterns/evals/triggers.json +16 -0
  248. package/skills/azure-patterns/SKILL.md +86 -0
  249. package/skills/azure-patterns/evals/triggers.json +16 -0
  250. package/skills/benchmark-methodology/SKILL.md +88 -0
  251. package/skills/benchmark-methodology/evals/triggers.json +16 -0
  252. package/skills/benchmark-methodology/references/language-harnesses.md +130 -0
  253. package/skills/bgp-diagnostics/SKILL.md +84 -0
  254. package/skills/bgp-diagnostics/evals/triggers.json +18 -0
  255. package/skills/bgp-diagnostics/references/bgp-reference.md +81 -0
  256. package/skills/bioinformatics-workflows/SKILL.md +108 -0
  257. package/skills/bioinformatics-workflows/evals/triggers.json +16 -0
  258. package/skills/bioinformatics-workflows/references/commands.md +71 -0
  259. package/skills/bioinformatics-workflows/references/formats.md +24 -0
  260. package/skills/bioinformatics-workflows/references/workflow-managers.md +107 -0
  261. package/skills/brand-voice/SKILL.md +112 -0
  262. package/skills/brand-voice/evals/triggers.json +16 -0
  263. package/skills/browser-qa/SKILL.md +99 -0
  264. package/skills/browser-qa/evals/triggers.json +16 -0
  265. package/skills/bun-runtime/SKILL.md +93 -0
  266. package/skills/bun-runtime/evals/triggers.json +16 -0
  267. package/skills/cisco-ios-config/SKILL.md +101 -0
  268. package/skills/cisco-ios-config/evals/triggers.json +18 -0
  269. package/skills/cisco-ios-config/references/verification.md +63 -0
  270. package/skills/clickhouse-patterns/SKILL.md +101 -0
  271. package/skills/clickhouse-patterns/evals/triggers.json +18 -0
  272. package/skills/clickhouse-patterns/references/engines-and-views.md +138 -0
  273. package/skills/clinical-decision-support/SKILL.md +90 -0
  274. package/skills/clinical-decision-support/evals/triggers.json +16 -0
  275. package/skills/clinical-decision-support/references/cds-hooks.md +76 -0
  276. package/skills/clinical-decision-support/references/regulatory-boundaries.md +37 -0
  277. package/skills/code-tour/SKILL.md +97 -0
  278. package/skills/code-tour/evals/triggers.json +14 -0
  279. package/skills/codebase-onboarding/SKILL.md +112 -0
  280. package/skills/codebase-onboarding/evals/triggers.json +14 -0
  281. package/skills/cold-outreach-sequences/SKILL.md +90 -0
  282. package/skills/cold-outreach-sequences/evals/triggers.json +16 -0
  283. package/skills/content-repurposing/SKILL.md +82 -0
  284. package/skills/content-repurposing/evals/triggers.json +16 -0
  285. package/skills/context-budget/SKILL.md +84 -0
  286. package/skills/context-budget/evals/triggers.json +14 -0
  287. package/skills/conventional-commits/SKILL.md +144 -0
  288. package/skills/conventional-commits/evals/triggers.json +16 -0
  289. package/skills/cpp-patterns/SKILL.md +129 -0
  290. package/skills/cpp-patterns/evals/triggers.json +16 -0
  291. package/skills/cpp-patterns/references/cmake-and-tooling.md +88 -0
  292. package/skills/cpp-patterns/references/undefined-behaviour.md +75 -0
  293. package/skills/cpp-testing/SKILL.md +131 -0
  294. package/skills/cpp-testing/evals/triggers.json +16 -0
  295. package/skills/csharp-patterns/SKILL.md +110 -0
  296. package/skills/csharp-patterns/evals/triggers.json +17 -0
  297. package/skills/csharp-patterns/references/analyzers.md +59 -0
  298. package/skills/csharp-testing/SKILL.md +85 -0
  299. package/skills/csharp-testing/evals/triggers.json +17 -0
  300. package/skills/csharp-testing/references/integration-tests.md +77 -0
  301. package/skills/css-architecture/SKILL.md +143 -0
  302. package/skills/css-architecture/evals/triggers.json +16 -0
  303. package/skills/customs-trade-compliance/SKILL.md +95 -0
  304. package/skills/customs-trade-compliance/evals/triggers.json +16 -0
  305. package/skills/customs-trade-compliance/references/incoterms-2020.md +42 -0
  306. package/skills/dart-patterns/SKILL.md +157 -0
  307. package/skills/dart-patterns/evals/triggers.json +18 -0
  308. package/skills/dart-testing/SKILL.md +164 -0
  309. package/skills/dart-testing/evals/triggers.json +18 -0
  310. package/skills/data-analysis-notebooks/SKILL.md +113 -0
  311. package/skills/data-analysis-notebooks/evals/triggers.json +16 -0
  312. package/skills/data-analysis-notebooks/references/dataframe-pitfalls.md +49 -0
  313. package/skills/data-analysis-notebooks/references/statistics-pitfalls.md +24 -0
  314. package/skills/data-pipelines/SKILL.md +90 -0
  315. package/skills/data-pipelines/evals/triggers.json +16 -0
  316. package/skills/data-pipelines/references/orchestrators.md +64 -0
  317. package/skills/database-migrations/SKILL.md +102 -0
  318. package/skills/database-migrations/evals/triggers.json +16 -0
  319. package/skills/database-migrations/references/recipes.md +98 -0
  320. package/skills/database-migrations/references/tools.md +21 -0
  321. package/skills/dbt-patterns/SKILL.md +96 -0
  322. package/skills/dbt-patterns/evals/triggers.json +16 -0
  323. package/skills/dbt-patterns/references/yaml-examples.md +114 -0
  324. package/skills/deep-research/SKILL.md +107 -0
  325. package/skills/deep-research/evals/triggers.json +14 -0
  326. package/skills/dependency-audit/SKILL.md +103 -0
  327. package/skills/dependency-audit/evals/triggers.json +16 -0
  328. package/skills/dependency-audit/references/tools.md +124 -0
  329. package/skills/deployment-strategies/SKILL.md +108 -0
  330. package/skills/deployment-strategies/evals/triggers.json +16 -0
  331. package/skills/django-patterns/SKILL.md +123 -0
  332. package/skills/django-patterns/evals/triggers.json +16 -0
  333. package/skills/docker-patterns/SKILL.md +132 -0
  334. package/skills/docker-patterns/evals/triggers.json +16 -0
  335. package/skills/docker-patterns/references/dockerfiles.md +105 -0
  336. package/skills/e2e-testing-playwright/SKILL.md +94 -0
  337. package/skills/e2e-testing-playwright/evals/triggers.json +16 -0
  338. package/skills/e2e-testing-playwright/references/config-and-ci.md +129 -0
  339. package/skills/ef-core-patterns/SKILL.md +117 -0
  340. package/skills/ef-core-patterns/evals/triggers.json +16 -0
  341. package/skills/email-deliverability/SKILL.md +99 -0
  342. package/skills/email-deliverability/evals/triggers.json +17 -0
  343. package/skills/email-deliverability/references/dns-records.md +85 -0
  344. package/skills/error-handling-patterns/SKILL.md +112 -0
  345. package/skills/error-handling-patterns/evals/triggers.json +18 -0
  346. package/skills/error-handling-patterns/references/language-idioms.md +49 -0
  347. package/skills/estimation-and-scoping/SKILL.md +97 -0
  348. package/skills/estimation-and-scoping/evals/triggers.json +14 -0
  349. package/skills/evm-dapp-integration/SKILL.md +73 -0
  350. package/skills/evm-dapp-integration/evals/triggers.json +16 -0
  351. package/skills/fastapi-patterns/SKILL.md +127 -0
  352. package/skills/fastapi-patterns/evals/triggers.json +16 -0
  353. package/skills/ffmpeg-media-processing/SKILL.md +94 -0
  354. package/skills/ffmpeg-media-processing/evals/triggers.json +16 -0
  355. package/skills/ffmpeg-media-processing/references/recipes.md +112 -0
  356. package/skills/fhir-integration/SKILL.md +81 -0
  357. package/skills/fhir-integration/evals/triggers.json +16 -0
  358. package/skills/fhir-integration/references/search-and-bundles.md +73 -0
  359. package/skills/fhir-integration/references/smart-on-fhir.md +50 -0
  360. package/skills/flask-patterns/SKILL.md +132 -0
  361. package/skills/flask-patterns/evals/triggers.json +16 -0
  362. package/skills/flutter-patterns/SKILL.md +99 -0
  363. package/skills/flutter-patterns/evals/triggers.json +16 -0
  364. package/skills/flutterwave-integration/SKILL.md +75 -0
  365. package/skills/flutterwave-integration/evals/triggers.json +16 -0
  366. package/skills/flutterwave-integration/references/api.md +73 -0
  367. package/skills/flutterwave-integration/references/webhooks.md +49 -0
  368. package/skills/fsharp-patterns/SKILL.md +133 -0
  369. package/skills/fsharp-patterns/evals/triggers.json +16 -0
  370. package/skills/fsharp-testing/SKILL.md +136 -0
  371. package/skills/fsharp-testing/evals/triggers.json +16 -0
  372. package/skills/gcp-patterns/SKILL.md +86 -0
  373. package/skills/gcp-patterns/evals/triggers.json +16 -0
  374. package/skills/git-workflow/SKILL.md +114 -0
  375. package/skills/git-workflow/evals/triggers.json +16 -0
  376. package/skills/github-actions-ci/SKILL.md +117 -0
  377. package/skills/github-actions-ci/evals/triggers.json +16 -0
  378. package/skills/github-api-automation/SKILL.md +101 -0
  379. package/skills/github-api-automation/evals/triggers.json +17 -0
  380. package/skills/go-patterns/SKILL.md +118 -0
  381. package/skills/go-patterns/evals/triggers.json +17 -0
  382. package/skills/go-patterns/references/concurrency.md +162 -0
  383. package/skills/go-testing/SKILL.md +154 -0
  384. package/skills/go-testing/evals/triggers.json +17 -0
  385. package/skills/hexagonal-architecture/SKILL.md +89 -0
  386. package/skills/hexagonal-architecture/evals/triggers.json +17 -0
  387. package/skills/hipaa-compliance/SKILL.md +91 -0
  388. package/skills/hipaa-compliance/evals/triggers.json +18 -0
  389. package/skills/hipaa-compliance/references/safeguards.md +68 -0
  390. package/skills/hl7v2-integration/SKILL.md +69 -0
  391. package/skills/hl7v2-integration/evals/triggers.json +16 -0
  392. package/skills/hl7v2-integration/references/messages-and-ack.md +78 -0
  393. package/skills/homelab-network-setup/SKILL.md +125 -0
  394. package/skills/homelab-network-setup/evals/triggers.json +18 -0
  395. package/skills/homelab-network-setup/references/firewall-and-dns.md +45 -0
  396. package/skills/homelab-network-setup/references/wireguard.md +72 -0
  397. package/skills/hubtel-integration/SKILL.md +77 -0
  398. package/skills/hubtel-integration/evals/triggers.json +16 -0
  399. package/skills/hubtel-integration/references/api.md +92 -0
  400. package/skills/i18n-localization/SKILL.md +114 -0
  401. package/skills/i18n-localization/evals/triggers.json +16 -0
  402. package/skills/i18n-localization/references/libraries.md +52 -0
  403. package/skills/incident-postmortem/SKILL.md +118 -0
  404. package/skills/incident-postmortem/evals/triggers.json +14 -0
  405. package/skills/inventory-demand-planning/SKILL.md +89 -0
  406. package/skills/inventory-demand-planning/evals/triggers.json +16 -0
  407. package/skills/inventory-demand-planning/references/formulas.md +62 -0
  408. package/skills/investor-materials/SKILL.md +127 -0
  409. package/skills/investor-materials/evals/triggers.json +16 -0
  410. package/skills/investor-materials/references/templates.md +74 -0
  411. package/skills/invoicing-and-tax/SKILL.md +84 -0
  412. package/skills/invoicing-and-tax/evals/triggers.json +17 -0
  413. package/skills/invoicing-and-tax/references/e-invoicing.md +24 -0
  414. package/skills/invoicing-and-tax/references/invoice-fields.md +38 -0
  415. package/skills/invoicing-and-tax/references/rounding.md +26 -0
  416. package/skills/java-patterns/SKILL.md +141 -0
  417. package/skills/java-patterns/evals/triggers.json +17 -0
  418. package/skills/java-testing/SKILL.md +142 -0
  419. package/skills/java-testing/evals/triggers.json +16 -0
  420. package/skills/jetpack-compose-patterns/SKILL.md +88 -0
  421. package/skills/jetpack-compose-patterns/evals/triggers.json +16 -0
  422. package/skills/jira-integration/SKILL.md +92 -0
  423. package/skills/jira-integration/evals/triggers.json +17 -0
  424. package/skills/jpa-hibernate/SKILL.md +92 -0
  425. package/skills/jpa-hibernate/evals/triggers.json +18 -0
  426. package/skills/jpa-hibernate/references/mapping.md +99 -0
  427. package/skills/kotlin-multiplatform/SKILL.md +97 -0
  428. package/skills/kotlin-multiplatform/evals/triggers.json +16 -0
  429. package/skills/kotlin-patterns/SKILL.md +128 -0
  430. package/skills/kotlin-patterns/evals/triggers.json +16 -0
  431. package/skills/kotlin-testing/SKILL.md +117 -0
  432. package/skills/kotlin-testing/evals/triggers.json +16 -0
  433. package/skills/ktor-patterns/SKILL.md +135 -0
  434. package/skills/ktor-patterns/evals/triggers.json +18 -0
  435. package/skills/kubernetes-patterns/SKILL.md +106 -0
  436. package/skills/kubernetes-patterns/evals/triggers.json +16 -0
  437. package/skills/kubernetes-patterns/references/manifests.md +115 -0
  438. package/skills/laravel-patterns/SKILL.md +136 -0
  439. package/skills/laravel-patterns/evals/triggers.json +16 -0
  440. package/skills/linear-integration/SKILL.md +98 -0
  441. package/skills/linear-integration/evals/triggers.json +17 -0
  442. package/skills/literature-review/SKILL.md +109 -0
  443. package/skills/literature-review/evals/triggers.json +16 -0
  444. package/skills/literature-review/references/appraisal.md +41 -0
  445. package/skills/literature-review/references/search-sources.md +39 -0
  446. package/skills/llm-app-patterns/SKILL.md +97 -0
  447. package/skills/llm-app-patterns/evals/triggers.json +17 -0
  448. package/skills/llm-evals/SKILL.md +98 -0
  449. package/skills/llm-evals/evals/triggers.json +16 -0
  450. package/skills/llm-evals/references/graders.md +66 -0
  451. package/skills/logistics-exception-management/SKILL.md +90 -0
  452. package/skills/logistics-exception-management/evals/triggers.json +16 -0
  453. package/skills/manim-animations/SKILL.md +106 -0
  454. package/skills/manim-animations/evals/triggers.json +16 -0
  455. package/skills/market-research/SKILL.md +117 -0
  456. package/skills/market-research/evals/triggers.json +16 -0
  457. package/skills/marketing-campaign/SKILL.md +111 -0
  458. package/skills/marketing-campaign/evals/triggers.json +16 -0
  459. package/skills/mcp-server-patterns/SKILL.md +127 -0
  460. package/skills/mcp-server-patterns/evals/triggers.json +18 -0
  461. package/skills/mcp-server-patterns/references/protocol-notes.md +68 -0
  462. package/skills/metrics-dashboards/SKILL.md +113 -0
  463. package/skills/metrics-dashboards/evals/triggers.json +16 -0
  464. package/skills/ml-experiment-workflow/SKILL.md +125 -0
  465. package/skills/ml-experiment-workflow/evals/triggers.json +16 -0
  466. package/skills/mongodb-patterns/SKILL.md +115 -0
  467. package/skills/mongodb-patterns/evals/triggers.json +18 -0
  468. package/skills/mongodb-patterns/references/indexes-and-aggregation.md +94 -0
  469. package/skills/mpesa-daraja-integration/SKILL.md +70 -0
  470. package/skills/mpesa-daraja-integration/evals/triggers.json +16 -0
  471. package/skills/mpesa-daraja-integration/references/api.md +103 -0
  472. package/skills/mpesa-daraja-integration/references/callbacks.md +74 -0
  473. package/skills/mtn-momo-integration/SKILL.md +66 -0
  474. package/skills/mtn-momo-integration/evals/triggers.json +16 -0
  475. package/skills/mtn-momo-integration/references/api.md +153 -0
  476. package/skills/mtn-momo-integration/references/callbacks.md +92 -0
  477. package/skills/mtn-momo-integration/references/sandbox-and-go-live.md +51 -0
  478. package/skills/mtn-momo-integration/scripts/sandbox-setup.js +79 -0
  479. package/skills/mysql-patterns/SKILL.md +96 -0
  480. package/skills/mysql-patterns/evals/triggers.json +16 -0
  481. package/skills/mysql-patterns/references/explain.md +34 -0
  482. package/skills/mysql-patterns/references/online-ddl.md +41 -0
  483. package/skills/nestjs-patterns/SKILL.md +114 -0
  484. package/skills/nestjs-patterns/evals/triggers.json +16 -0
  485. package/skills/nestjs-patterns/references/testing.md +68 -0
  486. package/skills/network-automation/SKILL.md +107 -0
  487. package/skills/network-automation/evals/triggers.json +18 -0
  488. package/skills/network-automation/references/tool-snippets.md +153 -0
  489. package/skills/network-troubleshooting/SKILL.md +152 -0
  490. package/skills/network-troubleshooting/evals/triggers.json +18 -0
  491. package/skills/network-troubleshooting/references/commands.md +33 -0
  492. package/skills/nextjs-patterns/SKILL.md +150 -0
  493. package/skills/nextjs-patterns/evals/triggers.json +18 -0
  494. package/skills/nextjs-patterns/references/caching.md +87 -0
  495. package/skills/node-backend-patterns/SKILL.md +103 -0
  496. package/skills/node-backend-patterns/evals/triggers.json +16 -0
  497. package/skills/node-backend-patterns/references/templates.md +122 -0
  498. package/skills/nuxt-patterns/SKILL.md +103 -0
  499. package/skills/nuxt-patterns/evals/triggers.json +16 -0
  500. package/skills/parallel-agent-orchestration/SKILL.md +106 -0
  501. package/skills/parallel-agent-orchestration/evals/triggers.json +14 -0
  502. package/skills/paystack-integration/SKILL.md +59 -0
  503. package/skills/paystack-integration/evals/triggers.json +14 -0
  504. package/skills/paystack-integration/references/api.md +73 -0
  505. package/skills/paystack-integration/references/mobile-money.md +50 -0
  506. package/skills/paystack-integration/references/webhooks.md +80 -0
  507. package/skills/pci-dss-scope/SKILL.md +103 -0
  508. package/skills/pci-dss-scope/evals/triggers.json +18 -0
  509. package/skills/pci-dss-scope/references/saq-and-data.md +36 -0
  510. package/skills/perl-patterns/SKILL.md +135 -0
  511. package/skills/perl-patterns/evals/triggers.json +18 -0
  512. package/skills/perl-testing/SKILL.md +126 -0
  513. package/skills/perl-testing/evals/triggers.json +17 -0
  514. package/skills/php-patterns/SKILL.md +116 -0
  515. package/skills/php-patterns/evals/triggers.json +16 -0
  516. package/skills/php-testing/SKILL.md +123 -0
  517. package/skills/php-testing/evals/triggers.json +16 -0
  518. package/skills/postgres-patterns/SKILL.md +103 -0
  519. package/skills/postgres-patterns/evals/triggers.json +17 -0
  520. package/skills/postgres-patterns/references/explain.md +59 -0
  521. package/skills/postgres-patterns/references/locks.md +53 -0
  522. package/skills/prd-writing/SKILL.md +124 -0
  523. package/skills/prd-writing/evals/triggers.json +15 -0
  524. package/skills/prisma-patterns/SKILL.md +83 -0
  525. package/skills/prisma-patterns/evals/triggers.json +18 -0
  526. package/skills/prisma-patterns/references/prisma-8.md +46 -0
  527. package/skills/prisma-patterns/references/workflow.md +50 -0
  528. package/skills/privacy-compliance/SKILL.md +121 -0
  529. package/skills/privacy-compliance/evals/triggers.json +18 -0
  530. package/skills/privacy-compliance/references/jurisdictions.md +51 -0
  531. package/skills/production-scheduling/SKILL.md +98 -0
  532. package/skills/production-scheduling/evals/triggers.json +16 -0
  533. package/skills/prompt-engineering/SKILL.md +92 -0
  534. package/skills/prompt-engineering/evals/triggers.json +16 -0
  535. package/skills/python-patterns/SKILL.md +107 -0
  536. package/skills/python-patterns/evals/triggers.json +16 -0
  537. package/skills/python-patterns/references/tooling.md +101 -0
  538. package/skills/python-testing/SKILL.md +126 -0
  539. package/skills/python-testing/evals/triggers.json +16 -0
  540. package/skills/python-testing/references/mocking.md +71 -0
  541. package/skills/pytorch-patterns/SKILL.md +139 -0
  542. package/skills/pytorch-patterns/evals/triggers.json +16 -0
  543. package/skills/pytorch-patterns/references/debugging.md +39 -0
  544. package/skills/quarkus-patterns/SKILL.md +93 -0
  545. package/skills/quarkus-patterns/evals/triggers.json +18 -0
  546. package/skills/rag-pipeline-patterns/SKILL.md +117 -0
  547. package/skills/rag-pipeline-patterns/evals/triggers.json +18 -0
  548. package/skills/rag-pipeline-patterns/references/evaluation.md +37 -0
  549. package/skills/rag-pipeline-patterns/references/retrieval-recipes.md +78 -0
  550. package/skills/rails-patterns/SKILL.md +132 -0
  551. package/skills/rails-patterns/evals/triggers.json +16 -0
  552. package/skills/react-native-patterns/SKILL.md +101 -0
  553. package/skills/react-native-patterns/evals/triggers.json +16 -0
  554. package/skills/react-patterns/SKILL.md +140 -0
  555. package/skills/react-patterns/evals/triggers.json +18 -0
  556. package/skills/react-performance/SKILL.md +107 -0
  557. package/skills/react-performance/evals/triggers.json +18 -0
  558. package/skills/redis-patterns/SKILL.md +109 -0
  559. package/skills/redis-patterns/evals/triggers.json +18 -0
  560. package/skills/redis-patterns/references/operations.md +61 -0
  561. package/skills/refactoring-safely/SKILL.md +107 -0
  562. package/skills/refactoring-safely/evals/triggers.json +17 -0
  563. package/skills/release-management/SKILL.md +141 -0
  564. package/skills/release-management/evals/triggers.json +16 -0
  565. package/skills/remotion-video/SKILL.md +91 -0
  566. package/skills/remotion-video/evals/triggers.json +16 -0
  567. package/skills/remotion-video/references/lambda.md +66 -0
  568. package/skills/returns-reverse-logistics/SKILL.md +97 -0
  569. package/skills/returns-reverse-logistics/evals/triggers.json +16 -0
  570. package/skills/ruby-patterns/SKILL.md +127 -0
  571. package/skills/ruby-patterns/evals/triggers.json +18 -0
  572. package/skills/ruby-testing/SKILL.md +113 -0
  573. package/skills/ruby-testing/evals/triggers.json +18 -0
  574. package/skills/runbook-writing/SKILL.md +101 -0
  575. package/skills/runbook-writing/evals/triggers.json +14 -0
  576. package/skills/rust-patterns/SKILL.md +118 -0
  577. package/skills/rust-patterns/evals/triggers.json +16 -0
  578. package/skills/rust-patterns/references/cargo-and-clippy.md +105 -0
  579. package/skills/rust-patterns/references/errors-and-traits.md +97 -0
  580. package/skills/rust-testing/SKILL.md +148 -0
  581. package/skills/rust-testing/evals/triggers.json +16 -0
  582. package/skills/rust-testing/references/fakes-proptest-async.md +113 -0
  583. package/skills/search-first/SKILL.md +73 -0
  584. package/skills/search-first/evals/triggers.json +14 -0
  585. package/skills/security-review/SKILL.md +58 -0
  586. package/skills/security-review/evals/triggers.json +14 -0
  587. package/skills/security-review/references/checklist.md +54 -0
  588. package/skills/security-review/scripts/scan-secrets.js +79 -0
  589. package/skills/seo-audit/SKILL.md +111 -0
  590. package/skills/seo-audit/evals/triggers.json +16 -0
  591. package/skills/seo-audit/references/checks.md +65 -0
  592. package/skills/session-handoff/SKILL.md +101 -0
  593. package/skills/session-handoff/evals/triggers.json +14 -0
  594. package/skills/skill-authoring/SKILL.md +87 -0
  595. package/skills/skill-authoring/evals/triggers.json +14 -0
  596. package/skills/skill-authoring/references/frontmatter.md +40 -0
  597. package/skills/slack-app-integration/SKILL.md +108 -0
  598. package/skills/slack-app-integration/evals/triggers.json +17 -0
  599. package/skills/smart-contract-security/SKILL.md +110 -0
  600. package/skills/smart-contract-security/evals/triggers.json +16 -0
  601. package/skills/smart-contract-security/references/vulnerability-checklist.md +79 -0
  602. package/skills/social-media-publishing/SKILL.md +84 -0
  603. package/skills/social-media-publishing/evals/triggers.json +17 -0
  604. package/skills/social-media-publishing/references/platform-apis.md +116 -0
  605. package/skills/solidity-patterns/SKILL.md +95 -0
  606. package/skills/solidity-patterns/evals/triggers.json +16 -0
  607. package/skills/spring-boot-patterns/SKILL.md +128 -0
  608. package/skills/spring-boot-patterns/evals/triggers.json +18 -0
  609. package/skills/spring-boot-patterns/references/testing.md +72 -0
  610. package/skills/stripe-integration/SKILL.md +69 -0
  611. package/skills/stripe-integration/evals/triggers.json +16 -0
  612. package/skills/stripe-integration/references/api.md +71 -0
  613. package/skills/stripe-integration/references/billing.md +58 -0
  614. package/skills/stripe-integration/references/webhooks.md +76 -0
  615. package/skills/subscription-billing-ops/SKILL.md +118 -0
  616. package/skills/subscription-billing-ops/evals/triggers.json +17 -0
  617. package/skills/subscription-billing-ops/references/proration.md +47 -0
  618. package/skills/subscription-billing-ops/references/revenue-metrics.md +38 -0
  619. package/skills/svelte-patterns/SKILL.md +122 -0
  620. package/skills/svelte-patterns/evals/triggers.json +16 -0
  621. package/skills/swift-patterns/SKILL.md +113 -0
  622. package/skills/swift-patterns/evals/triggers.json +16 -0
  623. package/skills/swift-patterns/references/concurrency-migration.md +40 -0
  624. package/skills/swift-testing/SKILL.md +121 -0
  625. package/skills/swift-testing/evals/triggers.json +16 -0
  626. package/skills/swift-testing/references/swift-testing-cheatsheet.md +81 -0
  627. package/skills/swiftui-patterns/SKILL.md +102 -0
  628. package/skills/swiftui-patterns/evals/triggers.json +16 -0
  629. package/skills/tdd-workflow/SKILL.md +67 -0
  630. package/skills/tdd-workflow/evals/triggers.json +14 -0
  631. package/skills/technical-writing/SKILL.md +95 -0
  632. package/skills/technical-writing/evals/triggers.json +14 -0
  633. package/skills/terraform-patterns/SKILL.md +122 -0
  634. package/skills/terraform-patterns/evals/triggers.json +16 -0
  635. package/skills/terraform-patterns/references/backends.md +67 -0
  636. package/skills/test-coverage-improvement/SKILL.md +107 -0
  637. package/skills/test-coverage-improvement/evals/triggers.json +16 -0
  638. package/skills/threat-modeling/SKILL.md +113 -0
  639. package/skills/threat-modeling/evals/triggers.json +16 -0
  640. package/skills/typescript-patterns/SKILL.md +122 -0
  641. package/skills/typescript-patterns/evals/triggers.json +16 -0
  642. package/skills/typescript-testing/SKILL.md +101 -0
  643. package/skills/typescript-testing/evals/triggers.json +16 -0
  644. package/skills/verification-loop/SKILL.md +70 -0
  645. package/skills/verification-loop/evals/triggers.json +14 -0
  646. package/skills/verification-loop/scripts/detect-checks.js +102 -0
  647. package/skills/vite-patterns/SKILL.md +117 -0
  648. package/skills/vite-patterns/evals/triggers.json +16 -0
  649. package/skills/vue-patterns/SKILL.md +104 -0
  650. package/skills/vue-patterns/evals/triggers.json +16 -0
  651. package/skills/web-accessibility/SKILL.md +119 -0
  652. package/skills/web-accessibility/evals/triggers.json +16 -0
  653. package/skills/web-performance/SKILL.md +107 -0
  654. package/skills/web-performance/evals/triggers.json +16 -0
  655. package/skills/web-scraping/SKILL.md +80 -0
  656. package/skills/web-scraping/evals/triggers.json +16 -0
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: rust-testing
3
+ description: Writing and organising tests for Rust crates with cargo test, covering #[cfg(test)] unit modules, integration tests under tests/, doc tests, trait-based fakes and mockall, property tests with proptest, #[tokio::test] for async code, and the cargo test flags for filtering and output. Use when adding or fixing Rust tests, deciding where a test belongs in a crate, testing async or I/O-bound Rust code, or getting a flaky cargo test run under control.
4
+ license: MIT
5
+ compatibility: Any Agent Skills host. Needs a Rust toolchain with cargo. proptest, mockall and tokio are used only if the project already depends on them or the user agrees to add them.
6
+ metadata:
7
+ kete-loom/version: "0.1.0"
8
+ kete-loom/category: testing
9
+ kete-loom/risk: runs-commands
10
+ kete-loom/requires: "cargo"
11
+ kete-loom/owner: "Kete-org"
12
+ ---
13
+
14
+ # Rust testing
15
+
16
+ Put each test where it can see exactly what it needs, keep it deterministic, and prove it with a `cargo test` run.
17
+
18
+ ## 0. Before you write a test
19
+
20
+ 1. Read `Cargo.toml` `[dev-dependencies]`: which of `proptest`, `mockall`, `tokio` (with which features), `tempfile`, `insta`, `rstest` are already there. Use those. **Ask the user** before adding a new dev-dependency.
21
+ 2. Check how CI runs tests (`.github/workflows/`, `Makefile`, `justfile`): plain `cargo test`, `cargo nextest run`, feature flags, `--workspace`. Use the same command.
22
+ 3. Run the existing suite once and record the result. If it already fails, **stop and tell the user** which tests fail before you change anything.
23
+
24
+ ## 1. Choose where the test goes
25
+
26
+ | Testing | Put it in | Can see |
27
+ |---|---|---|
28
+ | One function or private helper | `#[cfg(test)] mod tests` at the bottom of the same file | Private items via `use super::*;` |
29
+ | The crate's public API, as a user would call it | `tests/<feature>.rs` (each file is its own crate) | Only `pub` items |
30
+ | A usage example in the docs | A fenced code block in the item's `///` doc comment | Only `pub` items |
31
+ | A binary's behaviour end to end | `tests/cli.rs`, running the binary (for example with `assert_cmd` if present) | Process output |
32
+
33
+ - Binary crates: integration tests can't import `main.rs`. Move logic into `src/lib.rs` and keep `main.rs` thin.
34
+ - Shared integration helpers go in `tests/common/mod.rs` (not `tests/common.rs`, which cargo would run as its own test crate), pulled in with `mod common;`.
35
+
36
+ ## 2. Unit tests
37
+
38
+ ```rust
39
+ #[cfg(test)]
40
+ mod tests {
41
+ use super::*;
42
+
43
+ #[test]
44
+ fn parses_port_from_host_string() {
45
+ assert_eq!(parse_port("localhost:8080"), Ok(8080));
46
+ }
47
+
48
+ #[test]
49
+ fn rejects_missing_port() {
50
+ let err = parse_port("localhost").unwrap_err();
51
+ assert!(matches!(err, ParseError::MissingPort));
52
+ }
53
+
54
+ #[test]
55
+ fn reads_port_from_config_text() -> Result<(), Box<dyn std::error::Error>> {
56
+ let config: Config = "port = 8080".parse()?;
57
+ assert_eq!(config.port, 8080);
58
+ Ok(())
59
+ }
60
+
61
+ #[test]
62
+ #[should_panic(expected = "capacity must be non-zero")]
63
+ fn zero_capacity_panics() {
64
+ RingBuffer::<u8>::new(0);
65
+ }
66
+ }
67
+ ```
68
+
69
+ - Name tests after the behaviour (`rejects_missing_port`), not `test1`.
70
+ - Assert on the specific error variant with `matches!` instead of comparing `Debug` strings.
71
+ - Use `#[should_panic(expected = "...")]` only for documented panics; give the expected text so an unrelated panic doesn't pass.
72
+ - Tests may return `Result<(), E>` to use `?`; in tests, `unwrap()` and `expect()` are fine.
73
+
74
+ ## 3. Doc tests
75
+
76
+ - Every public function with a non-obvious use gets an example. Doc tests compile and run with `cargo test` (`cargo test --doc` for only these).
77
+ - Use `?` in examples by ending with `# Ok::<(), Box<dyn std::error::Error>>(())`; lines starting with `# ` are hidden from the rendered docs.
78
+ - Mark examples `no_run` when they need network or files, `compile_fail` to prove misuse doesn't compile, `ignore` only with a written reason.
79
+ - Doc tests run only for library targets. `cargo nextest` does not run doc tests, so CI that uses nextest needs a separate `cargo test --doc` step.
80
+
81
+ ## 4. Fakes and mocks via traits
82
+
83
+ Rust has no runtime monkey-patching. Make the boundary a trait and inject it.
84
+
85
+ 1. Define a small trait for the external dependency (clock, HTTP client, repository).
86
+ 2. Make the code under test generic over it (`struct Service<R: Repo>`) or take `&dyn Repo` / `Arc<dyn Repo>`.
87
+ 3. In tests, prefer a hand-written fake (an in-memory `HashMap` store) for state; use `mockall` (`#[cfg_attr(test, mockall::automock)]` on the trait) when you must assert on calls.
88
+ 4. Never mock the type under test, and never mock pure functions you could just call.
89
+
90
+ Examples for fakes, mockall expectations and time control: `references/fakes-proptest-async.md`.
91
+
92
+ ## 5. Property tests with proptest
93
+
94
+ Use them for parsers, encoders, data structures and anything with an invariant ("decode(encode(x)) == x", "sorted output is a permutation of input").
95
+
96
+ ```rust
97
+ use proptest::prelude::*;
98
+
99
+ proptest! {
100
+ #[test]
101
+ fn round_trips(s in "\\PC*") {
102
+ prop_assert_eq!(decode(&encode(&s)).unwrap(), s);
103
+ }
104
+ }
105
+ ```
106
+
107
+ - Use `prop_assert!` / `prop_assert_eq!` inside `proptest!` so failures shrink.
108
+ - Commit the `proptest-regressions/` files it writes; they replay past failures.
109
+
110
+ ## 6. Async tests
111
+
112
+ - `#[tokio::test]` runs on a current-thread runtime. Use `#[tokio::test(flavor = "multi_thread", worker_threads = 2)]` only when the code needs real parallelism (for example it calls `block_in_place`).
113
+ - `#[tokio::test]` needs tokio's `macros` and `rt` features for the test target (`[dev-dependencies] tokio = { ..., features = ["macros", "rt"] }`); the `multi_thread` flavor also needs `rt-multi-thread`.
114
+ - Don't sleep for real. With the `test-util` feature, `#[tokio::test(start_paused = true)]` and `tokio::time::advance` make timers instant and deterministic.
115
+ - Wrap anything that could hang in `tokio::time::timeout` so a bug fails the test instead of stalling CI.
116
+
117
+ ## 7. Running tests
118
+
119
+ | Goal | Command |
120
+ |---|---|
121
+ | Everything in a workspace | `cargo test --workspace --all-features` |
122
+ | Tests whose name contains a string | `cargo test parse_port` |
123
+ | One integration test file | `cargo test --test cli` |
124
+ | Only unit tests in the library | `cargo test --lib` |
125
+ | Only doc tests | `cargo test --doc` |
126
+ | Exact name match (full module path) | `cargo test -- --exact parser::tests::parses_port_from_host_string` |
127
+ | Show `println!` output | `cargo test -- --nocapture` |
128
+ | Run serially (shared global state) | `cargo test -- --test-threads=1` |
129
+ | Run ignored (slow) tests | `cargo test -- --ignored` or `-- --include-ignored` |
130
+ | Keep going after a failing test crate | `cargo test --no-fail-fast` |
131
+
132
+ Flags before `--` go to cargo; flags after `--` go to the test binary.
133
+
134
+ ## 8. Flaky tests
135
+
136
+ 1. Run the test alone and in a loop to reproduce: `for i in $(seq 50); do cargo test name -- --exact || break; done`.
137
+ 2. Common causes: tests sharing a file path, port, env var or global (run in parallel threads); real time; `HashMap` iteration order; unseeded randomness.
138
+ 3. Fix the cause: `tempfile::tempdir()` per test, bind port `0`, pass config instead of reading env vars, sort before asserting. `--test-threads=1` is a diagnostic, not a fix.
139
+
140
+ ## Never
141
+
142
+ - Never delete, `#[ignore]` or weaken an existing test to make the suite pass without the user's agreement.
143
+ - Never let tests touch the real network, the user's home directory or shared databases.
144
+ - Never assert on `format!("{:?}", ...)` output when a structured comparison is possible.
145
+
146
+ ## Report back
147
+
148
+ End with: tests added or changed (names and files), the exact command you ran, pass/fail counts, and anything not covered.
@@ -0,0 +1,16 @@
1
+ {
2
+ "should_trigger": [
3
+ "Add unit tests for the tokenizer module in my Rust crate",
4
+ "How do I mock the HTTP client trait in Rust so my service tests don't hit the network?",
5
+ "My #[tokio::test] hangs forever when the retry backoff sleeps, how do I test it without waiting?",
6
+ "Where should integration tests go in a Rust library and how do I share helpers between them?",
7
+ "Write a proptest that checks my Rust serializer round-trips arbitrary input"
8
+ ],
9
+ "should_not_trigger": [
10
+ "Refactor this Rust module to return thiserror errors instead of String",
11
+ "My Rust tests don't compile anymore after bumping tokio, error E0277 future is not Send",
12
+ "Review my Rust diff for blocking calls inside async functions",
13
+ "Write pytest fixtures for the Django user model",
14
+ "Set up Playwright end-to-end tests for the checkout flow"
15
+ ]
16
+ }
@@ -0,0 +1,113 @@
1
+ # Fakes, mockall, proptest strategies and async time
2
+
3
+ Read this when a test needs a test double, a custom proptest strategy, or control over time.
4
+
5
+ ## Hand-written fake
6
+
7
+ ```rust
8
+ pub trait Repo {
9
+ fn get(&self, id: u64) -> Result<Option<User>, RepoError>;
10
+ fn save(&self, user: &User) -> Result<(), RepoError>;
11
+ }
12
+
13
+ #[cfg(test)]
14
+ #[derive(Default)]
15
+ struct FakeRepo {
16
+ users: std::sync::Mutex<std::collections::HashMap<u64, User>>,
17
+ }
18
+
19
+ #[cfg(test)]
20
+ impl Repo for FakeRepo {
21
+ fn get(&self, id: u64) -> Result<Option<User>, RepoError> {
22
+ Ok(self.users.lock().unwrap().get(&id).cloned())
23
+ }
24
+ fn save(&self, user: &User) -> Result<(), RepoError> {
25
+ self.users.lock().unwrap().insert(user.id, user.clone());
26
+ Ok(())
27
+ }
28
+ }
29
+ ```
30
+
31
+ A fake keeps real behaviour (what you save, you can read back), so tests check outcomes instead of call sequences. Prefer it over a mock whenever state is involved.
32
+
33
+ ## mockall
34
+
35
+ ```rust
36
+ #[cfg_attr(test, mockall::automock)]
37
+ pub trait Mailer {
38
+ fn send(&self, to: &str, body: &str) -> Result<(), MailError>;
39
+ }
40
+
41
+ #[test]
42
+ fn sends_welcome_mail_once() {
43
+ let mut mailer = MockMailer::new();
44
+ mailer
45
+ .expect_send()
46
+ .withf(|to, _| to == "ama@example.com")
47
+ .times(1)
48
+ .returning(|_, _| Ok(()));
49
+
50
+ signup(&mailer, "ama@example.com").unwrap();
51
+ }
52
+ ```
53
+
54
+ - Expectations are checked when the mock is dropped; an unmet `times(1)` fails the test.
55
+ - Keep `mockall` in `[dev-dependencies]` and gate `automock` with `cfg_attr(test, ...)` so it never reaches release builds.
56
+ - If a mock needs more than three expectations, the unit is probably doing too much; consider a fake or a smaller seam.
57
+
58
+ ## Injecting time
59
+
60
+ ```rust
61
+ pub trait Clock { fn now(&self) -> std::time::SystemTime; }
62
+
63
+ struct FixedClock(std::time::SystemTime);
64
+ impl Clock for FixedClock { fn now(&self) -> std::time::SystemTime { self.0 } }
65
+ ```
66
+
67
+ Pass the clock into the code under test rather than calling `SystemTime::now()` inside it.
68
+
69
+ ## proptest strategies
70
+
71
+ ```rust
72
+ use proptest::prelude::*;
73
+
74
+ fn order() -> impl Strategy<Value = Order> {
75
+ (1u32..1000, prop::collection::vec("[a-z]{1,8}", 0..10))
76
+ .prop_map(|(qty, tags)| Order { qty, tags })
77
+ }
78
+
79
+ proptest! {
80
+ #![proptest_config(ProptestConfig::with_cases(512))]
81
+
82
+ #[test]
83
+ fn order_round_trips_through_text(o in order()) {
84
+ prop_assert_eq!(o.to_string().parse::<Order>().unwrap(), o);
85
+ }
86
+ }
87
+ ```
88
+
89
+ - Derive strategies for your own types with `prop_map` or, if the project uses it, `#[derive(Arbitrary)]` from `proptest-derive`.
90
+ - Use `prop_assume!` sparingly; filtering too many cases makes proptest give up.
91
+
92
+ ## Async time control (tokio `test-util` feature)
93
+
94
+ ```rust
95
+ #[tokio::test(start_paused = true)]
96
+ async fn retries_after_backoff() {
97
+ let handle = tokio::spawn(fetch_with_retry());
98
+ tokio::time::advance(std::time::Duration::from_secs(5)).await;
99
+ assert!(handle.await.unwrap().is_ok());
100
+ }
101
+ ```
102
+
103
+ With time paused, the runtime auto-advances to the next timer when every task is idle, so `sleep`-based code completes instantly and deterministically.
104
+
105
+ ## Temporary files
106
+
107
+ ```rust
108
+ let dir = tempfile::tempdir()?; // removed when `dir` is dropped
109
+ let path = dir.path().join("config.toml");
110
+ std::fs::write(&path, "port = 8080")?;
111
+ ```
112
+
113
+ Never write test files into the repository tree or a fixed path in `/tmp`.
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: search-first
3
+ description: Reuse-before-build check that runs before writing any new helper, utility, component or integration. Searches the current codebase for an existing function or pattern, then the project's installed dependencies and the standard library, then the package ecosystem, and weighs reuse, extend or build on fit, maintenance, licence, size and security before any code is written. Use when about to add a new function, module, wrapper or dependency, when the user asks "do we already have something for this" or "is there a library for X", or when a task smells like a solved problem (parsing, retries, dates, validation, caching).
4
+ license: MIT
5
+ compatibility: Any Agent Skills host. Ecosystem search needs network access and the project's package manager.
6
+ metadata:
7
+ kete-loom/version: "0.1.0"
8
+ kete-loom/category: meta
9
+ kete-loom/risk: network
10
+ kete-loom/owner: "Kete-org"
11
+ ---
12
+
13
+ # Search first
14
+
15
+ The cheapest code is code that already exists and is already tested. Spend a few minutes searching before writing anything new. Go outward in rings, and stop at the first ring that has a good fit.
16
+
17
+ ## Ring 1: this codebase
18
+
19
+ 1. Name the capability in a few ways: the verb and the noun ("retry", "backoff", "withRetry", "attempts"), domain words, and likely file names (`utils`, `helpers`, `lib`, `common`, `shared`).
20
+ 2. Search the code for each term, and for call sites of similar behaviour (for example search for `setTimeout` near `catch` when looking for retries).
21
+ 3. Check shared packages in a monorepo (`packages/`, `libs/`) and internal SDKs.
22
+ 4. Look at how neighbouring features solved the same problem. A local convention beats a better-in-theory approach.
23
+
24
+ If you find something close: use it as is, or extend it in place (add a parameter, generalise carefully, add a test). Don't fork a near-copy.
25
+
26
+ ## Ring 2: what's already installed
27
+
28
+ 1. Read the dependency manifest (`package.json`, `pyproject.toml`, `requirements*.txt`, `go.mod`, `Cargo.toml`, `pom.xml`, `build.gradle`, `Gemfile`, `composer.json`, `*.csproj`, `pubspec.yaml`).
29
+ 2. Check whether an installed library already does this (lodash, date libraries, validation libraries, HTTP clients with retry support, framework helpers).
30
+ 3. Check the language's standard library and the platform: many "helpers" are one built-in call (`structuredClone`, `Intl.DateTimeFormat`, `AbortSignal.timeout`, Python `itertools` and `functools`, Go `slices` and `maps`).
31
+
32
+ ## Ring 3: the ecosystem
33
+
34
+ Only when rings 1 and 2 have nothing:
35
+
36
+ 1. Search the package registry for the language and the official docs of the framework in use.
37
+ 2. Shortlist at most three candidates and check each against the table below. Use the registry page and the repository, not memory.
38
+
39
+ | Check | Look at | Red flag |
40
+ |---|---|---|
41
+ | Fit | README, API docs | Needs heavy wrapping to do your one job |
42
+ | Maintenance | Last release, open issues, response to issues | No release in years with open bugs, archived repo |
43
+ | Adoption | Download counts, dependents | Tiny usage for a critical path |
44
+ | Licence | Licence file | Incompatible with the project (ask if unsure) |
45
+ | Size and deps | Install size, transitive dependencies | Large tree for a small job |
46
+ | Security | Advisories (`npm audit`, `pip-audit`, `cargo audit`, GitHub advisories) | Unpatched advisories, typo-squat names |
47
+
48
+ ## Decide
49
+
50
+ Pick one, and say why in one or two lines:
51
+
52
+ - **Reuse**: an existing internal or installed option fits. Best default.
53
+ - **Extend**: an internal one almost fits. Change it in place, with a test.
54
+ - **Adopt**: a new dependency is clearly worth it. **Ask the user before adding any dependency**, and respect project rules (some repos forbid new dependencies in some folders).
55
+ - **Build**: nothing fits, or the job is a few lines and a dependency would cost more than it saves. Write the minimum, following local conventions, with a test.
56
+
57
+ ## Report
58
+
59
+ Before writing code, state:
60
+
61
+ ```
62
+ Need: <capability>
63
+ Searched: <terms and places>, installed deps, stdlib, <registry if used>
64
+ Found: <path or package, or "nothing suitable">
65
+ Decision: reuse | extend | adopt | build, because <reason>
66
+ ```
67
+
68
+ ## Never
69
+
70
+ - Never add a dependency without the user's approval.
71
+ - Never copy-paste a near-duplicate of an existing helper.
72
+ - Never pick a package by name or popularity alone without checking its repository.
73
+ - Never let the search turn into a research project: for a few-line helper, a couple of minutes is enough.
@@ -0,0 +1,14 @@
1
+ {
2
+ "should_trigger": [
3
+ "I need a retry-with-backoff helper for our API client, do we already have something like that?",
4
+ "Before you write a new slugify function, check the repo and our dependencies for one",
5
+ "Is there an existing library for parsing ISO 8601 durations or should we write our own?",
6
+ "Add CSV export to the reports page but reuse whatever we already have instead of writing from scratch"
7
+ ],
8
+ "should_not_trigger": [
9
+ "Audit our dependencies for known vulnerabilities and outdated packages",
10
+ "Research and compare three managed message brokers for our architecture decision, with citations",
11
+ "Refactor the duplicated validation code in the checkout module without changing behaviour",
12
+ "Find where the session timeout is configured in this app"
13
+ ]
14
+ }
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: security-review
3
+ description: Security review of a code change or module covering secrets, injection, authentication and authorization, input validation, data exposure, dependencies and unsafe configuration, with findings ranked by severity and concrete fixes. Use when the user asks for a security review, audit or vulnerability check, or before shipping code that handles auth, payments, user input, files or personal data.
4
+ license: MIT
5
+ compatibility: Any Agent Skills host. The secret scanner needs Node 18+ and git.
6
+ metadata:
7
+ kete-loom/version: "0.1.2"
8
+ kete-loom/category: security
9
+ kete-loom/risk: read-only
10
+ kete-loom/requires: "git, node"
11
+ kete-loom/owner: "Kete-org"
12
+ ---
13
+
14
+ # Security review
15
+
16
+ Find real, exploitable problems in the code in front of you and explain how to fix them. This skill is **read-only**: report findings, and change code only if the user asks.
17
+
18
+ ## 1. Set the scope
19
+
20
+ - Default scope is the current change: `git diff <base>...HEAD` plus uncommitted work. If the user names files or a module, review that instead.
21
+ - Identify the trust boundaries the code touches: HTTP handlers, CLI args, file uploads, webhooks, queues, database, third-party APIs, LLM prompts.
22
+
23
+ ## 2. Scan for secrets first
24
+
25
+ Run the scanner from the root of the repo being reviewed, pointing at this skill's folder (`<skill-dir>` is the folder holding this SKILL.md):
26
+
27
+ ```
28
+ node <skill-dir>/scripts/scan-secrets.js # changed files vs. HEAD and staged work
29
+ node <skill-dir>/scripts/scan-secrets.js --all # every tracked file
30
+ ```
31
+
32
+ Treat any hit as **critical** until shown to be a test fixture or placeholder. If a real secret was committed, tell the user it must be **rotated**: removing it from the code is not enough, because it stays in git history.
33
+
34
+ ## 3. Walk the checklist
35
+
36
+ Read `references/checklist.md` and apply each section that matches the code in scope. The essentials:
37
+
38
+ 1. **Injection**: SQL/NoSQL built with string concatenation, shell commands with user input, template injection, path traversal (`../`), SSRF in URL fetchers, prompt injection where user text reaches an LLM with tool access.
39
+ 2. **AuthN / AuthZ**: every sensitive route checks the session *and* that this user may act on this specific resource (no IDOR). Password hashing uses bcrypt/scrypt/argon2. Tokens expire.
40
+ 3. **Input validation**: validated at the boundary with a schema; size limits on bodies and uploads; file type checked by content, not just extension.
41
+ 4. **Data exposure**: no secrets, tokens, PII or stack traces in logs, errors or API responses; least-privilege queries (no `SELECT *` sent to clients).
42
+ 5. **Web**: CSRF protection on cookie-authenticated mutations, output encoding (XSS), strict CORS, security headers, secure cookie flags.
43
+ 6. **Payments and webhooks**: signatures verified on the raw body, amounts computed server-side, idempotency on retries.
44
+ 7. **Dependencies**: run the ecosystem's audit (`npm audit`, `pip-audit`, `govulncheck`, `cargo audit`) if available; flag new dependencies that are unmaintained or unpinned.
45
+ 8. **Config**: debug mode off in production, no default credentials, secrets read from the environment or a secret manager.
46
+
47
+ Trace each suspicious input from where it enters to where it is used before calling it a finding. No path from untrusted input means no finding.
48
+
49
+ ## 4. Report
50
+
51
+ Order findings by severity: **Critical** (exploitable now, data or money at risk), **High**, **Medium**, **Low**. For each finding give:
52
+
53
+ - **Where:** `file:line`
54
+ - **What:** one sentence on the flaw.
55
+ - **Exploit:** how an attacker would trigger it.
56
+ - **Fix:** a concrete code change.
57
+
58
+ Finish with what you checked and found clean, and anything you couldn't assess (for example infrastructure you can't see). Don't pad the report with generic advice; if the change is clean, say so.
@@ -0,0 +1,14 @@
1
+ {
2
+ "should_trigger": [
3
+ "Review my last commit for security vulnerabilities",
4
+ "Audit the login and password reset handlers before we go live",
5
+ "Did I accidentally commit any API keys or secrets in this branch?",
6
+ "Check this file upload endpoint for injection or path traversal issues"
7
+ ],
8
+ "should_not_trigger": [
9
+ "Run all the checks on my branch before I open a pull request",
10
+ "Explain the difference between authentication and authorization",
11
+ "Speed up this slow database query",
12
+ "Add a password strength meter to the signup form UI"
13
+ ]
14
+ }
@@ -0,0 +1,54 @@
1
+ # Security review checklist
2
+
3
+ Apply the sections that match the code in scope. Each item is a question; a "no" is a candidate finding to trace and confirm.
4
+
5
+ ## Secrets
6
+ - Are all keys, tokens and passwords read from the environment or a secret manager?
7
+ - Are `.env` files and key files listed in `.gitignore`?
8
+ - Do test fixtures use obviously fake values?
9
+
10
+ ## Injection
11
+ - Are all database queries parameterised (placeholders or ORM query builders, no string concatenation)?
12
+ - Is user input ever passed to a shell? If so, is it passed as an argument array, never through a shell string?
13
+ - Are file paths built from user input normalised and checked to stay inside an allowed directory?
14
+ - Do server-side URL fetches restrict scheme and host (SSRF), and block private and metadata IP ranges?
15
+ - Do templates auto-escape? Is any `dangerouslySetInnerHTML`, `v-html`, `|safe` or `innerHTML` fed user data?
16
+ - Can user-supplied text reach an LLM that can call tools or read private data? Is the tool scope limited?
17
+
18
+ ## Authentication
19
+ - Are passwords hashed with argon2, scrypt or bcrypt (never plain SHA/MD5)?
20
+ - Do sessions and tokens expire, and are they invalidated on logout and password change?
21
+ - Is login rate-limited? Do responses avoid revealing whether an account exists?
22
+ - Are JWTs verified with a fixed algorithm (no `alg: none`, no algorithm taken from the token)?
23
+
24
+ ## Authorization
25
+ - Does every handler that reads or changes a resource check that *this* user may access *this* resource (not only that they are logged in)?
26
+ - Are admin routes protected server-side, not just hidden in the UI?
27
+ - Are mass-assignment risks handled (only allowed fields copied from the request)?
28
+
29
+ ## Input validation
30
+ - Is every external input validated against a schema at the boundary?
31
+ - Are there limits on body size, upload size, array length and pagination size?
32
+ - Are uploaded files checked by content type and stored outside the web root with generated names?
33
+
34
+ ## Data exposure
35
+ - Do logs exclude passwords, tokens, card data and personal data?
36
+ - Do error responses hide stack traces and internal details in production?
37
+ - Do API responses return only the fields the client needs?
38
+
39
+ ## Web
40
+ - Are cookie-authenticated state changes protected against CSRF?
41
+ - Are cookies `HttpOnly`, `Secure` and `SameSite`?
42
+ - Is CORS restricted to known origins (no `*` with credentials)?
43
+ - Are security headers set (CSP, HSTS, X-Content-Type-Options, frame-ancestors)?
44
+
45
+ ## Payments and webhooks
46
+ - Is every webhook signature verified against the raw request body with a constant-time comparison?
47
+ - Are amounts and prices computed on the server, never trusted from the client?
48
+ - Is payment status confirmed with the provider's verify API before value is given?
49
+ - Are webhook handlers idempotent (the same event processed twice has no extra effect)?
50
+
51
+ ## Dependencies and config
52
+ - Does the dependency audit pass, or are remaining issues justified?
53
+ - Are new dependencies maintained and pinned in a lockfile?
54
+ - Is debug mode off and are default credentials removed in production config?
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ // Lightweight secret scanner. Read-only.
5
+ // node scan-secrets.js changed + staged + untracked files (vs HEAD)
6
+ // node scan-secrets.js --all every tracked file
7
+ // node scan-secrets.js <file> specific files
8
+ // Exit code 1 if anything is found. Values are masked in the output.
9
+
10
+ const fs = require('fs');
11
+ const { execFileSync } = require('child_process');
12
+
13
+ const RULES = [
14
+ ['AWS access key', /\b(AKIA|ASIA)[0-9A-Z]{16}\b/],
15
+ ['GitHub token', /\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36,}\b|\bgithub_pat_[A-Za-z0-9_]{60,}\b/],
16
+ ['Anthropic API key', /\bsk-ant-[A-Za-z0-9_-]{20,}\b/],
17
+ ['OpenAI API key', /\bsk-(proj-)?[A-Za-z0-9_-]{32,}\b/],
18
+ ['Paystack secret key', /\bsk_(live|test)_[a-f0-9]{40}\b/],
19
+ ['Stripe live key', /\b(sk|rk)_live_[A-Za-z0-9]{20,}\b/],
20
+ ['Slack token', /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/],
21
+ ['Google API key', /\bAIza[0-9A-Za-z_-]{35}\b/],
22
+ ['Private key block', /-----BEGIN (RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/],
23
+ ['JWT', /\beyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/],
24
+ ['Connection string with password', /\b(postgres(ql)?|mysql|mongodb(\+srv)?|redis|amqp):\/\/[^\s:@/]+:[^\s@/]{3,}@/i],
25
+ ['Hard-coded secret assignment', /\b(password|passwd|secret|api[_-]?key|access[_-]?token|auth[_-]?token)\b["']?\s*[:=]\s*["'][^"'\s]{8,}["']/i],
26
+ ];
27
+
28
+ const PLACEHOLDER = /(example|placeholder|changeme|your[_-]|xxxx|dummy|fake|<[^>]+>|\$\{|process\.env|os\.environ)/i;
29
+ const SKIP_FILE = /(\.lock$|lock\.json$|\.min\.js$|\.(png|jpe?g|gif|webp|ico|pdf|zip|gz|woff2?|ttf)$)/i;
30
+
31
+ function git(args) {
32
+ try {
33
+ return execFileSync('git', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
34
+ } catch {
35
+ return '';
36
+ }
37
+ }
38
+
39
+ function files(argv) {
40
+ const explicit = argv.filter((a) => !a.startsWith('--'));
41
+ if (explicit.length) return explicit;
42
+ if (argv.includes('--all')) return git(['ls-files']).split('\n').filter(Boolean);
43
+ const changed = [
44
+ // --relative: diff paths are repo-root based by default; ls-files is cwd based
45
+ ...git(['diff', '--name-only', '--relative', 'HEAD']).split('\n'),
46
+ ...git(['diff', '--name-only', '--relative', '--cached']).split('\n'),
47
+ ...git(['ls-files', '--others', '--exclude-standard']).split('\n'),
48
+ ];
49
+ return [...new Set(changed.filter(Boolean))];
50
+ }
51
+
52
+ function mask(s) {
53
+ return s.length <= 8 ? '****' : `${s.slice(0, 4)}…${s.slice(-2)} (${s.length} chars)`;
54
+ }
55
+
56
+ const hits = [];
57
+ for (const file of files(process.argv.slice(2))) {
58
+ if (SKIP_FILE.test(file) || !fs.existsSync(file) || fs.statSync(file).isDirectory()) continue;
59
+ if (fs.statSync(file).size > 1_000_000) continue;
60
+ const lines = fs.readFileSync(file, 'utf8').split('\n');
61
+ lines.forEach((line, i) => {
62
+ const seen = new Set();
63
+ for (const [label, re] of RULES) {
64
+ const m = re.exec(line);
65
+ // Check the match, not the line: `process.env.KEY || "sk_live_..."` is still a leak.
66
+ if (!m || PLACEHOLDER.test(m[0]) || seen.has(m[0])) continue;
67
+ seen.add(m[0]); // most specific rule wins (rules are ordered specific-first)
68
+ hits.push({ file, line: i + 1, rule: label, match: mask(m[0]) });
69
+ }
70
+ });
71
+ }
72
+
73
+ if (!hits.length) {
74
+ console.log('No likely secrets found.');
75
+ } else {
76
+ for (const h of hits) console.log(`${h.file}:${h.line} ${h.rule} ${h.match}`);
77
+ console.log(`\n${hits.length} possible secret(s). Confirm each; rotate any real secret that was committed.`);
78
+ process.exitCode = 1;
79
+ }