@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,400 @@
1
+ ---
2
+ description: Padrões DARE para APIs em Ruby on Rails 8 — API mode, ActiveRecord, Solid Queue, Solid Cable, Action Cable, strong parameters, services, serializers (Blueprinter/Alba), Devise/JWT, rack-attack, rswag/grape-swagger.
3
+ globs: **/*.rb,Gemfile,Gemfile.lock,config/**/*.rb,db/**/*.rb,spec/**/*.rb,app/**/*.rb
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Skill: Rails 8 API DARE
8
+
9
+ Você é um desenvolvedor sênior Ruby on Rails 8.x especializado em APIs. Esta skill garante código **idiomático Rails, com Layered Design, Solid Queue/Cable, serializers explícitos e auth/autz robustos**.
10
+
11
+ ## Stack canônica
12
+
13
+ - **Ruby 3.3+**
14
+ - **Rails 8.x** modo API (`rails new --api`)
15
+ - **PostgreSQL 16**
16
+ - **Solid Queue** — substitui Sidekiq, built-in Rails 8
17
+ - **Solid Cable** — substitui Redis para Action Cable, built-in Rails 8
18
+ - **Devise + devise-jwt** ou JWT puro
19
+ - **Pundit** ou **CanCanCan**
20
+ - **Blueprinter** ou **Alba** para serializers
21
+ - **rack-attack** para rate limit
22
+ - **rswag** para OpenAPI/Swagger
23
+ - **RSpec + FactoryBot + Faker**
24
+ - **Rubocop + rubocop-rails-omakase** (estilo oficial)
25
+ - **bundler-audit**
26
+
27
+ ---
28
+
29
+ ## Layered Design em Rails
30
+
31
+ | Camada DARE | Pasta Rails |
32
+ |---|---|
33
+ | Handler | `app/controllers/api/v1/` |
34
+ | Service | `app/services/` (ou `app/interactors/`) |
35
+ | Repository | `app/repositories/` (opcional em Rails) |
36
+ | Model | `app/models/` |
37
+ | Presenter | `app/blueprints/` ou `app/serializers/` |
38
+
39
+ > Em Rails 8 API, Repositories são opcionais — ActiveRecord queries dentro de Services bem encapsulados é aceito.
40
+
41
+ ---
42
+
43
+ ## Controllers
44
+
45
+ ```ruby
46
+ module Api
47
+ module V1
48
+ class UsersController < ApplicationController
49
+ before_action :authenticate_user!
50
+
51
+ def create
52
+ result = RegisterUser.new(user_params).call
53
+ if result.success?
54
+ render json: UserBlueprint.render(result.user), status: :created
55
+ else
56
+ render json: { error: result.error_code }, status: :conflict
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def user_params
63
+ params.require(:user).permit(:email, :name, :password)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ ```
69
+
70
+ Regras:
71
+ - Apenas: autenticar → strong params → chamar Service → renderizar Blueprint
72
+ - NUNCA: query AR no controller, lógica de negócio
73
+
74
+ ---
75
+
76
+ ## Services (Service Object)
77
+
78
+ ```ruby
79
+ class RegisterUser
80
+ Result = Struct.new(:success?, :user, :error_code, keyword_init: true)
81
+
82
+ def initialize(params)
83
+ @params = params
84
+ end
85
+
86
+ def call
87
+ return Result.new(success?: false, error_code: 'USER_EXISTS') if User.exists?(email: @params[:email])
88
+ user = User.create!(@params)
89
+ Result.new(success?: true, user: user)
90
+ end
91
+ end
92
+ ```
93
+
94
+ Alternativa com gem `interactor`:
95
+
96
+ ```ruby
97
+ class RegisterUser
98
+ include Interactor
99
+
100
+ def call
101
+ context.fail!(error_code: 'USER_EXISTS') if User.exists?(email: context.params[:email])
102
+ context.user = User.create!(context.params)
103
+ end
104
+ end
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Models
110
+
111
+ ```ruby
112
+ class User < ApplicationRecord
113
+ has_secure_password
114
+
115
+ validates :email, presence: true, uniqueness: true, format: URI::MailTo::EMAIL_REGEXP
116
+ validates :name, presence: true
117
+ validates :password, length: { minimum: 12 }, if: :password_required?
118
+
119
+ has_many :sessions, dependent: :destroy
120
+ scope :active, -> { where(deleted_at: nil) }
121
+ end
122
+ ```
123
+
124
+ `has_secure_password` usa BCrypt (default). Para Argon2, troque para gem `argon2` + métodos customizados.
125
+
126
+ ---
127
+
128
+ ## Serializers (Blueprinter)
129
+
130
+ ```ruby
131
+ class UserBlueprint < Blueprinter::Base
132
+ identifier :id
133
+ fields :email, :name
134
+
135
+ field :created_at do |user|
136
+ user.created_at.iso8601
137
+ end
138
+
139
+ view :extended do
140
+ fields :phone, :address
141
+ end
142
+ end
143
+
144
+ # Uso:
145
+ UserBlueprint.render(user)
146
+ UserBlueprint.render(users, view: :extended)
147
+ ```
148
+
149
+ ---
150
+
151
+ ## Auth (devise-jwt)
152
+
153
+ ```ruby
154
+ # Gemfile
155
+ gem 'devise'
156
+ gem 'devise-jwt'
157
+
158
+ # config/initializers/devise.rb
159
+ config.jwt do |jwt|
160
+ jwt.secret = Rails.application.credentials.devise_jwt_secret_key!
161
+ jwt.dispatch_requests = [['POST', %r{^/api/v1/login$}]]
162
+ jwt.revocation_requests = [['DELETE', %r{^/api/v1/logout$}]]
163
+ jwt.expiration_time = 15.minutes.to_i
164
+ end
165
+ ```
166
+
167
+ Refresh token com rotação em tabela própria.
168
+
169
+ ---
170
+
171
+ ## Rate limit (rack-attack)
172
+
173
+ ```ruby
174
+ # config/initializers/rack_attack.rb
175
+ class Rack::Attack
176
+ throttle('login/ip', limit: 5, period: 15.minutes) do |req|
177
+ req.ip if req.path == '/api/v1/login' && req.post?
178
+ end
179
+
180
+ throttle('login/email', limit: 5, period: 15.minutes) do |req|
181
+ if req.path == '/api/v1/login' && req.post?
182
+ req.params['email'].to_s.downcase.gsub(/\s+/, '')
183
+ end
184
+ end
185
+
186
+ throttle('api/ip', limit: 100, period: 1.minute) do |req|
187
+ req.ip if req.path.start_with?('/api/')
188
+ end
189
+ end
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Solid Queue (jobs)
195
+
196
+ ```ruby
197
+ class SendWelcomeEmailJob < ApplicationJob
198
+ queue_as :default
199
+
200
+ def perform(user_id)
201
+ user = User.find(user_id)
202
+ UserMailer.welcome(user).deliver_now
203
+ end
204
+ end
205
+
206
+ # config/queue.yml — Solid Queue default em Rails 8
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Solid Cable + Action Cable
212
+
213
+ ```ruby
214
+ class NotificationsChannel < ApplicationCable::Channel
215
+ def subscribed
216
+ stream_for current_user
217
+ end
218
+ end
219
+
220
+ # Broadcast em qualquer lugar
221
+ NotificationsChannel.broadcast_to(user, type: 'message.sent.v1', payload: {...})
222
+
223
+ # Connection auth
224
+ class ApplicationCable::Connection < ActionCable::Connection::Base
225
+ identified_by :current_user
226
+
227
+ def connect
228
+ self.current_user = find_verified_user
229
+ end
230
+
231
+ private
232
+
233
+ def find_verified_user
234
+ if (user = decode_jwt(request.params[:token]))
235
+ user
236
+ else
237
+ reject_unauthorized_connection
238
+ end
239
+ end
240
+ end
241
+ ```
242
+
243
+ ---
244
+
245
+ ## OpenAPI (rswag)
246
+
247
+ ```ruby
248
+ # Gemfile
249
+ group :development, :test do
250
+ gem 'rswag-specs'
251
+ end
252
+
253
+ # spec/integration/users_spec.rb
254
+ require 'swagger_helper'
255
+
256
+ RSpec.describe 'Users API', type: :request do
257
+ path '/api/v1/users' do
258
+ post 'Creates a user' do
259
+ tags 'Users'
260
+ consumes 'application/json'
261
+ parameter name: :user, in: :body, schema: {
262
+ type: :object,
263
+ properties: {
264
+ email: { type: :string },
265
+ name: { type: :string },
266
+ password: { type: :string, minLength: 12 },
267
+ },
268
+ required: %w[email name password],
269
+ }
270
+ response '201', 'user created' do ... end
271
+ response '409', 'duplicate email' do ... end
272
+ end
273
+ end
274
+ end
275
+
276
+ # rake rswag:specs:swaggerize → swagger/v1/swagger.yaml
277
+ ```
278
+
279
+ Exportar para JSON e expor em `/openapi.json`.
280
+
281
+ ---
282
+
283
+ ## Testes RSpec
284
+
285
+ ```ruby
286
+ # spec/services/register_user_spec.rb
287
+ RSpec.describe RegisterUser do
288
+ let(:params) { { email: 'jane@example.com', name: 'Jane', password: 'longsecret123' } }
289
+
290
+ it 'cria usuário com sucesso' do
291
+ result = described_class.new(params).call
292
+ expect(result.success?).to be true
293
+ expect(result.user.email).to eq 'jane@example.com'
294
+ end
295
+
296
+ it 'falha se email já existe' do
297
+ User.create!(params)
298
+ result = described_class.new(params).call
299
+ expect(result.success?).to be false
300
+ expect(result.error_code).to eq 'USER_EXISTS'
301
+ end
302
+ end
303
+
304
+ # spec/requests/api/v1/users_spec.rb
305
+ RSpec.describe 'POST /api/v1/users', type: :request do
306
+ let(:admin) { create(:user, :admin) }
307
+
308
+ it 'cria com sucesso' do
309
+ post '/api/v1/users',
310
+ params: { user: { email: 'jane@example.com', name: 'Jane', password: 'longsecret123' } },
311
+ headers: { 'Authorization' => "Bearer #{token_for(admin)}" }
312
+ expect(response).to have_http_status(:created)
313
+ end
314
+ end
315
+ ```
316
+
317
+ ---
318
+
319
+ ## Antipatterns
320
+
321
+ | AP | Antipattern | Correção |
322
+ |---|---|---|
323
+ | AP-01 | Query AR no controller | Service object |
324
+ | AP-02 | Lógica no controller | Service object |
325
+ | AP-03 | `render json: user` | Blueprinter/Alba |
326
+ | AP-04 | Fat Model (>500 linhas) | Concerns + Services |
327
+ | AP-05 | Skip strong params | `params.require(...).permit(...)` |
328
+ | AP-06 | Sem rack-attack em login | rate limit obrigatório |
329
+ | AP-07 | JWT secret em código | `Rails.application.credentials` |
330
+ | AP-08 | Logs com PII | `filter_parameters` configurado |
331
+ | AP-09 | N+1 sem `includes` | `bullet` gem em dev |
332
+ | AP-10 | Sem `--api` no rails new | use modo API |
333
+
334
+ ---
335
+
336
+ ## Segurança
337
+
338
+ - `has_secure_password` (BCrypt cost ≥ 12)
339
+ - `force_ssl = true` em produção
340
+ - `secure_headers` gem ou middleware nativo Rails 8
341
+ - `rack-cors` com origens específicas
342
+ - `filter_parameters` para `password`, `token`, `secret`, `ssn`
343
+ - bundler-audit no CI
344
+
345
+ ---
346
+
347
+ ## CI
348
+
349
+ ```bash
350
+ bundle exec rubocop
351
+ bundle exec rspec
352
+ bundle exec bundler-audit check --update
353
+ bundle exec rails db:schema:dump
354
+ ```
355
+
356
+ ---
357
+
358
+ ## Aplicação por fase DARE
359
+
360
+ ### Design
361
+ - Listar endpoints REST com tags + métodos
362
+ - Definir strong params por controller
363
+ - Auth strategy (Devise/JWT)
364
+
365
+ ### Blueprint
366
+ - Estrutura `controllers/api/v1/`, `services/`, `blueprints/`
367
+ - Schema do banco (migrations)
368
+ - Strategy de jobs (Solid Queue) e realtime (Solid Cable)
369
+
370
+ ### Tasks
371
+ - Por feature: Migration, Model, Service, Controller, Blueprint, RSpec
372
+ - Task de configuração rack-attack + filter_parameters
373
+ - Task de OpenAPI com rswag
374
+
375
+ ### Execute
376
+ - Ralph Loop:
377
+ ```bash
378
+ bundle exec rubocop && bundle exec rspec && bundle exec bundler-audit check
379
+ ```
380
+
381
+ ---
382
+
383
+ ## Checklist final
384
+
385
+ - [ ] Ruby 3.3+, Rails 8.x modo API
386
+ - [ ] Rubocop + rails-omakase configurado
387
+ - [ ] Strong parameters em todos os controllers
388
+ - [ ] Lógica em Services (não em controllers)
389
+ - [ ] Blueprinter/Alba (não `render json: object`)
390
+ - [ ] rack-attack para login + APIs públicas
391
+ - [ ] `has_secure_password` (não senha plaintext)
392
+ - [ ] JWT secret via credentials.yml.enc
393
+ - [ ] `filter_parameters` configurado
394
+ - [ ] Solid Queue para jobs (default Rails 8)
395
+ - [ ] OpenAPI exportado via rswag
396
+ - [ ] bundler-audit no CI
397
+
398
+ ---
399
+
400
+ Skill licenciada MIT — parte do DARE Method v3.
@@ -0,0 +1,262 @@
1
+ ---
2
+ description: Comunicação real-time (WebSocket, SSE) DARE-compliant — eventos tipados com JSON Schema, subscriptions autorizadas, reconexão com exponential backoff, e gerenciamento de subscriptions sem ghost listeners.
3
+ globs: **/realtime/**,**/ws/**,**/socket*.ts,**/socket*.py,**/socket*.rs,**/cable/**,**/channels/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Skill: Realtime DARE
8
+
9
+ Você é um especialista em comunicação real-time (WebSocket, SSE). Esta skill garante que toda integração real-time em projeto DARE seja **tipada, autorizada, reconectável e sem ghost listeners**.
10
+
11
+ ## Arquitetura recomendada
12
+
13
+ ```
14
+ ┌─────────────────────────────────────────────────────────┐
15
+ │ Event Registry │
16
+ │ - Tipos de evento com schema JSON │
17
+ │ - Versionamento (.v1, .v2…) │
18
+ │ - Autorização declarada por evento │
19
+ └─────────────────────────────────────────────────────────┘
20
+
21
+ ┌─────────────────────────────────────────────────────────┐
22
+ │ Subscription Manager │
23
+ │ - Map<connection_id, Set<event_type>> │
24
+ │ - Cleanup garantido on disconnect │
25
+ └─────────────────────────────────────────────────────────┘
26
+
27
+ ┌─────────────────────────────────────────────────────────┐
28
+ │ Reconnect Strategy │
29
+ │ - Exponential backoff (1s, 2s, 4s, 8s, max 30s) │
30
+ │ - Jitter para evitar thundering herd │
31
+ │ - Resync de estado após reconectar │
32
+ └─────────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Os 4 pilares
38
+
39
+ ### 1. Schema validation de eventos
40
+
41
+ Todo evento WS/SSE tem schema JSON declarado:
42
+
43
+ ```typescript
44
+ // src/realtime/event_registry.ts
45
+ import { z } from 'zod';
46
+
47
+ export const EventRegistry = {
48
+ 'user.created.v1': {
49
+ schema: z.object({
50
+ id: z.string().uuid(),
51
+ email: z.string().email(),
52
+ createdAt: z.string().datetime(),
53
+ }),
54
+ requires: 'admin',
55
+ },
56
+ 'message.sent.v1': {
57
+ schema: z.object({
58
+ conversationId: z.string().uuid(),
59
+ senderId: z.string().uuid(),
60
+ body: z.string().max(2000),
61
+ sentAt: z.string().datetime(),
62
+ }),
63
+ requires: 'participant',
64
+ },
65
+ } as const;
66
+ ```
67
+
68
+ Server valida antes de emitir, client valida antes de processar. Evento inválido = log + drop.
69
+
70
+ ### 2. Registro central de tipos
71
+
72
+ Um único arquivo `event_registry.ts/py/rs`. Adicionar evento passa por PR explícito. Versionamento via sufixo `.v1`, `.v2`.
73
+
74
+ ### 3. Reconexão com exponential backoff
75
+
76
+ ```typescript
77
+ export class ReconnectStrategy {
78
+ private attempt = 0;
79
+ constructor(private base = 1000, private max = 30_000) {}
80
+
81
+ next(): number {
82
+ const delay = Math.min(this.base * 2 ** this.attempt, this.max);
83
+ const jitter = Math.random() * 1000;
84
+ this.attempt++;
85
+ return delay + jitter;
86
+ }
87
+
88
+ reset() { this.attempt = 0; }
89
+ }
90
+ ```
91
+
92
+ Após reconectar, **resync de estado** — buscar eventos perdidos via REST ou pedir snapshot.
93
+
94
+ ### 4. Subscription manager (zero ghost listeners)
95
+
96
+ ```typescript
97
+ export class SubscriptionManager {
98
+ private subs = new Map<string, Set<string>>();
99
+
100
+ subscribe(connId: string, event: string) {
101
+ if (!this.subs.has(connId)) this.subs.set(connId, new Set());
102
+ this.subs.get(connId)!.add(event);
103
+ }
104
+
105
+ unsubscribe(connId: string, event: string) {
106
+ this.subs.get(connId)?.delete(event);
107
+ }
108
+
109
+ // Cleanup SEMPRE on disconnect — sem exceção
110
+ onDisconnect(connId: string) {
111
+ this.subs.delete(connId);
112
+ }
113
+
114
+ metrics() {
115
+ return { connections: this.subs.size, totalSubs: [...this.subs.values()].reduce((s, set) => s + set.size, 0) };
116
+ }
117
+ }
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Métricas (verificáveis em CI/runtime)
123
+
124
+ | ID | Métrica | Como medir |
125
+ |---|---|---|
126
+ | M-01 | 100% de event types com JSON Schema | grep no registry — todo evento tem `schema:` |
127
+ | M-02 | 100% de subscriptions autorizadas | grep por `authorize(` antes de `subscribe(` |
128
+ | M-03 | 0 ghost listeners após desconexão | métrica runtime `subs.size === 0` após disconnect |
129
+ | M-04 | Reconnect strategy configurada | grep por `ReconnectStrategy` ou backoff manual |
130
+
131
+ ---
132
+
133
+ ## Antipatterns
134
+
135
+ | AP | Antipattern | Sinal | Correção |
136
+ |---|---|---|---|
137
+ | AP-01 | Evento sem schema | `socket.emit('foo', anything)` | Adicionar schema no registry |
138
+ | AP-02 | `socket.on(...)` sem cleanup | listener vive após disconnect | Usar SubscriptionManager |
139
+ | AP-03 | Reconexão sem backoff | reconecta imediatamente em loop | Exponential + jitter |
140
+ | AP-04 | Sem autorização de subscription | usuário ouve eventos cross-tenant | `authorize(user, event)` antes de `subscribe()` |
141
+ | AP-05 | Broadcast sem filtro | `io.emit()` para todos | Rooms/channels por tenant |
142
+ | AP-06 | Estado não recuperado | UI mostra dados stale | Resync via REST ou snapshot WS |
143
+
144
+ ---
145
+
146
+ ## Stack recomendada
147
+
148
+ | Stack | WebSocket | SSE |
149
+ |---|---|---|
150
+ | Node | `socket.io`, `ws` | endpoint custom + `EventSource` no client |
151
+ | Rails | Action Cable + Solid Cable | Rack streaming |
152
+ | Rust/Axum | `tokio-tungstenite`, `axum::extract::ws` | `axum::response::sse::Sse` |
153
+ | FastAPI | `fastapi.WebSocket` | `sse-starlette` (`EventSourceResponse`) |
154
+ | Go | `gorilla/websocket`, `melody` | stdlib `http.Flusher` |
155
+ | NestJS | `@nestjs/websockets` (Socket.io ou ws) | endpoint custom |
156
+
157
+ ---
158
+
159
+ ## Exemplo completo — Socket.io (Node)
160
+
161
+ ```typescript
162
+ // Server
163
+ io.on('connection', (socket) => {
164
+ socket.on('subscribe', ({ eventType }) => {
165
+ const entry = EventRegistry[eventType];
166
+ if (!entry) return socket.emit('error', { code: 'UNKNOWN_EVENT' });
167
+ if (!authorize(socket.data.user, entry.requires)) {
168
+ return socket.emit('error', { code: 'FORBIDDEN' });
169
+ }
170
+ subMgr.subscribe(socket.id, eventType);
171
+ socket.join(`event:${eventType}`);
172
+ });
173
+
174
+ socket.on('disconnect', () => {
175
+ subMgr.onDisconnect(socket.id); // cleanup SEMPRE
176
+ });
177
+ });
178
+
179
+ // Quando emitir um evento (de qualquer lugar)
180
+ export function emit<E extends keyof typeof EventRegistry>(eventType: E, payload: unknown) {
181
+ const entry = EventRegistry[eventType];
182
+ const valid = entry.schema.safeParse(payload);
183
+ if (!valid.success) { log.error('invalid event payload', valid.error); return; }
184
+ io.to(`event:${eventType}`).emit(eventType, valid.data);
185
+ }
186
+ ```
187
+
188
+ ```typescript
189
+ // Client
190
+ const socket = io(url);
191
+ const strategy = new ReconnectStrategy();
192
+
193
+ socket.on('connect', () => {
194
+ strategy.reset();
195
+ resyncState();
196
+ });
197
+
198
+ socket.on('disconnect', () => {
199
+ setTimeout(() => socket.connect(), strategy.next());
200
+ });
201
+
202
+ socket.on('message.sent.v1', (payload) => {
203
+ const valid = EventRegistry['message.sent.v1'].schema.safeParse(payload);
204
+ if (!valid.success) return log.warn('invalid event received', valid.error);
205
+ handleMessage(valid.data);
206
+ });
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Aplicação por fase DARE
212
+
213
+ ### Design
214
+ - Listar eventos WS/SSE necessários (formato `dominio.acao.vN`)
215
+ - Autorização por evento
216
+ - Estratégia de resync após reconect
217
+
218
+ ### Blueprint
219
+ - Diagrama de event flow
220
+ - Stack escolhida (WS lib + cliente)
221
+ - Backoff configurado (base, max, jitter)
222
+
223
+ ### Tasks
224
+ - Task: criar `event_registry.ts`
225
+ - Task: implementar `SubscriptionManager`
226
+ - Task: implementar `ReconnectStrategy`
227
+ - Task: configurar autorização por evento
228
+ - Task: instrumentar métrica de ghost listeners
229
+
230
+ ### Execute
231
+ - Ralph Loop: grep falha se `socket.on` sem cleanup correspondente
232
+ - Métrica runtime: `subMgr.metrics()` em endpoint `/internal/realtime/stats`
233
+
234
+ ---
235
+
236
+ ## Boas práticas
237
+
238
+ 1. **SSE para server→client unidirecional** — logs, métricas, dashboards
239
+ 2. **WebSocket para bidirectional** — chat, colaboração ao vivo
240
+ 3. **Heartbeat ping-pong** — detecta conexão zumbi (TCP OK, peer não responde)
241
+ 4. **Backpressure** — se client lento, drop eventos antigos para evitar OOM
242
+ 5. **Replay limitado** — guardar últimos N eventos por room (não histórico completo)
243
+ 6. **Versionar eventos** — `.v1`, `.v2` permite migração gradual
244
+ 7. **Logs estruturados** — emitir log por evento com tenant, user, eventType, success/fail
245
+
246
+ ---
247
+
248
+ ## Checklist final
249
+
250
+ - [ ] `event_registry.ts/py/rs` com todos os event types
251
+ - [ ] Cada evento tem schema JSON validado
252
+ - [ ] Cada evento declara `requires:` (autorização)
253
+ - [ ] `SubscriptionManager` com cleanup on disconnect
254
+ - [ ] `ReconnectStrategy` no client com exponential backoff + jitter
255
+ - [ ] Resync de estado pós-reconect (REST ou snapshot WS)
256
+ - [ ] Validação de payload no server antes de emitir
257
+ - [ ] Validação de payload no client antes de processar
258
+ - [ ] Métrica de ghost listeners em endpoint `/internal/realtime/stats`
259
+
260
+ ---
261
+
262
+ Skill licenciada MIT — parte do DARE Method v3.