@dewtech/dare-cli 2.17.0 → 3.0.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 (344) hide show
  1. package/README.md +98 -3
  2. package/dist/__tests__/confidence.test.d.ts +2 -0
  3. package/dist/__tests__/confidence.test.d.ts.map +1 -0
  4. package/dist/__tests__/confidence.test.js +73 -0
  5. package/dist/__tests__/confidence.test.js.map +1 -0
  6. package/dist/__tests__/datamodel.test.d.ts +2 -0
  7. package/dist/__tests__/datamodel.test.d.ts.map +1 -0
  8. package/dist/__tests__/datamodel.test.js +131 -0
  9. package/dist/__tests__/datamodel.test.js.map +1 -0
  10. package/dist/__tests__/dna-detector.test.d.ts +2 -0
  11. package/dist/__tests__/dna-detector.test.d.ts.map +1 -0
  12. package/dist/__tests__/dna-detector.test.js +97 -0
  13. package/dist/__tests__/dna-detector.test.js.map +1 -0
  14. package/dist/__tests__/dna-facts.test.d.ts +2 -0
  15. package/dist/__tests__/dna-facts.test.d.ts.map +1 -0
  16. package/dist/__tests__/dna-facts.test.js +44 -0
  17. package/dist/__tests__/dna-facts.test.js.map +1 -0
  18. package/dist/__tests__/graph-renderer.test.d.ts +2 -0
  19. package/dist/__tests__/graph-renderer.test.d.ts.map +1 -0
  20. package/dist/__tests__/graph-renderer.test.js +85 -0
  21. package/dist/__tests__/graph-renderer.test.js.map +1 -0
  22. package/dist/__tests__/migration.test.d.ts +2 -0
  23. package/dist/__tests__/migration.test.d.ts.map +1 -0
  24. package/dist/__tests__/migration.test.js +77 -0
  25. package/dist/__tests__/migration.test.js.map +1 -0
  26. package/dist/__tests__/module-detector.test.d.ts +2 -0
  27. package/dist/__tests__/module-detector.test.d.ts.map +1 -0
  28. package/dist/__tests__/module-detector.test.js +83 -0
  29. package/dist/__tests__/module-detector.test.js.map +1 -0
  30. package/dist/__tests__/refine.test.js +49 -49
  31. package/dist/__tests__/reverse-facts.test.d.ts +2 -0
  32. package/dist/__tests__/reverse-facts.test.d.ts.map +1 -0
  33. package/dist/__tests__/reverse-facts.test.js +78 -0
  34. package/dist/__tests__/reverse-facts.test.js.map +1 -0
  35. package/dist/__tests__/review.test.js +38 -38
  36. package/dist/__tests__/validate.test.js +65 -65
  37. package/dist/bin/dare.js +32 -3
  38. package/dist/bin/dare.js.map +1 -1
  39. package/dist/commands/blueprint.js +122 -122
  40. package/dist/commands/dag.d.ts.map +1 -1
  41. package/dist/commands/dag.js +43 -79
  42. package/dist/commands/dag.js.map +1 -1
  43. package/dist/commands/dna.d.ts +3 -0
  44. package/dist/commands/dna.d.ts.map +1 -0
  45. package/dist/commands/dna.js +69 -0
  46. package/dist/commands/dna.js.map +1 -0
  47. package/dist/commands/migrate.d.ts +3 -0
  48. package/dist/commands/migrate.d.ts.map +1 -0
  49. package/dist/commands/migrate.js +101 -0
  50. package/dist/commands/migrate.js.map +1 -0
  51. package/dist/commands/new.d.ts +16 -0
  52. package/dist/commands/new.d.ts.map +1 -0
  53. package/dist/commands/new.js +103 -0
  54. package/dist/commands/new.js.map +1 -0
  55. package/dist/commands/reverse.d.ts +3 -0
  56. package/dist/commands/reverse.d.ts.map +1 -0
  57. package/dist/commands/reverse.js +201 -0
  58. package/dist/commands/reverse.js.map +1 -0
  59. package/dist/commands/welcome.d.ts +14 -0
  60. package/dist/commands/welcome.d.ts.map +1 -0
  61. package/dist/commands/welcome.js +29 -0
  62. package/dist/commands/welcome.js.map +1 -0
  63. package/dist/skills/commands/add.d.ts +23 -0
  64. package/dist/skills/commands/add.d.ts.map +1 -0
  65. package/dist/skills/commands/add.js +206 -0
  66. package/dist/skills/commands/add.js.map +1 -0
  67. package/dist/skills/commands/info.d.ts +14 -0
  68. package/dist/skills/commands/info.d.ts.map +1 -0
  69. package/dist/skills/commands/info.js +99 -0
  70. package/dist/skills/commands/info.js.map +1 -0
  71. package/dist/skills/commands/list.d.ts +19 -0
  72. package/dist/skills/commands/list.d.ts.map +1 -0
  73. package/dist/skills/commands/list.js +163 -0
  74. package/dist/skills/commands/list.js.map +1 -0
  75. package/dist/skills/commands/publish.d.ts +56 -0
  76. package/dist/skills/commands/publish.d.ts.map +1 -0
  77. package/dist/skills/commands/publish.js +272 -0
  78. package/dist/skills/commands/publish.js.map +1 -0
  79. package/dist/skills/commands/remove.d.ts +19 -0
  80. package/dist/skills/commands/remove.d.ts.map +1 -0
  81. package/dist/skills/commands/remove.js +96 -0
  82. package/dist/skills/commands/remove.js.map +1 -0
  83. package/dist/skills/commands/update.d.ts +31 -0
  84. package/dist/skills/commands/update.d.ts.map +1 -0
  85. package/dist/skills/commands/update.js +132 -0
  86. package/dist/skills/commands/update.js.map +1 -0
  87. package/dist/skills/index.d.ts +22 -0
  88. package/dist/skills/index.d.ts.map +1 -0
  89. package/dist/skills/index.js +33 -0
  90. package/dist/skills/index.js.map +1 -0
  91. package/dist/skills/manifest.d.ts +54 -0
  92. package/dist/skills/manifest.d.ts.map +1 -0
  93. package/dist/skills/manifest.js +162 -0
  94. package/dist/skills/manifest.js.map +1 -0
  95. package/dist/skills/registry-local.d.ts +67 -0
  96. package/dist/skills/registry-local.d.ts.map +1 -0
  97. package/dist/skills/registry-local.js +130 -0
  98. package/dist/skills/registry-local.js.map +1 -0
  99. package/dist/skills/registry-mock.json +109 -0
  100. package/dist/skills/registry-remote.d.ts +110 -0
  101. package/dist/skills/registry-remote.d.ts.map +1 -0
  102. package/dist/skills/registry-remote.js +246 -0
  103. package/dist/skills/registry-remote.js.map +1 -0
  104. package/dist/skills/registry.d.ts +49 -0
  105. package/dist/skills/registry.d.ts.map +1 -0
  106. package/dist/skills/registry.js +94 -0
  107. package/dist/skills/registry.js.map +1 -0
  108. package/dist/skills/tests/manifest.spec.d.ts +8 -0
  109. package/dist/skills/tests/manifest.spec.d.ts.map +1 -0
  110. package/dist/skills/tests/manifest.spec.js +176 -0
  111. package/dist/skills/tests/manifest.spec.js.map +1 -0
  112. package/dist/skills/tests/publish.spec.d.ts +12 -0
  113. package/dist/skills/tests/publish.spec.d.ts.map +1 -0
  114. package/dist/skills/tests/publish.spec.js +276 -0
  115. package/dist/skills/tests/publish.spec.js.map +1 -0
  116. package/dist/skills/tests/registry-local.spec.d.ts +8 -0
  117. package/dist/skills/tests/registry-local.spec.d.ts.map +1 -0
  118. package/dist/skills/tests/registry-local.spec.js +231 -0
  119. package/dist/skills/tests/registry-local.spec.js.map +1 -0
  120. package/dist/skills/tests/registry.spec.d.ts +7 -0
  121. package/dist/skills/tests/registry.spec.d.ts.map +1 -0
  122. package/dist/skills/tests/registry.spec.js +58 -0
  123. package/dist/skills/tests/registry.spec.js.map +1 -0
  124. package/dist/skills/tests/remote-registry.spec.d.ts +9 -0
  125. package/dist/skills/tests/remote-registry.spec.d.ts.map +1 -0
  126. package/dist/skills/tests/remote-registry.spec.js +357 -0
  127. package/dist/skills/tests/remote-registry.spec.js.map +1 -0
  128. package/dist/skills/tests/update.spec.d.ts +9 -0
  129. package/dist/skills/tests/update.spec.d.ts.map +1 -0
  130. package/dist/skills/tests/update.spec.js +166 -0
  131. package/dist/skills/tests/update.spec.js.map +1 -0
  132. package/dist/utils/banner.d.ts +28 -0
  133. package/dist/utils/banner.d.ts.map +1 -0
  134. package/dist/utils/banner.js +77 -0
  135. package/dist/utils/banner.js.map +1 -0
  136. package/dist/utils/banner.spec.d.ts +5 -0
  137. package/dist/utils/banner.spec.d.ts.map +1 -0
  138. package/dist/utils/banner.spec.js +253 -0
  139. package/dist/utils/banner.spec.js.map +1 -0
  140. package/dist/utils/confidence.d.ts +41 -0
  141. package/dist/utils/confidence.d.ts.map +1 -0
  142. package/dist/utils/confidence.js +101 -0
  143. package/dist/utils/confidence.js.map +1 -0
  144. package/dist/utils/datamodel.d.ts +41 -0
  145. package/dist/utils/datamodel.d.ts.map +1 -0
  146. package/dist/utils/datamodel.js +535 -0
  147. package/dist/utils/datamodel.js.map +1 -0
  148. package/dist/utils/dna-detector.d.ts +61 -0
  149. package/dist/utils/dna-detector.d.ts.map +1 -0
  150. package/dist/utils/dna-detector.js +354 -0
  151. package/dist/utils/dna-detector.js.map +1 -0
  152. package/dist/utils/dna-facts.d.ts +13 -0
  153. package/dist/utils/dna-facts.d.ts.map +1 -0
  154. package/dist/utils/dna-facts.js +109 -0
  155. package/dist/utils/dna-facts.js.map +1 -0
  156. package/dist/utils/excalidraw-renderer.d.ts +11 -71
  157. package/dist/utils/excalidraw-renderer.d.ts.map +1 -1
  158. package/dist/utils/excalidraw-renderer.js +29 -162
  159. package/dist/utils/excalidraw-renderer.js.map +1 -1
  160. package/dist/utils/graph-renderer.d.ts +115 -0
  161. package/dist/utils/graph-renderer.d.ts.map +1 -0
  162. package/dist/utils/graph-renderer.js +216 -0
  163. package/dist/utils/graph-renderer.js.map +1 -0
  164. package/dist/utils/migration.d.ts +64 -0
  165. package/dist/utils/migration.d.ts.map +1 -0
  166. package/dist/utils/migration.js +183 -0
  167. package/dist/utils/migration.js.map +1 -0
  168. package/dist/utils/module-detector.d.ts +46 -0
  169. package/dist/utils/module-detector.d.ts.map +1 -0
  170. package/dist/utils/module-detector.js +348 -0
  171. package/dist/utils/module-detector.js.map +1 -0
  172. package/dist/utils/project-generator.js +252 -252
  173. package/dist/utils/reverse-facts.d.ts +50 -0
  174. package/dist/utils/reverse-facts.d.ts.map +1 -0
  175. package/dist/utils/reverse-facts.js +291 -0
  176. package/dist/utils/reverse-facts.js.map +1 -0
  177. package/dist/utils/stack-bootstrap.js +371 -371
  178. package/package.json +8 -3
  179. package/templates/DARE-dag-example.yaml +280 -280
  180. package/templates/UPDATE-MANIFEST.json +48 -48
  181. package/templates/backend/node-nestjs/.env.example +9 -9
  182. package/templates/backend/node-nestjs/nest-cli.json +8 -8
  183. package/templates/backend/node-nestjs/package.json +50 -50
  184. package/templates/backend/node-nestjs/src/app.controller.ts +12 -12
  185. package/templates/backend/node-nestjs/src/app.module.ts +15 -15
  186. package/templates/backend/node-nestjs/src/app.service.ts +8 -8
  187. package/templates/backend/node-nestjs/src/main.ts +24 -24
  188. package/templates/backend/node-nestjs/tsconfig.json +21 -21
  189. package/templates/backend/php-laravel/.env.example +22 -22
  190. package/templates/backend/php-laravel/app/Http/Controllers/HealthController.php +15 -15
  191. package/templates/backend/php-laravel/composer.json +40 -40
  192. package/templates/backend/python-fastapi/.env.example +4 -4
  193. package/templates/backend/python-fastapi/app/api/router.py +8 -8
  194. package/templates/backend/python-fastapi/app/core/config.py +20 -20
  195. package/templates/backend/python-fastapi/main.py +35 -35
  196. package/templates/backend/python-fastapi/requirements.txt +13 -13
  197. package/templates/backend/rust-axum/.env.example +3 -3
  198. package/templates/backend/rust-axum/Cargo.toml +23 -23
  199. package/templates/backend/rust-axum/src/errors.rs +30 -30
  200. package/templates/backend/rust-axum/src/main.rs +32 -32
  201. package/templates/backend/rust-axum/src/routes.rs +6 -6
  202. package/templates/frontend/leptos-csr/.cargo/config.toml +2 -2
  203. package/templates/frontend/leptos-csr/Cargo.toml +16 -16
  204. package/templates/frontend/leptos-csr/Trunk.toml +10 -10
  205. package/templates/frontend/leptos-csr/index.html +11 -11
  206. package/templates/frontend/leptos-csr/src/lib.rs +20 -20
  207. package/templates/frontend/leptos-csr/style/main.scss +19 -19
  208. package/templates/frontend/leptos-fullstack/.cargo/config.toml +4 -4
  209. package/templates/frontend/leptos-fullstack/Cargo.toml +56 -56
  210. package/templates/frontend/leptos-fullstack/src/app.rs +49 -49
  211. package/templates/frontend/leptos-fullstack/src/lib.rs +9 -9
  212. package/templates/frontend/leptos-fullstack/src/main.rs +29 -29
  213. package/templates/frontend/leptos-fullstack/style/main.scss +19 -19
  214. package/templates/frontend/react/index.html +12 -12
  215. package/templates/frontend/react/package.json +35 -35
  216. package/templates/frontend/react/src/App.tsx +25 -25
  217. package/templates/frontend/react/src/main.tsx +9 -9
  218. package/templates/frontend/vue/package.json +32 -32
  219. package/templates/frontend/vue/src/App.vue +7 -7
  220. package/templates/frontend/vue/src/main.ts +10 -10
  221. package/templates/frontend/vue/src/router/index.ts +14 -14
  222. package/templates/frontend/vue/src/views/HomeView.vue +6 -6
  223. package/templates/hooks/pre-commit-dare-validate +24 -24
  224. package/templates/ide/antigravity/.agents/skills/dare-ax/SKILL.md +152 -0
  225. package/templates/ide/antigravity/.agents/skills/dare-dag-build/SKILL.md +154 -0
  226. package/templates/ide/antigravity/.agents/skills/dare-dag-run/SKILL.md +130 -0
  227. package/templates/ide/antigravity/.agents/skills/dare-dag-runner/SKILL.md +203 -203
  228. package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +63 -0
  229. package/templates/ide/antigravity/.agents/skills/dare-docker/SKILL.md +315 -0
  230. package/templates/ide/antigravity/.agents/skills/dare-frontend-design/SKILL.md +192 -0
  231. package/templates/ide/antigravity/.agents/skills/dare-laravel-api/SKILL.md +337 -0
  232. package/templates/ide/antigravity/.agents/skills/dare-layered-design/SKILL.md +166 -0
  233. package/templates/ide/antigravity/.agents/skills/dare-llm-integration/SKILL.md +217 -0
  234. package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +61 -0
  235. package/templates/ide/antigravity/.agents/skills/dare-quality-telemetry/SKILL.md +187 -0
  236. package/templates/ide/antigravity/.agents/skills/dare-realtime/SKILL.md +217 -0
  237. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +114 -114
  238. package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +108 -0
  239. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +111 -111
  240. package/templates/ide/antigravity/.agents/skills/dare-rust-leptos/SKILL.md +263 -0
  241. package/templates/ide/antigravity/.agents/skills/dare-rust-workspace/SKILL.md +275 -275
  242. package/templates/ide/antigravity/.agents/skills/dare-security/SKILL.md +274 -0
  243. package/templates/ide/antigravity/.agents/skills/dare-tasks/SKILL.md +265 -265
  244. package/templates/ide/antigravity/.agents/skills/dare-telemetry/SKILL.md +188 -0
  245. package/templates/ide/antigravity/.agents/skills/skill-fastapi-api/SKILL.md +343 -0
  246. package/templates/ide/antigravity/.agents/skills/skill-go-gin-api/SKILL.md +377 -0
  247. package/templates/ide/antigravity/.agents/skills/skill-mcp-server/SKILL.md +382 -0
  248. package/templates/ide/antigravity/.agents/skills/skill-nestjs-api/SKILL.md +326 -0
  249. package/templates/ide/antigravity/.agents/skills/skill-rails-api/SKILL.md +393 -0
  250. package/templates/ide/antigravity/templates/BLUEPRINT-template.md +193 -193
  251. package/templates/ide/antigravity/templates/DESIGN-template.md +129 -129
  252. package/templates/ide/antigravity/templates/TASK-SPEC-template.md +141 -141
  253. package/templates/ide/claude/.claude/commands/dare-ax.md +131 -0
  254. package/templates/ide/claude/.claude/commands/dare-blueprint.md +134 -134
  255. package/templates/ide/claude/.claude/commands/dare-bugfix-design.md +119 -0
  256. package/templates/ide/claude/.claude/commands/dare-dag-build.md +151 -151
  257. package/templates/ide/claude/.claude/commands/dare-dag-run.md +109 -109
  258. package/templates/ide/claude/.claude/commands/dare-dag-runner.md +117 -0
  259. package/templates/ide/claude/.claude/commands/dare-dag-viz.md +197 -197
  260. package/templates/ide/claude/.claude/commands/dare-design.md +69 -69
  261. package/templates/ide/claude/.claude/commands/dare-dna.md +75 -0
  262. package/templates/ide/claude/.claude/commands/dare-docker.md +207 -0
  263. package/templates/ide/claude/.claude/commands/dare-execute.md +152 -152
  264. package/templates/ide/claude/.claude/commands/dare-feature-design.md +147 -0
  265. package/templates/ide/claude/.claude/commands/dare-frontend-design.md +149 -0
  266. package/templates/ide/claude/.claude/commands/dare-laravel-api.md +211 -0
  267. package/templates/ide/claude/.claude/commands/dare-layered-design.md +124 -0
  268. package/templates/ide/claude/.claude/commands/dare-llm-integration.md +148 -0
  269. package/templates/ide/claude/.claude/commands/dare-migrate.md +72 -0
  270. package/templates/ide/claude/.claude/commands/dare-quality-telemetry.md +166 -0
  271. package/templates/ide/claude/.claude/commands/dare-realtime.md +159 -0
  272. package/templates/ide/claude/.claude/commands/dare-refine.md +145 -145
  273. package/templates/ide/claude/.claude/commands/dare-reverse.md +139 -0
  274. package/templates/ide/claude/.claude/commands/dare-review.md +113 -113
  275. package/templates/ide/claude/.claude/commands/dare-rust-leptos.md +269 -269
  276. package/templates/ide/claude/.claude/commands/dare-rust-workspace.md +209 -209
  277. package/templates/ide/claude/.claude/commands/dare-security.md +232 -232
  278. package/templates/ide/claude/.claude/commands/dare-tasks.md +70 -70
  279. package/templates/ide/claude/.claude/commands/dare-telemetry.md +132 -0
  280. package/templates/ide/claude/.claude/commands/skill-fastapi-api.md +205 -0
  281. package/templates/ide/claude/.claude/commands/skill-go-gin-api.md +232 -0
  282. package/templates/ide/claude/.claude/commands/skill-mcp-server.md +228 -0
  283. package/templates/ide/claude/.claude/commands/skill-nestjs-api.md +210 -0
  284. package/templates/ide/claude/.claude/commands/skill-rails-api.md +236 -0
  285. package/templates/ide/claude/.claude/settings.example.json +35 -35
  286. package/templates/ide/claude/CLAUDE.md +146 -146
  287. package/templates/ide/claude/templates/BLUEPRINT-template.md +193 -193
  288. package/templates/ide/claude/templates/DESIGN-template.md +129 -129
  289. package/templates/ide/claude/templates/TASK-SPEC-template.md +141 -141
  290. package/templates/ide/cursor/.cursor/commands/dag-viz.md +139 -0
  291. package/templates/ide/cursor/.cursor/commands/generate-blueprint.md +86 -86
  292. package/templates/ide/cursor/.cursor/commands/generate-design.md +35 -35
  293. package/templates/ide/cursor/.cursor/commands/generate-tasks.md +184 -184
  294. package/templates/ide/cursor/.cursor/commands/refine-task.md +107 -107
  295. package/templates/ide/cursor/.cursor/commands/review-task.md +91 -91
  296. package/templates/ide/cursor/.cursor/commands/run-dag.md +110 -110
  297. package/templates/ide/cursor/.cursor/rules/skill-ax.mdc +263 -0
  298. package/templates/ide/cursor/.cursor/rules/skill-dag-build.mdc +173 -0
  299. package/templates/ide/cursor/.cursor/rules/skill-dag-run.mdc +134 -0
  300. package/templates/ide/cursor/.cursor/rules/skill-dag-runner.mdc +221 -221
  301. package/templates/ide/cursor/.cursor/rules/skill-dna.mdc +63 -0
  302. package/templates/ide/cursor/.cursor/rules/skill-fastapi-api.mdc +352 -0
  303. package/templates/ide/cursor/.cursor/rules/skill-frontend-design.mdc +244 -0
  304. package/templates/ide/cursor/.cursor/rules/skill-go-gin-api.mdc +371 -0
  305. package/templates/ide/cursor/.cursor/rules/skill-layered-design.mdc +266 -0
  306. package/templates/ide/cursor/.cursor/rules/skill-llm-integration.mdc +295 -0
  307. package/templates/ide/cursor/.cursor/rules/skill-mcp-server.mdc +367 -0
  308. package/templates/ide/cursor/.cursor/rules/skill-migrate.mdc +58 -0
  309. package/templates/ide/cursor/.cursor/rules/skill-nestjs-api.mdc +346 -0
  310. package/templates/ide/cursor/.cursor/rules/skill-quality-telemetry.mdc +248 -0
  311. package/templates/ide/cursor/.cursor/rules/skill-rails-api.mdc +400 -0
  312. package/templates/ide/cursor/.cursor/rules/skill-realtime.mdc +262 -0
  313. package/templates/ide/cursor/.cursor/rules/skill-reverse.mdc +107 -0
  314. package/templates/ide/cursor/.cursor/rules/skill-rust-leptos.mdc +281 -0
  315. package/templates/ide/cursor/.cursor/rules/skill-rust-workspace.mdc +312 -312
  316. package/templates/ide/cursor/.cursor/rules/skill-security.mdc +245 -245
  317. package/templates/ide/cursor/templates/BLUEPRINT-template.md +193 -193
  318. package/templates/ide/cursor/templates/DESIGN-template.md +129 -129
  319. package/templates/ide/cursor/templates/TASK-SPEC-template.md +141 -141
  320. package/templates/shared/docker-compose.yml +41 -41
  321. package/dist/__tests__/dag-runner/adapters.test.d.ts +0 -2
  322. package/dist/__tests__/dag-runner/adapters.test.d.ts.map +0 -1
  323. package/dist/__tests__/dag-runner/adapters.test.js +0 -134
  324. package/dist/__tests__/dag-runner/adapters.test.js.map +0 -1
  325. package/dist/dag-runner/adapters/antigravity.d.ts +0 -6
  326. package/dist/dag-runner/adapters/antigravity.d.ts.map +0 -1
  327. package/dist/dag-runner/adapters/antigravity.js +0 -54
  328. package/dist/dag-runner/adapters/antigravity.js.map +0 -1
  329. package/dist/dag-runner/adapters/claude.d.ts +0 -6
  330. package/dist/dag-runner/adapters/claude.d.ts.map +0 -1
  331. package/dist/dag-runner/adapters/claude.js +0 -48
  332. package/dist/dag-runner/adapters/claude.js.map +0 -1
  333. package/dist/dag-runner/adapters/cursor.d.ts +0 -6
  334. package/dist/dag-runner/adapters/cursor.d.ts.map +0 -1
  335. package/dist/dag-runner/adapters/cursor.js +0 -58
  336. package/dist/dag-runner/adapters/cursor.js.map +0 -1
  337. package/dist/dag-runner/adapters/index.d.ts +0 -46
  338. package/dist/dag-runner/adapters/index.d.ts.map +0 -1
  339. package/dist/dag-runner/adapters/index.js +0 -55
  340. package/dist/dag-runner/adapters/index.js.map +0 -1
  341. package/dist/dag-runner/utils/timeout.d.ts +0 -27
  342. package/dist/dag-runner/utils/timeout.d.ts.map +0 -1
  343. package/dist/dag-runner/utils/timeout.js +0 -55
  344. package/dist/dag-runner/utils/timeout.js.map +0 -1
@@ -0,0 +1,295 @@
1
+ ---
2
+ description: Integração segura e eficiente com LLMs (Gemini, Claude, OpenAI, Ollama) em projetos DARE. Fornece LLMProvider abstraction, cache TTL, rate limit via token bucket, prompts versionados e validação de output via JSON Schema.
3
+ globs: prompts/**/*.md,**/llm*.ts,**/llm*.py,**/llm*.rs,**/llm*.go,**/providers/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Skill: LLM Integration DARE
8
+
9
+ Você é um especialista em integração com LLMs. Esta skill garante que toda chamada a LLM em projeto DARE seja **abstraída, cacheada, rate-limited, validada e defendida contra prompt injection**.
10
+
11
+ ## Arquitetura recomendada
12
+
13
+ ```
14
+ ┌──────────────────────────────────────────────────────┐
15
+ │ Handler / Service de negócio │
16
+ └──────────────────────────────────────────────────────┘
17
+ ↓ injeta
18
+ ┌──────────────────────────────────────────────────────┐
19
+ │ LLMProvider (interface) │
20
+ │ ├── GeminiProvider │
21
+ │ ├── ClaudeProvider │
22
+ │ ├── OpenAIProvider │
23
+ │ └── OllamaProvider (local) │
24
+ └──────────────────────────────────────────────────────┘
25
+ ↓ wrap
26
+ ┌──────────────────────────────────────────────────────┐
27
+ │ Cache (TTL) + RateLimit (token bucket) + Schema │
28
+ └──────────────────────────────────────────────────────┘
29
+
30
+ ┌──────────────────────────────────────────────────────┐
31
+ │ HTTP call externo │
32
+ └──────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ ## Os 5 pilares
36
+
37
+ ### 1. LLMProvider abstraction
38
+
39
+ Nunca chame SDK direto em Handler ou Service de negócio.
40
+
41
+ ```typescript
42
+ // ❌ Errado
43
+ class SummaryService {
44
+ async run(text: string) {
45
+ const client = new GoogleGenAI({ apiKey: 'xxx' });
46
+ return client.generateContent({ contents: text });
47
+ }
48
+ }
49
+
50
+ // ✅ Certo
51
+ class SummaryService {
52
+ constructor(private llm: LLMProvider) {}
53
+ async run(text: string) {
54
+ return this.llm.complete({
55
+ promptId: 'summarize-v1',
56
+ input: { text },
57
+ schema: SummarySchema,
58
+ });
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### 2. Cache em memória com TTL
64
+
65
+ Key = `hash(promptId + input + model)`. TTL configurável (default 1h).
66
+
67
+ **AP-02:** sem cache = custo explode em loops + latência ruim.
68
+
69
+ ### 3. Rate limit via token bucket
70
+
71
+ | Provider | Limite típico |
72
+ |---|---|
73
+ | Gemini Free | 15 RPM, 1M tokens/dia |
74
+ | Claude tier 1 | 50 RPM |
75
+ | OpenAI tier 1 | 500 RPM |
76
+ | Ollama local | sem limite, latência alta |
77
+
78
+ Token bucket por provider, configurado em `app.config`.
79
+
80
+ ### 4. Prompts versionados
81
+
82
+ Prompts vivem em `prompts/<id>.v<n>.md`:
83
+
84
+ ```markdown
85
+ ---
86
+ id: summarize
87
+ version: 1
88
+ model: gemini-2.0-flash
89
+ temperature: 0.2
90
+ max_tokens: 500
91
+ schema: SummarySchema
92
+ ---
93
+
94
+ # System
95
+ You are a concise summarizer. Output JSON matching: {schema}
96
+
97
+ # User
98
+ Summarize the following text in 3 bullet points:
99
+
100
+ <text>{{ text }}</text>
101
+ ```
102
+
103
+ Substituição com template engine **seguro** (Jinja2 sandboxed, Handlebars, string-interp com escape). Nunca `eval` ou `f-string` direta com user input.
104
+
105
+ ### 5. Validação de output
106
+
107
+ LLM mente. Sempre valide:
108
+
109
+ ```typescript
110
+ const raw = await llm.complete({...});
111
+ const result = SummarySchema.parse(raw); // Zod/Pydantic/ajv
112
+ if (!result.success) {
113
+ throw new LLMOutputInvalidError(result.error);
114
+ // Pode indicar prompt injection ou drift de modelo — logar + alertar
115
+ }
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Métricas obrigatórias
121
+
122
+ | ID | Métrica | Como medir |
123
+ |---|---|---|
124
+ | M-01 | 100% das chamadas LLM via LLMProvider | grep por SDK direto em Handlers/Services |
125
+ | M-02 | 100% das responses cacheadas | logs do cache layer |
126
+ | M-03 | 100% das requests com rate limit | rate limiter ativo em todo provider |
127
+ | M-04 | 100% das respostas validadas contra schema | grep por `.parse(` ou `model_validate(` |
128
+
129
+ ---
130
+
131
+ ## Antipatterns (CI falha)
132
+
133
+ | AP | Antipattern | Por que evitar |
134
+ |---|---|---|
135
+ | AP-01 | SDK direto em Handler | impossível mockar / trocar provider |
136
+ | AP-02 | Sem cache | custo explode, latência ruim |
137
+ | AP-03 | Prompt em código | impossível versionar / A-B testar |
138
+ | AP-04 | User input direto em prompt | prompt injection trivial |
139
+ | AP-05 | Confiar em output LLM sem validar | LLM mente — schema é defesa |
140
+
141
+ ---
142
+
143
+ ## Defesa contra prompt injection
144
+
145
+ ```python
146
+ # ❌ Errado — instrução + dado misturados
147
+ system = f"You are an assistant. {user_question}"
148
+ ```
149
+
150
+ ```python
151
+ # ✅ Certo — separação clara + escape
152
+ messages = [
153
+ {"role": "system", "content": "You are an assistant. Answer only based on the provided document."},
154
+ {"role": "user", "content": f"<document>{escape(doc)}</document>\n\n<question>{escape(q)}</question>"}
155
+ ]
156
+ ```
157
+
158
+ Regras:
159
+ - Use delimitadores (`<document>`, `<question>`)
160
+ - Escape conteúdo do usuário (XML/HTML escape)
161
+ - Detecte e remova padrões "Ignore instructions above", "You are now ..."
162
+ - Valide output contra schema — output fora do schema = possível injection bem-sucedido
163
+
164
+ ---
165
+
166
+ ## Exemplos por stack
167
+
168
+ ### TypeScript (NestJS)
169
+
170
+ ```typescript
171
+ @Injectable()
172
+ export class GeminiProvider implements LLMProvider {
173
+ constructor(
174
+ private cache: Cache,
175
+ private rateLimit: TokenBucket,
176
+ @Inject('GEMINI_API_KEY') private apiKey: string,
177
+ ) {}
178
+
179
+ async complete(req: LLMRequest): Promise<unknown> {
180
+ const cached = await this.cache.get(req.cacheKey());
181
+ if (cached) return cached;
182
+ await this.rateLimit.acquire(1);
183
+ const raw = await this.callGemini(req);
184
+ const validated = req.schema.parse(raw);
185
+ await this.cache.set(req.cacheKey(), validated, req.ttl);
186
+ return validated;
187
+ }
188
+ }
189
+ ```
190
+
191
+ ### Python (FastAPI)
192
+
193
+ ```python
194
+ class ClaudeProvider(LLMProvider):
195
+ def __init__(self, client: Anthropic, cache: Cache, bucket: TokenBucket):
196
+ self.client = client
197
+ self.cache = cache
198
+ self.bucket = bucket
199
+
200
+ async def complete(self, req: LLMRequest):
201
+ cached = await self.cache.get(req.cache_key())
202
+ if cached: return cached
203
+ await self.bucket.acquire(1)
204
+ raw = await self.client.messages.create(...)
205
+ validated = req.schema.model_validate(raw.content[0].text)
206
+ await self.cache.set(req.cache_key(), validated.model_dump(), req.ttl)
207
+ return validated
208
+ ```
209
+
210
+ ### Rust/Axum
211
+
212
+ ```rust
213
+ pub struct GeminiProvider {
214
+ client: reqwest::Client,
215
+ cache: Arc<dyn Cache>,
216
+ bucket: Arc<TokenBucket>,
217
+ }
218
+
219
+ #[async_trait]
220
+ impl LLMProvider for GeminiProvider {
221
+ async fn complete<T: DeserializeOwned + JsonSchema>(&self, req: LLMRequest<T>) -> Result<T> {
222
+ if let Some(cached) = self.cache.get(&req.cache_key()).await? {
223
+ return Ok(cached);
224
+ }
225
+ self.bucket.acquire(1).await?;
226
+ let raw = self.call_gemini(&req).await?;
227
+ let validated: T = serde_json::from_value(raw)?;
228
+ self.cache.set(&req.cache_key(), &validated, req.ttl).await?;
229
+ Ok(validated)
230
+ }
231
+ }
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Observabilidade obrigatória
237
+
238
+ Logue estruturado por chamada:
239
+
240
+ ```json
241
+ {
242
+ "promptId": "summarize",
243
+ "version": 1,
244
+ "model": "gemini-2.0-flash",
245
+ "cacheHit": false,
246
+ "tokensIn": 1342,
247
+ "tokensOut": 287,
248
+ "estimatedCostUsd": 0.0021,
249
+ "latencyMs": 850,
250
+ "schemaValid": true
251
+ }
252
+ ```
253
+
254
+ Não logue: prompt completo (privacidade), output completo (PII), API keys.
255
+
256
+ ---
257
+
258
+ ## Aplicação por fase DARE
259
+
260
+ ### Design
261
+ - Listar quais LLMs serão usados (provider, modelo)
262
+ - Estimar volume de calls/dia → ajustar rate limit
263
+ - Definir prompts iniciais com schema
264
+
265
+ ### Blueprint
266
+ - Diagrama da camada LLM (provider, cache, rate limit)
267
+ - Estratégia de fallback (primary → secondary)
268
+ - Estratégia de versionamento de prompts
269
+
270
+ ### Tasks
271
+ - Task dedicada: "Criar LLMProvider + cache + rate limit"
272
+ - Task por prompt: "Extrair prompt X para `prompts/x.v1.md`"
273
+ - Task de validação: "Adicionar schema Zod/Pydantic para cada prompt"
274
+
275
+ ### Execute
276
+ - Ralph Loop: grep falha se SDK direto em Service/Handler
277
+ - Métricas M-01 a M-04 reportadas em cada PR
278
+
279
+ ---
280
+
281
+ ## Checklist final
282
+
283
+ - [ ] Interface `LLMProvider` definida
284
+ - [ ] Pelo menos 1 provider implementado
285
+ - [ ] Cache em memória com TTL configurado
286
+ - [ ] Token bucket configurado por provider
287
+ - [ ] Todos os prompts em `prompts/<id>.v<n>.md`
288
+ - [ ] Schema para cada prompt
289
+ - [ ] Validação de output em todo chamador
290
+ - [ ] Logs estruturados com tokens + custo
291
+ - [ ] Defesa contra prompt injection em prompts com user input
292
+
293
+ ---
294
+
295
+ Skill licenciada MIT — parte do DARE Method v3.
@@ -0,0 +1,367 @@
1
+ ---
2
+ description: Padrões DARE para servidores MCP (Model Context Protocol da Anthropic) em TypeScript ou Python. Tools, resources, prompts; transports stdio/SSE/HTTP; validação Zod/Pydantic; autorização por tool; observabilidade; testes; publicação.
3
+ globs: **/*.ts,**/*.py,package.json,pyproject.toml,claude_desktop_config.json
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Skill: MCP Server DARE
8
+
9
+ Você é um especialista em servidores MCP (Model Context Protocol). Esta skill garante MCP servers **bem estruturados, seguros, testáveis e publicáveis**, expondo tools/resources/prompts via stdio, SSE ou HTTP.
10
+
11
+ ## O que é MCP em 30 segundos
12
+
13
+ Protocolo aberto da Anthropic para conectar agentes (Claude Code, Claude Desktop, Cursor, etc.) a fontes de dados e ações externas. Server expõe:
14
+
15
+ - **Tools** — funções chamáveis pelo agente
16
+ - **Resources** — dados leitáveis (URI + mimeType)
17
+ - **Prompts** — templates parametrizados
18
+
19
+ Transports:
20
+
21
+ | Transport | Quando usar |
22
+ |---|---|
23
+ | **stdio** | Server local, agente spawnea processo |
24
+ | **SSE** | Server remoto, streaming bidirectional |
25
+ | **HTTP** | Server remoto stateless |
26
+
27
+ ---
28
+
29
+ ## Stack canônica
30
+
31
+ ### TypeScript
32
+
33
+ - Node 20+ + TS 5.5+
34
+ - `@modelcontextprotocol/sdk` SDK oficial
35
+ - Zod para schemas
36
+ - vitest
37
+
38
+ ### Python
39
+
40
+ - Python 3.11+
41
+ - `mcp` (SDK oficial, `pip install mcp`)
42
+ - Pydantic v2
43
+ - pytest + pytest-asyncio
44
+
45
+ ---
46
+
47
+ ## Estrutura
48
+
49
+ ```
50
+ mcp-meu-server/
51
+ ├── package.json (ou pyproject.toml)
52
+ ├── src/
53
+ │ ├── index.ts ← stdio entrypoint
54
+ │ ├── server.ts ← criação do MCP Server
55
+ │ ├── tools/
56
+ │ │ ├── create_issue.ts
57
+ │ │ └── search_issues.ts
58
+ │ ├── resources/
59
+ │ ├── prompts/
60
+ │ ├── schemas/
61
+ │ └── lib/ ← clientes externos
62
+ └── tests/
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Exemplo TypeScript (stdio)
68
+
69
+ ```typescript
70
+ // src/index.ts
71
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
72
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
73
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
74
+ import { z } from 'zod';
75
+
76
+ const CreateIssueInput = z.object({
77
+ title: z.string().min(1).max(255),
78
+ description: z.string().optional(),
79
+ priority: z.enum(['low', 'medium', 'high']).default('medium'),
80
+ team_id: z.string().uuid(),
81
+ });
82
+
83
+ const server = new Server(
84
+ { name: 'meu-server', version: '1.0.0' },
85
+ { capabilities: { tools: {}, resources: {}, prompts: {} } }
86
+ );
87
+
88
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
89
+ tools: [{
90
+ name: 'create_issue',
91
+ description: 'Create a new issue in Linear with the given title, description, and priority',
92
+ inputSchema: CreateIssueInput.shape,
93
+ }],
94
+ }));
95
+
96
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
97
+ if (req.params.name !== 'create_issue') throw new Error('unknown tool');
98
+ const input = CreateIssueInput.parse(req.params.arguments);
99
+ const result = await linearClient.createIssue(input);
100
+ return { content: [{ type: 'text', text: JSON.stringify(result) }] };
101
+ });
102
+
103
+ const transport = new StdioServerTransport();
104
+ await server.connect(transport);
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Exemplo Python (stdio)
110
+
111
+ ```python
112
+ import asyncio
113
+ from mcp.server import Server
114
+ from mcp.server.stdio import stdio_server
115
+ from mcp.types import Tool, TextContent
116
+ from pydantic import BaseModel, Field
117
+
118
+ app = Server("meu-server")
119
+
120
+ class CreateIssueInput(BaseModel):
121
+ title: str = Field(min_length=1, max_length=255)
122
+ description: str | None = None
123
+ priority: str = Field(default="medium", pattern="^(low|medium|high)$")
124
+ team_id: str
125
+
126
+ @app.list_tools()
127
+ async def list_tools() -> list[Tool]:
128
+ return [
129
+ Tool(
130
+ name="create_issue",
131
+ description="Create a new issue in Linear",
132
+ inputSchema=CreateIssueInput.model_json_schema(),
133
+ )
134
+ ]
135
+
136
+ @app.call_tool()
137
+ async def call_tool(name: str, arguments: dict) -> list[TextContent]:
138
+ if name != "create_issue":
139
+ raise ValueError(f"unknown tool: {name}")
140
+ input_data = CreateIssueInput.model_validate(arguments)
141
+ result = await linear_client.create_issue(input_data)
142
+ return [TextContent(type="text", text=result.model_dump_json())]
143
+
144
+ async def main():
145
+ async with stdio_server() as (read, write):
146
+ await app.run(read, write, app.create_initialization_options())
147
+
148
+ if __name__ == "__main__":
149
+ asyncio.run(main())
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Resources
155
+
156
+ ```typescript
157
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
158
+ resources: [{
159
+ uri: 'linear://schema',
160
+ name: 'Linear Issue Schema',
161
+ mimeType: 'application/json',
162
+ }],
163
+ }));
164
+
165
+ server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
166
+ if (req.params.uri === 'linear://schema') {
167
+ return {
168
+ contents: [{
169
+ uri: req.params.uri,
170
+ mimeType: 'application/json',
171
+ text: JSON.stringify(schema),
172
+ }],
173
+ };
174
+ }
175
+ throw new Error('unknown resource');
176
+ });
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Prompts
182
+
183
+ ```typescript
184
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
185
+ prompts: [{
186
+ name: 'triage_issue',
187
+ description: 'Triage an issue and assign priority',
188
+ arguments: [
189
+ { name: 'description', description: 'Issue description', required: true },
190
+ ],
191
+ }],
192
+ }));
193
+
194
+ server.setRequestHandler(GetPromptRequestSchema, async (req) => ({
195
+ messages: [{
196
+ role: 'user',
197
+ content: {
198
+ type: 'text',
199
+ text: `Triage this issue and suggest a priority:\n\n${req.params.arguments?.description}`,
200
+ },
201
+ }],
202
+ }));
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Autorização por tool
208
+
209
+ ```typescript
210
+ // Tool destrutiva exige confirm explícito
211
+ if (input.confirm !== 'YES_I_AM_SURE') {
212
+ throw new Error('this tool requires confirmation');
213
+ }
214
+
215
+ // Tool admin
216
+ if (!callerHasRole('admin')) {
217
+ throw new Error('admin only');
218
+ }
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Observabilidade
224
+
225
+ **Crítico em stdio:** o protocolo MCP usa **stdout**. Logs SEMPRE em stderr.
226
+
227
+ ```typescript
228
+ console.error(JSON.stringify({
229
+ ts: new Date().toISOString(),
230
+ tool: req.params.name,
231
+ duration_ms: Date.now() - start,
232
+ success: true,
233
+ // sem args (PII), sem result completo (pode ter PII)
234
+ }));
235
+ ```
236
+
237
+ ---
238
+
239
+ ## Testes
240
+
241
+ ```typescript
242
+ // Unit
243
+ import { test, expect } from 'vitest';
244
+ test('valida input correto', () => {
245
+ const valid = CreateIssueInput.parse({
246
+ title: 'Test',
247
+ team_id: '550e8400-e29b-41d4-a716-446655440000',
248
+ });
249
+ expect(valid.priority).toBe('medium');
250
+ });
251
+
252
+ test('rejeita team_id inválido', () => {
253
+ expect(() => CreateIssueInput.parse({
254
+ title: 'Test',
255
+ team_id: 'not-uuid',
256
+ })).toThrow();
257
+ });
258
+
259
+ // E2E com client MCP
260
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
261
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
262
+
263
+ const transport = new StdioClientTransport({ command: 'node', args: ['dist/index.js'] });
264
+ const client = new Client({ name: 'test', version: '0.0.0' }, { capabilities: {} });
265
+ await client.connect(transport);
266
+ const tools = await client.listTools();
267
+ expect(tools.tools.map(t => t.name)).toContain('create_issue');
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Antipatterns
273
+
274
+ | AP | Antipattern | Por quê |
275
+ |---|---|---|
276
+ | AP-01 | Logs no stdout (stdio) | Quebra o protocolo MCP |
277
+ | AP-02 | Tool sem schema de input | Cliente passa lixo |
278
+ | AP-03 | Sem validação no server | Confia no client (errado) |
279
+ | AP-04 | Tool destrutiva sem confirm | Agente apaga sem querer |
280
+ | AP-05 | Secrets em código | Use env vars |
281
+ | AP-06 | Tool name vago (`do_thing`) | Agente não sabe quando usar |
282
+ | AP-07 | Description curto/vago | Agente erra na escolha |
283
+ | AP-08 | Resource sem mimeType | Cliente não parseia |
284
+ | AP-09 | Tool sem error handling | Erro vira crash em vez de mensagem |
285
+
286
+ ---
287
+
288
+ ## Publicação
289
+
290
+ ### Pré-requisitos
291
+
292
+ - `README.md` com:
293
+ - Instalação e configuração
294
+ - Lista de tools/resources/prompts
295
+ - Variáveis de ambiente
296
+ - Exemplo `claude_desktop_config.json`
297
+ - `LICENSE` (MIT recomendado)
298
+ - `package.json`/`pyproject.toml` versionado
299
+
300
+ ### Distribuição
301
+
302
+ | Stack | Comando |
303
+ |---|---|
304
+ | TypeScript | `npm publish` |
305
+ | Python | `python -m build && twine upload dist/*` |
306
+ | Docker (SSE/HTTP) | multi-stage build + push para registry |
307
+
308
+ ### Config no Claude Desktop
309
+
310
+ ```json
311
+ {
312
+ "mcpServers": {
313
+ "meu-server": {
314
+ "command": "node",
315
+ "args": ["/abs/path/to/dist/index.js"],
316
+ "env": {
317
+ "LINEAR_API_KEY": "lin_api_..."
318
+ }
319
+ }
320
+ }
321
+ }
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Aplicação por fase DARE
327
+
328
+ ### Design
329
+ - Definir capabilities (tools, resources, prompts) com nomes e descrições claras
330
+ - Decidir transport (stdio/SSE/HTTP)
331
+ - Listar variáveis de ambiente necessárias
332
+
333
+ ### Blueprint
334
+ - Estrutura de pastas
335
+ - Schemas Zod/Pydantic por tool
336
+ - Estratégia de autorização
337
+
338
+ ### Tasks
339
+ - Por tool: 1 task (schema + handler + teste)
340
+ - Task de configuração transport + entrypoint
341
+ - Task de publicação (README + LICENSE + CI release)
342
+
343
+ ### Execute
344
+ - Ralph Loop:
345
+ ```bash
346
+ npm run lint && npm test && npm run build
347
+ # ou
348
+ ruff check . && mypy . && pytest
349
+ ```
350
+
351
+ ---
352
+
353
+ ## Checklist final
354
+
355
+ - [ ] Transport escolhido (stdio/SSE/HTTP) com justificativa
356
+ - [ ] Cada tool tem name descritivo, description completa, input schema
357
+ - [ ] Validação Zod/Pydantic no início de cada handler
358
+ - [ ] Tools destrutivas exigem `confirm`
359
+ - [ ] Logs em stderr (stdio) com JSON estruturado
360
+ - [ ] Secrets via env vars, nunca em código
361
+ - [ ] Testes unit + E2E com client MCP
362
+ - [ ] README + LICENSE MIT
363
+ - [ ] Publicação configurada (npm/PyPI/Docker)
364
+
365
+ ---
366
+
367
+ Skill licenciada MIT — parte do DARE Method v3.