@dewtech/dare-cli 3.10.0 → 3.12.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 (441) hide show
  1. package/README.md +7 -1
  2. package/dist/__tests__/ci-pr-regression.test.d.ts +2 -0
  3. package/dist/__tests__/ci-pr-regression.test.d.ts.map +1 -0
  4. package/dist/__tests__/ci-pr-regression.test.js +76 -0
  5. package/dist/__tests__/ci-pr-regression.test.js.map +1 -0
  6. package/dist/__tests__/dashboard-front.test.d.ts +2 -0
  7. package/dist/__tests__/dashboard-front.test.d.ts.map +1 -0
  8. package/dist/__tests__/dashboard-front.test.js +37 -0
  9. package/dist/__tests__/dashboard-front.test.js.map +1 -0
  10. package/dist/__tests__/dashboard-regression.test.d.ts +2 -0
  11. package/dist/__tests__/dashboard-regression.test.d.ts.map +1 -0
  12. package/dist/__tests__/dashboard-regression.test.js +68 -0
  13. package/dist/__tests__/dashboard-regression.test.js.map +1 -0
  14. package/dist/__tests__/dynamic-dag-regression.test.d.ts +2 -0
  15. package/dist/__tests__/dynamic-dag-regression.test.d.ts.map +1 -0
  16. package/dist/__tests__/dynamic-dag-regression.test.js +464 -0
  17. package/dist/__tests__/dynamic-dag-regression.test.js.map +1 -0
  18. package/dist/__tests__/ensure-skills.test.js +5 -0
  19. package/dist/__tests__/ensure-skills.test.js.map +1 -1
  20. package/dist/__tests__/ide-command-parity.test.js +2 -0
  21. package/dist/__tests__/ide-command-parity.test.js.map +1 -1
  22. package/dist/__tests__/project-generator.test.js +17 -0
  23. package/dist/__tests__/project-generator.test.js.map +1 -1
  24. package/dist/__tests__/reverse-facts.test.js +1 -0
  25. package/dist/__tests__/reverse-facts.test.js.map +1 -1
  26. package/dist/__tests__/terminal-parity-regression.test.d.ts +2 -0
  27. package/dist/__tests__/terminal-parity-regression.test.d.ts.map +1 -0
  28. package/dist/__tests__/terminal-parity-regression.test.js +116 -0
  29. package/dist/__tests__/terminal-parity-regression.test.js.map +1 -0
  30. package/dist/__tests__/terminal-parity.test.d.ts +2 -0
  31. package/dist/__tests__/terminal-parity.test.d.ts.map +1 -0
  32. package/dist/__tests__/terminal-parity.test.js +81 -0
  33. package/dist/__tests__/terminal-parity.test.js.map +1 -0
  34. package/dist/agent/__tests__/antigravity-driver.test.d.ts +2 -0
  35. package/dist/agent/__tests__/antigravity-driver.test.d.ts.map +1 -0
  36. package/dist/agent/__tests__/antigravity-driver.test.js +52 -0
  37. package/dist/agent/__tests__/antigravity-driver.test.js.map +1 -0
  38. package/dist/agent/__tests__/codex-driver.test.d.ts +2 -0
  39. package/dist/agent/__tests__/codex-driver.test.d.ts.map +1 -0
  40. package/dist/agent/__tests__/codex-driver.test.js +68 -0
  41. package/dist/agent/__tests__/codex-driver.test.js.map +1 -0
  42. package/dist/agent/__tests__/cursor-driver.test.d.ts +2 -0
  43. package/dist/agent/__tests__/cursor-driver.test.d.ts.map +1 -0
  44. package/dist/agent/__tests__/cursor-driver.test.js +52 -0
  45. package/dist/agent/__tests__/cursor-driver.test.js.map +1 -0
  46. package/dist/agent/driver.d.ts +1 -1
  47. package/dist/agent/driver.d.ts.map +1 -1
  48. package/dist/agent/drivers/antigravity.d.ts +8 -0
  49. package/dist/agent/drivers/antigravity.d.ts.map +1 -0
  50. package/dist/agent/drivers/antigravity.js +99 -0
  51. package/dist/agent/drivers/antigravity.js.map +1 -0
  52. package/dist/agent/drivers/codex.d.ts +12 -0
  53. package/dist/agent/drivers/codex.d.ts.map +1 -0
  54. package/dist/agent/drivers/codex.js +137 -0
  55. package/dist/agent/drivers/codex.js.map +1 -0
  56. package/dist/agent/drivers/cursor.d.ts +8 -0
  57. package/dist/agent/drivers/cursor.d.ts.map +1 -0
  58. package/dist/agent/drivers/cursor.js +99 -0
  59. package/dist/agent/drivers/cursor.js.map +1 -0
  60. package/dist/ai/__tests__/ai-core.test.d.ts +2 -0
  61. package/dist/ai/__tests__/ai-core.test.d.ts.map +1 -0
  62. package/dist/ai/__tests__/ai-core.test.js +41 -0
  63. package/dist/ai/__tests__/ai-core.test.js.map +1 -0
  64. package/dist/ai/__tests__/parity.test.d.ts +2 -0
  65. package/dist/ai/__tests__/parity.test.d.ts.map +1 -0
  66. package/dist/ai/__tests__/parity.test.js +36 -0
  67. package/dist/ai/__tests__/parity.test.js.map +1 -0
  68. package/dist/ai/__tests__/pipeline.test.d.ts +2 -0
  69. package/dist/ai/__tests__/pipeline.test.d.ts.map +1 -0
  70. package/dist/ai/__tests__/pipeline.test.js +147 -0
  71. package/dist/ai/__tests__/pipeline.test.js.map +1 -0
  72. package/dist/ai/__tests__/refine-bridge.test.d.ts +2 -0
  73. package/dist/ai/__tests__/refine-bridge.test.d.ts.map +1 -0
  74. package/dist/ai/__tests__/refine-bridge.test.js +17 -0
  75. package/dist/ai/__tests__/refine-bridge.test.js.map +1 -0
  76. package/dist/ai/__tests__/resolve.test.d.ts +2 -0
  77. package/dist/ai/__tests__/resolve.test.d.ts.map +1 -0
  78. package/dist/ai/__tests__/resolve.test.js +42 -0
  79. package/dist/ai/__tests__/resolve.test.js.map +1 -0
  80. package/dist/ai/capabilities.d.ts +3 -0
  81. package/dist/ai/capabilities.d.ts.map +1 -0
  82. package/dist/ai/capabilities.js +11 -0
  83. package/dist/ai/capabilities.js.map +1 -0
  84. package/dist/ai/command-options.d.ts +10 -0
  85. package/dist/ai/command-options.d.ts.map +1 -0
  86. package/dist/ai/command-options.js +15 -0
  87. package/dist/ai/command-options.js.map +1 -0
  88. package/dist/ai/config.d.ts +27 -0
  89. package/dist/ai/config.d.ts.map +1 -0
  90. package/dist/ai/config.js +89 -0
  91. package/dist/ai/config.js.map +1 -0
  92. package/dist/ai/parity.d.ts +13 -0
  93. package/dist/ai/parity.d.ts.map +1 -0
  94. package/dist/ai/parity.js +87 -0
  95. package/dist/ai/parity.js.map +1 -0
  96. package/dist/ai/parse-json-output.d.ts +5 -0
  97. package/dist/ai/parse-json-output.d.ts.map +1 -0
  98. package/dist/ai/parse-json-output.js +25 -0
  99. package/dist/ai/parse-json-output.js.map +1 -0
  100. package/dist/ai/pipeline.d.ts +20 -0
  101. package/dist/ai/pipeline.d.ts.map +1 -0
  102. package/dist/ai/pipeline.js +303 -0
  103. package/dist/ai/pipeline.js.map +1 -0
  104. package/dist/ai/prompts.d.ts +6 -0
  105. package/dist/ai/prompts.d.ts.map +1 -0
  106. package/dist/ai/prompts.js +49 -0
  107. package/dist/ai/prompts.js.map +1 -0
  108. package/dist/ai/providers.d.ts +63 -0
  109. package/dist/ai/providers.d.ts.map +1 -0
  110. package/dist/ai/providers.js +297 -0
  111. package/dist/ai/providers.js.map +1 -0
  112. package/dist/ai/refine-bridge.d.ts +5 -0
  113. package/dist/ai/refine-bridge.d.ts.map +1 -0
  114. package/dist/ai/refine-bridge.js +14 -0
  115. package/dist/ai/refine-bridge.js.map +1 -0
  116. package/dist/ai/registry.d.ts +12 -0
  117. package/dist/ai/registry.d.ts.map +1 -0
  118. package/dist/ai/registry.js +43 -0
  119. package/dist/ai/registry.js.map +1 -0
  120. package/dist/ai/resolve.d.ts +28 -0
  121. package/dist/ai/resolve.d.ts.map +1 -0
  122. package/dist/ai/resolve.js +83 -0
  123. package/dist/ai/resolve.js.map +1 -0
  124. package/dist/ai/schemas.d.ts +175 -0
  125. package/dist/ai/schemas.d.ts.map +1 -0
  126. package/dist/ai/schemas.js +199 -0
  127. package/dist/ai/schemas.js.map +1 -0
  128. package/dist/ai/types.d.ts +52 -0
  129. package/dist/ai/types.d.ts.map +1 -0
  130. package/dist/ai/types.js +8 -0
  131. package/dist/ai/types.js.map +1 -0
  132. package/dist/bin/dare.js +4 -0
  133. package/dist/bin/dare.js.map +1 -1
  134. package/dist/commands/__tests__/ai-command.test.d.ts +2 -0
  135. package/dist/commands/__tests__/ai-command.test.d.ts.map +1 -0
  136. package/dist/commands/__tests__/ai-command.test.js +68 -0
  137. package/dist/commands/__tests__/ai-command.test.js.map +1 -0
  138. package/dist/commands/__tests__/dashboard-command.test.d.ts +2 -0
  139. package/dist/commands/__tests__/dashboard-command.test.d.ts.map +1 -0
  140. package/dist/commands/__tests__/dashboard-command.test.js +62 -0
  141. package/dist/commands/__tests__/dashboard-command.test.js.map +1 -0
  142. package/dist/commands/__tests__/execute-agent.test.js +82 -0
  143. package/dist/commands/__tests__/execute-agent.test.js.map +1 -1
  144. package/dist/commands/__tests__/gate-flags.test.d.ts +2 -0
  145. package/dist/commands/__tests__/gate-flags.test.d.ts.map +1 -0
  146. package/dist/commands/__tests__/gate-flags.test.js +58 -0
  147. package/dist/commands/__tests__/gate-flags.test.js.map +1 -0
  148. package/dist/commands/__tests__/persist-viz.test.d.ts +2 -0
  149. package/dist/commands/__tests__/persist-viz.test.d.ts.map +1 -0
  150. package/dist/commands/__tests__/persist-viz.test.js +178 -0
  151. package/dist/commands/__tests__/persist-viz.test.js.map +1 -0
  152. package/dist/commands/__tests__/refine-apply.test.d.ts +2 -0
  153. package/dist/commands/__tests__/refine-apply.test.d.ts.map +1 -0
  154. package/dist/commands/__tests__/refine-apply.test.js +118 -0
  155. package/dist/commands/__tests__/refine-apply.test.js.map +1 -0
  156. package/dist/commands/__tests__/replan-splice.test.d.ts +2 -0
  157. package/dist/commands/__tests__/replan-splice.test.d.ts.map +1 -0
  158. package/dist/commands/__tests__/replan-splice.test.js +295 -0
  159. package/dist/commands/__tests__/replan-splice.test.js.map +1 -0
  160. package/dist/commands/ai.d.ts +3 -0
  161. package/dist/commands/ai.d.ts.map +1 -0
  162. package/dist/commands/ai.js +141 -0
  163. package/dist/commands/ai.js.map +1 -0
  164. package/dist/commands/blueprint.d.ts.map +1 -1
  165. package/dist/commands/blueprint.js +17 -3
  166. package/dist/commands/blueprint.js.map +1 -1
  167. package/dist/commands/dag.d.ts.map +1 -1
  168. package/dist/commands/dag.js +2 -0
  169. package/dist/commands/dag.js.map +1 -1
  170. package/dist/commands/dashboard.d.ts +17 -0
  171. package/dist/commands/dashboard.d.ts.map +1 -0
  172. package/dist/commands/dashboard.js +77 -0
  173. package/dist/commands/dashboard.js.map +1 -0
  174. package/dist/commands/design.d.ts.map +1 -1
  175. package/dist/commands/design.js +21 -2
  176. package/dist/commands/design.js.map +1 -1
  177. package/dist/commands/discover.d.ts.map +1 -1
  178. package/dist/commands/discover.js +9 -1
  179. package/dist/commands/discover.js.map +1 -1
  180. package/dist/commands/dna.d.ts.map +1 -1
  181. package/dist/commands/dna.js +23 -3
  182. package/dist/commands/dna.js.map +1 -1
  183. package/dist/commands/execute.d.ts +11 -0
  184. package/dist/commands/execute.d.ts.map +1 -1
  185. package/dist/commands/execute.js +219 -6
  186. package/dist/commands/execute.js.map +1 -1
  187. package/dist/commands/graph.d.ts.map +1 -1
  188. package/dist/commands/graph.js +33 -5
  189. package/dist/commands/graph.js.map +1 -1
  190. package/dist/commands/guard.d.ts.map +1 -1
  191. package/dist/commands/guard.js +27 -3
  192. package/dist/commands/guard.js.map +1 -1
  193. package/dist/commands/init.d.ts.map +1 -1
  194. package/dist/commands/init.js +1 -0
  195. package/dist/commands/init.js.map +1 -1
  196. package/dist/commands/migrate.d.ts.map +1 -1
  197. package/dist/commands/migrate.js +14 -2
  198. package/dist/commands/migrate.js.map +1 -1
  199. package/dist/commands/patterns.d.ts.map +1 -1
  200. package/dist/commands/patterns.js +14 -2
  201. package/dist/commands/patterns.js.map +1 -1
  202. package/dist/commands/refine.d.ts +2 -0
  203. package/dist/commands/refine.d.ts.map +1 -1
  204. package/dist/commands/refine.js +94 -22
  205. package/dist/commands/refine.js.map +1 -1
  206. package/dist/commands/reverse.d.ts.map +1 -1
  207. package/dist/commands/reverse.js +28 -3
  208. package/dist/commands/reverse.js.map +1 -1
  209. package/dist/commands/review.d.ts.map +1 -1
  210. package/dist/commands/review.js +60 -7
  211. package/dist/commands/review.js.map +1 -1
  212. package/dist/core/types/project.d.ts +1 -1
  213. package/dist/core/types/project.d.ts.map +1 -1
  214. package/dist/dag-runner/__tests__/maxdepth-config.test.d.ts +2 -0
  215. package/dist/dag-runner/__tests__/maxdepth-config.test.d.ts.map +1 -0
  216. package/dist/dag-runner/__tests__/maxdepth-config.test.js +28 -0
  217. package/dist/dag-runner/__tests__/maxdepth-config.test.js.map +1 -0
  218. package/dist/dag-runner/__tests__/sub-dag.test.d.ts +2 -0
  219. package/dist/dag-runner/__tests__/sub-dag.test.d.ts.map +1 -0
  220. package/dist/dag-runner/__tests__/sub-dag.test.js +127 -0
  221. package/dist/dag-runner/__tests__/sub-dag.test.js.map +1 -0
  222. package/dist/dag-runner/run_dag.d.ts +3 -1
  223. package/dist/dag-runner/run_dag.d.ts.map +1 -1
  224. package/dist/dag-runner/run_dag.js.map +1 -1
  225. package/dist/dag-runner/state-store.d.ts +2 -0
  226. package/dist/dag-runner/state-store.d.ts.map +1 -1
  227. package/dist/dag-runner/state-store.js +44 -8
  228. package/dist/dag-runner/state-store.js.map +1 -1
  229. package/dist/dag-runner/sub-dag.d.ts +23 -0
  230. package/dist/dag-runner/sub-dag.d.ts.map +1 -0
  231. package/dist/dag-runner/sub-dag.js +117 -0
  232. package/dist/dag-runner/sub-dag.js.map +1 -0
  233. package/dist/dashboard/__tests__/dashboard-routes.test.d.ts +2 -0
  234. package/dist/dashboard/__tests__/dashboard-routes.test.d.ts.map +1 -0
  235. package/dist/dashboard/__tests__/dashboard-routes.test.js +102 -0
  236. package/dist/dashboard/__tests__/dashboard-routes.test.js.map +1 -0
  237. package/dist/dashboard/routes.d.ts +8 -0
  238. package/dist/dashboard/routes.d.ts.map +1 -0
  239. package/dist/dashboard/routes.js +70 -0
  240. package/dist/dashboard/routes.js.map +1 -0
  241. package/dist/exec/safe-spawn.d.ts.map +1 -1
  242. package/dist/exec/safe-spawn.js +6 -1
  243. package/dist/exec/safe-spawn.js.map +1 -1
  244. package/dist/graphrag/__tests__/hybrid-integration.test.js +1 -1
  245. package/dist/graphrag/__tests__/hybrid-integration.test.js.map +1 -1
  246. package/dist/graphrag/__tests__/no-heavy-dep-in-core.test.js +2 -2
  247. package/dist/graphrag/__tests__/no-heavy-dep-in-core.test.js.map +1 -1
  248. package/dist/graphrag/embeddings.js +1 -1
  249. package/dist/graphrag/embeddings.js.map +1 -1
  250. package/dist/http/__tests__/shared-app.test.d.ts +2 -0
  251. package/dist/http/__tests__/shared-app.test.d.ts.map +1 -0
  252. package/dist/http/__tests__/shared-app.test.js +57 -0
  253. package/dist/http/__tests__/shared-app.test.js.map +1 -0
  254. package/dist/http/app.d.ts +15 -0
  255. package/dist/http/app.d.ts.map +1 -0
  256. package/dist/http/app.js +32 -0
  257. package/dist/http/app.js.map +1 -0
  258. package/dist/mcp-server/server.d.ts.map +1 -1
  259. package/dist/mcp-server/server.js +5 -15
  260. package/dist/mcp-server/server.js.map +1 -1
  261. package/dist/reporters/__tests__/github-reporter.test.d.ts +2 -0
  262. package/dist/reporters/__tests__/github-reporter.test.d.ts.map +1 -0
  263. package/dist/reporters/__tests__/github-reporter.test.js +93 -0
  264. package/dist/reporters/__tests__/github-reporter.test.js.map +1 -0
  265. package/dist/reporters/ci-gate.d.ts +27 -0
  266. package/dist/reporters/ci-gate.d.ts.map +1 -0
  267. package/dist/reporters/ci-gate.js +100 -0
  268. package/dist/reporters/ci-gate.js.map +1 -0
  269. package/dist/reporters/github.d.ts +36 -0
  270. package/dist/reporters/github.d.ts.map +1 -0
  271. package/dist/reporters/github.js +142 -0
  272. package/dist/reporters/github.js.map +1 -0
  273. package/dist/skills/bundled.d.ts +5 -0
  274. package/dist/skills/bundled.d.ts.map +1 -0
  275. package/dist/skills/bundled.js +34 -0
  276. package/dist/skills/bundled.js.map +1 -0
  277. package/dist/skills/commands/add.d.ts +1 -3
  278. package/dist/skills/commands/add.d.ts.map +1 -1
  279. package/dist/skills/commands/add.js +20 -3
  280. package/dist/skills/commands/add.js.map +1 -1
  281. package/dist/skills/tests/bundled.spec.d.ts +2 -0
  282. package/dist/skills/tests/bundled.spec.d.ts.map +1 -0
  283. package/dist/skills/tests/bundled.spec.js +24 -0
  284. package/dist/skills/tests/bundled.spec.js.map +1 -0
  285. package/dist/telemetry/__tests__/aggregator.test.d.ts +2 -0
  286. package/dist/telemetry/__tests__/aggregator.test.d.ts.map +1 -0
  287. package/dist/telemetry/__tests__/aggregator.test.js +164 -0
  288. package/dist/telemetry/__tests__/aggregator.test.js.map +1 -0
  289. package/dist/telemetry/aggregator.d.ts +43 -0
  290. package/dist/telemetry/aggregator.d.ts.map +1 -0
  291. package/dist/telemetry/aggregator.js +282 -0
  292. package/dist/telemetry/aggregator.js.map +1 -0
  293. package/dist/types/UpdateManifest.types.d.ts +1 -1
  294. package/dist/types/UpdateManifest.types.d.ts.map +1 -1
  295. package/dist/utils/dag-converter.js +1 -1
  296. package/dist/utils/dag-converter.js.map +1 -1
  297. package/dist/utils/excalidraw-renderer.d.ts.map +1 -1
  298. package/dist/utils/excalidraw-renderer.js +1 -0
  299. package/dist/utils/excalidraw-renderer.js.map +1 -1
  300. package/dist/utils/graph-renderer.d.ts +2 -0
  301. package/dist/utils/graph-renderer.d.ts.map +1 -1
  302. package/dist/utils/graph-renderer.js +188 -14
  303. package/dist/utils/graph-renderer.js.map +1 -1
  304. package/dist/utils/project-detector.d.ts +1 -0
  305. package/dist/utils/project-detector.d.ts.map +1 -1
  306. package/dist/utils/project-detector.js +8 -0
  307. package/dist/utils/project-detector.js.map +1 -1
  308. package/dist/utils/project-generator.d.ts +1 -1
  309. package/dist/utils/project-generator.d.ts.map +1 -1
  310. package/dist/utils/project-generator.js +23 -2
  311. package/dist/utils/project-generator.js.map +1 -1
  312. package/dist/utils/templates.d.ts +2 -0
  313. package/dist/utils/templates.d.ts.map +1 -1
  314. package/dist/utils/templates.js +74 -0
  315. package/dist/utils/templates.js.map +1 -1
  316. package/dist/verification/__tests__/decay-policy.test.js +1 -0
  317. package/dist/verification/__tests__/decay-policy.test.js.map +1 -1
  318. package/dist/verification/__tests__/safe-spawn.test.js +12 -0
  319. package/dist/verification/__tests__/safe-spawn.test.js.map +1 -1
  320. package/dist/verification/config.d.ts.map +1 -1
  321. package/dist/verification/config.js +2 -0
  322. package/dist/verification/config.js.map +1 -1
  323. package/dist/verification/types.d.ts +2 -0
  324. package/dist/verification/types.d.ts.map +1 -1
  325. package/package.json +3 -2
  326. package/skills/dare-ax/generator.ts +325 -0
  327. package/skills/dare-ax/index.ts +19 -0
  328. package/skills/dare-ax/metrics.ts +352 -0
  329. package/skills/dare-ax/package-lock.json +1855 -0
  330. package/skills/dare-ax/package.json +50 -0
  331. package/skills/dare-ax/secret-detector.ts +123 -0
  332. package/skills/dare-ax/skill.yml +19 -0
  333. package/skills/dare-ax/templates/llms.txt.jinja2 +80 -0
  334. package/skills/dare-ax/tests/generator.spec.ts +193 -0
  335. package/skills/dare-ax/tests/metrics.spec.ts +394 -0
  336. package/skills/dare-ax/tests/validator.spec.ts +298 -0
  337. package/skills/dare-ax/tsconfig.json +18 -0
  338. package/skills/dare-ax/types.ts +79 -0
  339. package/skills/dare-ax/validator.ts +238 -0
  340. package/skills/dare-frontend-design/generator.ts +616 -0
  341. package/skills/dare-frontend-design/index.ts +25 -0
  342. package/skills/dare-frontend-design/linter.ts +227 -0
  343. package/skills/dare-frontend-design/metrics.ts +82 -0
  344. package/skills/dare-frontend-design/package-lock.json +1855 -0
  345. package/skills/dare-frontend-design/package.json +43 -0
  346. package/skills/dare-frontend-design/skill.yml +20 -0
  347. package/skills/dare-frontend-design/tests/frontend_design.spec.ts +435 -0
  348. package/skills/dare-frontend-design/tsconfig.json +18 -0
  349. package/skills/dare-frontend-design/types.ts +62 -0
  350. package/skills/dare-layered-design/generator.ts +740 -0
  351. package/skills/dare-layered-design/index.ts +17 -0
  352. package/skills/dare-layered-design/linter.ts +462 -0
  353. package/skills/dare-layered-design/metrics.ts +409 -0
  354. package/skills/dare-layered-design/package-lock.json +1855 -0
  355. package/skills/dare-layered-design/package.json +50 -0
  356. package/skills/dare-layered-design/skill.yml +35 -0
  357. package/skills/dare-layered-design/tests/generator.spec.ts +156 -0
  358. package/skills/dare-layered-design/tests/linter.spec.ts +255 -0
  359. package/skills/dare-layered-design/tests/metrics.spec.ts +286 -0
  360. package/skills/dare-layered-design/tsconfig.json +18 -0
  361. package/skills/dare-layered-design/types.ts +48 -0
  362. package/skills/dare-llm-integration/cache/llm_cache.ts +122 -0
  363. package/skills/dare-llm-integration/index.ts +49 -0
  364. package/skills/dare-llm-integration/metrics.ts +107 -0
  365. package/skills/dare-llm-integration/package-lock.json +1855 -0
  366. package/skills/dare-llm-integration/package.json +49 -0
  367. package/skills/dare-llm-integration/prompts/prompt_loader.ts +258 -0
  368. package/skills/dare-llm-integration/providers/anthropic_provider.ts +159 -0
  369. package/skills/dare-llm-integration/providers/dummy_provider.ts +113 -0
  370. package/skills/dare-llm-integration/providers/llm_provider.ts +6 -0
  371. package/skills/dare-llm-integration/providers/openai_provider.ts +215 -0
  372. package/skills/dare-llm-integration/rate_limit/token_bucket.ts +86 -0
  373. package/skills/dare-llm-integration/skill.yml +23 -0
  374. package/skills/dare-llm-integration/tests/fixtures/greet_v1.jinja2 +1 -0
  375. package/skills/dare-llm-integration/tests/fixtures/summarize_v1.jinja2 +1 -0
  376. package/skills/dare-llm-integration/tests/fixtures/summarize_v2.jinja2 +3 -0
  377. package/skills/dare-llm-integration/tests/llm_integration.spec.ts +657 -0
  378. package/skills/dare-llm-integration/tsconfig.json +23 -0
  379. package/skills/dare-llm-integration/types.ts +91 -0
  380. package/skills/dare-llm-integration/validators/output_validator.ts +200 -0
  381. package/skills/dare-quality-telemetry/collect.ts +134 -0
  382. package/skills/dare-quality-telemetry/collectors/dare_ax_collector.ts +301 -0
  383. package/skills/dare-quality-telemetry/collectors/dare_layered_design_collector.ts +406 -0
  384. package/skills/dare-quality-telemetry/collectors/index.ts +24 -0
  385. package/skills/dare-quality-telemetry/github_actions_template.ts +25 -0
  386. package/skills/dare-quality-telemetry/index.ts +18 -0
  387. package/skills/dare-quality-telemetry/metrics.ts +137 -0
  388. package/skills/dare-quality-telemetry/package-lock.json +1855 -0
  389. package/skills/dare-quality-telemetry/package.json +48 -0
  390. package/skills/dare-quality-telemetry/regression.ts +60 -0
  391. package/skills/dare-quality-telemetry/reporter.ts +132 -0
  392. package/skills/dare-quality-telemetry/skill.yml +18 -0
  393. package/skills/dare-quality-telemetry/tests/quality_telemetry.spec.ts +885 -0
  394. package/skills/dare-quality-telemetry/tsconfig.json +19 -0
  395. package/skills/dare-quality-telemetry/types.ts +41 -0
  396. package/skills/dare-realtime/event_registry.ts +101 -0
  397. package/skills/dare-realtime/index.ts +30 -0
  398. package/skills/dare-realtime/metrics.ts +84 -0
  399. package/skills/dare-realtime/package-lock.json +1855 -0
  400. package/skills/dare-realtime/package.json +43 -0
  401. package/skills/dare-realtime/reconnect_strategy.ts +85 -0
  402. package/skills/dare-realtime/schema_validator.ts +80 -0
  403. package/skills/dare-realtime/skill.yml +21 -0
  404. package/skills/dare-realtime/subscription_manager.ts +106 -0
  405. package/skills/dare-realtime/tests/realtime.spec.ts +482 -0
  406. package/skills/dare-realtime/tsconfig.json +18 -0
  407. package/skills/dare-realtime/types.ts +51 -0
  408. package/templates/.github/workflows/dare-pr.yml +26 -0
  409. package/templates/dashboard/app.js +184 -0
  410. package/templates/dashboard/index.html +63 -0
  411. package/templates/dashboard/style.css +134 -0
  412. package/templates/ide/antigravity/.agents/skills/dare-ai/SKILL.md +17 -0
  413. package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +2 -0
  414. package/templates/ide/antigravity/.agents/skills/dare-dashboard/SKILL.md +18 -0
  415. package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +2 -0
  416. package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +3 -0
  417. package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +3 -0
  418. package/templates/ide/antigravity/.agents/skills/dare-patterns/SKILL.md +3 -0
  419. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +3 -0
  420. package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +3 -0
  421. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +3 -0
  422. package/templates/ide/claude/.claude/commands/dare-ai.md +17 -0
  423. package/templates/ide/claude/.claude/commands/dare-blueprint.md +2 -0
  424. package/templates/ide/claude/.claude/commands/dare-dashboard.md +18 -0
  425. package/templates/ide/claude/.claude/commands/dare-design.md +2 -0
  426. package/templates/ide/claude/.claude/commands/dare-dna.md +2 -0
  427. package/templates/ide/claude/.claude/commands/dare-migrate.md +2 -0
  428. package/templates/ide/claude/.claude/commands/dare-patterns.md +3 -0
  429. package/templates/ide/claude/.claude/commands/dare-refine.md +3 -0
  430. package/templates/ide/claude/.claude/commands/dare-reverse.md +2 -0
  431. package/templates/ide/claude/.claude/commands/dare-review.md +3 -0
  432. package/templates/ide/cursor/.cursor/commands/dare-ai.md +17 -0
  433. package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +3 -0
  434. package/templates/ide/cursor/.cursor/commands/dare-dashboard.md +18 -0
  435. package/templates/ide/cursor/.cursor/commands/dare-design.md +3 -0
  436. package/templates/ide/cursor/.cursor/commands/dare-dna.md +2 -0
  437. package/templates/ide/cursor/.cursor/commands/dare-migrate.md +2 -0
  438. package/templates/ide/cursor/.cursor/commands/dare-patterns.md +3 -0
  439. package/templates/ide/cursor/.cursor/commands/dare-refine.md +3 -0
  440. package/templates/ide/cursor/.cursor/commands/dare-reverse.md +2 -0
  441. package/templates/ide/cursor/.cursor/commands/dare-review.md +3 -0
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@dewtech/dare-frontend-design",
3
+ "version": "1.0.0",
4
+ "description": "dare-frontend-design — Frontend architecture patterns skill for DARE Method v3.0",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "skill.yml"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "typecheck": "tsc --noEmit"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^20.19.41",
26
+ "typescript": "^5.9.3",
27
+ "vitest": "^1.6.1"
28
+ },
29
+ "keywords": [
30
+ "dare",
31
+ "dare-method",
32
+ "dare-frontend-design",
33
+ "react",
34
+ "vue",
35
+ "linter",
36
+ "scaffold"
37
+ ],
38
+ "author": "Dewtech Technologies",
39
+ "license": "MIT",
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ }
43
+ }
@@ -0,0 +1,20 @@
1
+ name: dare-frontend-design
2
+ version: 1.0.0
3
+ license: MIT
4
+ description: >
5
+ Skill transversal DARE para arquitetura frontend. Detecta componentes grandes
6
+ (> 300 linhas), chamadas fetch inline em JSX/template, e gera scaffold DARE-compliant
7
+ para projetos React e Vue com error boundaries e loading states.
8
+ author: Dewtech Technologies
9
+ frameworks:
10
+ - react
11
+ - vue
12
+ metrics:
13
+ - id: M-01
14
+ description: 100% de componentes < 300 linhas
15
+ - id: M-02
16
+ description: 0 fetch() direto em JSX/template
17
+ - id: M-03
18
+ description: 100% de páginas com error boundary
19
+ - id: M-04
20
+ description: Bundle config presente para monitorar tamanho
@@ -0,0 +1,435 @@
1
+ /**
2
+ * dare-frontend-design — test suite
3
+ * 35+ tests covering linter, generator, and metrics.
4
+ * License: MIT
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import os from 'os';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ import { FrontendLinter } from '../linter.js';
14
+ import { FrontendGenerator } from '../generator.js';
15
+ import { collectFrontendMetrics } from '../metrics.js';
16
+
17
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Helpers
21
+ // ---------------------------------------------------------------------------
22
+
23
+ function createTempDir(): string {
24
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'dare-fe-'));
25
+ }
26
+
27
+ function removeTempDir(dir: string): void {
28
+ fs.rmSync(dir, { recursive: true, force: true });
29
+ }
30
+
31
+ function writeFile(dir: string, relPath: string, content: string): string {
32
+ const fullPath = path.join(dir, relPath);
33
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
34
+ fs.writeFileSync(fullPath, content, 'utf-8');
35
+ return fullPath;
36
+ }
37
+
38
+ function makeLargeComponent(lineCount: number): string {
39
+ const lines = ['import React from "react";', '', 'export function BigComponent() {', ' return (', ' <div>'];
40
+ for (let i = 0; i < lineCount - 8; i++) {
41
+ lines.push(` <p>Line ${i}</p>`);
42
+ }
43
+ lines.push(' </div>', ' );', '}');
44
+ return lines.join('\n');
45
+ }
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // FrontendLinter — component-too-large
49
+ // ---------------------------------------------------------------------------
50
+
51
+ describe('FrontendLinter — component-too-large', () => {
52
+ let tmpDir: string;
53
+ let linter: FrontendLinter;
54
+
55
+ beforeEach(() => {
56
+ tmpDir = createTempDir();
57
+ linter = new FrontendLinter();
58
+ });
59
+
60
+ afterEach(() => removeTempDir(tmpDir));
61
+
62
+ it('passes for a small component (< 300 lines)', () => {
63
+ const content = 'import React from "react";\nexport function Small() { return <div/>; }';
64
+ const file = writeFile(tmpDir, 'Small.tsx', content);
65
+ const violations = linter.lintFile(file);
66
+ expect(violations.filter((v) => v.rule === 'component-too-large')).toHaveLength(0);
67
+ });
68
+
69
+ it('flags component with exactly 301 lines', () => {
70
+ const file = writeFile(tmpDir, 'Big.tsx', makeLargeComponent(301));
71
+ const violations = linter.lintFile(file);
72
+ const large = violations.filter((v) => v.rule === 'component-too-large');
73
+ expect(large).toHaveLength(1);
74
+ expect(large[0].severity).toBe('error');
75
+ expect(large[0].message).toContain('301 lines');
76
+ });
77
+
78
+ it('does not flag non-component files (.ts)', () => {
79
+ const file = writeFile(tmpDir, 'utils.ts', makeLargeComponent(500));
80
+ const violations = linter.lintFile(file);
81
+ expect(violations).toHaveLength(0);
82
+ });
83
+
84
+ it('lintDirectory finds violations in nested .tsx files', () => {
85
+ writeFile(tmpDir, 'src/Big.tsx', makeLargeComponent(400));
86
+ writeFile(tmpDir, 'src/Small.tsx', 'export function S() { return null; }');
87
+ const result = linter.lintDirectory(tmpDir);
88
+ expect(result.filesChecked).toBe(2);
89
+ expect(result.violations.some((v) => v.rule === 'component-too-large')).toBe(true);
90
+ expect(result.pass).toBe(false);
91
+ });
92
+
93
+ it('lintDirectory passes when all components are small', () => {
94
+ writeFile(tmpDir, 'A.tsx', 'export function A() { return null; }');
95
+ writeFile(tmpDir, 'B.tsx', 'export function B() { return null; }');
96
+ const result = linter.lintDirectory(tmpDir);
97
+ expect(result.pass).toBe(true);
98
+ });
99
+
100
+ it('lintFiles returns 0 violations for non-component files', () => {
101
+ const file = writeFile(tmpDir, 'utils.ts', makeLargeComponent(500));
102
+ const result = linter.lintFiles([file]);
103
+ expect(result.filesChecked).toBe(0);
104
+ expect(result.violations).toHaveLength(0);
105
+ });
106
+
107
+ it('returns empty for non-existent file', () => {
108
+ const violations = linter.lintFile('/tmp/nonexistent.tsx');
109
+ expect(violations).toHaveLength(0);
110
+ });
111
+ });
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // FrontendLinter — fetch-in-jsx
115
+ // ---------------------------------------------------------------------------
116
+
117
+ describe('FrontendLinter — fetch-in-jsx', () => {
118
+ let tmpDir: string;
119
+ let linter: FrontendLinter;
120
+
121
+ beforeEach(() => {
122
+ tmpDir = createTempDir();
123
+ linter = new FrontendLinter();
124
+ });
125
+
126
+ afterEach(() => removeTempDir(tmpDir));
127
+
128
+ it('flags fetch() in a non-hook .tsx file with JSX context', () => {
129
+ const content = `import React from 'react';
130
+
131
+ export function UserCard() {
132
+ const data = fetch('/api/users').then(r => r.json());
133
+ return <div>{JSON.stringify(data)}</div>;
134
+ }`;
135
+ const file = writeFile(tmpDir, 'UserCard.tsx', content);
136
+ const violations = linter.lintFile(file);
137
+ const fetchViolations = violations.filter((v) => v.rule === 'fetch-in-jsx');
138
+ expect(fetchViolations.length).toBeGreaterThan(0);
139
+ });
140
+
141
+ it('does NOT flag fetch() in a useXxx hook file', () => {
142
+ const content = `export function useUserData(id: string) {
143
+ const data = fetch(\`/api/users/\${id}\`).then(r => r.json());
144
+ return data;
145
+ }`;
146
+ const file = writeFile(tmpDir, 'useUserData.ts', content);
147
+ const violations = linter.lintFile(file);
148
+ const fetchViolations = violations.filter((v) => v.rule === 'fetch-in-jsx');
149
+ expect(fetchViolations).toHaveLength(0);
150
+ });
151
+
152
+ it('does NOT flag axios in a useXxx composable .ts file', () => {
153
+ const content = `export function useApi() {
154
+ return axios.get('/api').then(r => r.data);
155
+ }`;
156
+ const file = writeFile(tmpDir, 'useApi.ts', content);
157
+ const violations = linter.lintFile(file);
158
+ expect(violations.filter((v) => v.rule === 'fetch-in-jsx')).toHaveLength(0);
159
+ });
160
+
161
+ it('flags fetch in Vue <template> section', () => {
162
+ const content = `<template>
163
+ <div>{{ fetch('/api') }}</div>
164
+ </template>
165
+
166
+ <script setup lang="ts">
167
+ </script>`;
168
+ const file = writeFile(tmpDir, 'Bad.vue', content);
169
+ const violations = linter.lintFile(file);
170
+ // template fetch is flagged
171
+ expect(violations.some((v) => v.rule === 'fetch-in-jsx')).toBe(true);
172
+ });
173
+ });
174
+
175
+ // ---------------------------------------------------------------------------
176
+ // FrontendGenerator — React
177
+ // ---------------------------------------------------------------------------
178
+
179
+ describe('FrontendGenerator — React', () => {
180
+ let tmpDir: string;
181
+ let generator: FrontendGenerator;
182
+
183
+ beforeEach(() => {
184
+ tmpDir = createTempDir();
185
+ generator = new FrontendGenerator();
186
+ });
187
+
188
+ afterEach(() => removeTempDir(tmpDir));
189
+
190
+ it('creates React scaffold with all expected directories', () => {
191
+ const result = generator.scaffold({ framework: 'react', outputDir: tmpDir });
192
+ const expectedDirs = ['components', 'hooks', 'pages', 'store', 'api'];
193
+ for (const dir of expectedDirs) {
194
+ expect(result.dirsCreated.some((d) => d.includes(dir))).toBe(true);
195
+ }
196
+ });
197
+
198
+ it('creates ErrorBoundary.tsx', () => {
199
+ const result = generator.scaffold({ framework: 'react', outputDir: tmpDir });
200
+ expect(result.filesCreated.some((f) => f.includes('ErrorBoundary.tsx'))).toBe(true);
201
+ const content = fs.readFileSync(path.join(tmpDir, 'src/components/ErrorBoundary.tsx'), 'utf-8');
202
+ expect(content).toContain('ErrorBoundary');
203
+ expect(content).toContain('hasError');
204
+ });
205
+
206
+ it('creates useFetch.ts hook', () => {
207
+ generator.scaffold({ framework: 'react', outputDir: tmpDir });
208
+ const content = fs.readFileSync(path.join(tmpDir, 'src/hooks/useFetch.ts'), 'utf-8');
209
+ expect(content).toContain('useFetch');
210
+ expect(content).toContain("status: 'loading'");
211
+ });
212
+
213
+ it('creates NotFoundPage.tsx with ErrorBoundary import', () => {
214
+ generator.scaffold({ framework: 'react', outputDir: tmpDir });
215
+ const content = fs.readFileSync(path.join(tmpDir, 'src/pages/NotFoundPage.tsx'), 'utf-8');
216
+ expect(content).toContain('ErrorBoundary');
217
+ expect(content).toContain('404');
218
+ });
219
+
220
+ it('creates API client with auth headers', () => {
221
+ generator.scaffold({ framework: 'react', outputDir: tmpDir });
222
+ const content = fs.readFileSync(path.join(tmpDir, 'src/api/client.ts'), 'utf-8');
223
+ expect(content).toContain('apiGet');
224
+ expect(content).toContain('Authorization');
225
+ });
226
+
227
+ it('creates App.tsx with ErrorBoundary', () => {
228
+ generator.scaffold({ framework: 'react', outputDir: tmpDir, projectName: 'MyApp' });
229
+ const content = fs.readFileSync(path.join(tmpDir, 'src/App.tsx'), 'utf-8');
230
+ expect(content).toContain('ErrorBoundary');
231
+ expect(content).toContain('MyApp');
232
+ });
233
+
234
+ it('returns framework in result', () => {
235
+ const result = generator.scaffold({ framework: 'react', outputDir: tmpDir });
236
+ expect(result.framework).toBe('react');
237
+ });
238
+
239
+ it('creates LoadingSpinner.tsx', () => {
240
+ generator.scaffold({ framework: 'react', outputDir: tmpDir });
241
+ const content = fs.readFileSync(path.join(tmpDir, 'src/components/LoadingSpinner.tsx'), 'utf-8');
242
+ expect(content).toContain('LoadingSpinner');
243
+ expect(content).toContain('aria-label');
244
+ });
245
+ });
246
+
247
+ // ---------------------------------------------------------------------------
248
+ // FrontendGenerator — Vue
249
+ // ---------------------------------------------------------------------------
250
+
251
+ describe('FrontendGenerator — Vue', () => {
252
+ let tmpDir: string;
253
+ let generator: FrontendGenerator;
254
+
255
+ beforeEach(() => {
256
+ tmpDir = createTempDir();
257
+ generator = new FrontendGenerator();
258
+ });
259
+
260
+ afterEach(() => removeTempDir(tmpDir));
261
+
262
+ it('creates Vue scaffold with all expected directories', () => {
263
+ const result = generator.scaffold({ framework: 'vue', outputDir: tmpDir });
264
+ const expectedDirs = ['components', 'composables', 'pages', 'stores', 'api'];
265
+ for (const dir of expectedDirs) {
266
+ expect(result.dirsCreated.some((d) => d.includes(dir))).toBe(true);
267
+ }
268
+ });
269
+
270
+ it('creates ErrorBoundary.vue with onErrorCaptured', () => {
271
+ generator.scaffold({ framework: 'vue', outputDir: tmpDir });
272
+ const content = fs.readFileSync(path.join(tmpDir, 'src/components/ErrorBoundary.vue'), 'utf-8');
273
+ expect(content).toContain('onErrorCaptured');
274
+ expect(content).toContain('hasError');
275
+ });
276
+
277
+ it('creates useFetch.ts composable', () => {
278
+ generator.scaffold({ framework: 'vue', outputDir: tmpDir });
279
+ const content = fs.readFileSync(path.join(tmpDir, 'src/composables/useFetch.ts'), 'utf-8');
280
+ expect(content).toContain('useFetch');
281
+ expect(content).toContain('watchEffect');
282
+ });
283
+
284
+ it('creates NotFoundPage.vue with ErrorBoundary', () => {
285
+ generator.scaffold({ framework: 'vue', outputDir: tmpDir });
286
+ const content = fs.readFileSync(path.join(tmpDir, 'src/pages/NotFoundPage.vue'), 'utf-8');
287
+ expect(content).toContain('ErrorBoundary');
288
+ expect(content).toContain('404');
289
+ });
290
+
291
+ it('creates Pinia store', () => {
292
+ generator.scaffold({ framework: 'vue', outputDir: tmpDir, projectName: 'MyVueApp' });
293
+ const content = fs.readFileSync(path.join(tmpDir, 'src/stores/app.ts'), 'utf-8');
294
+ expect(content).toContain('defineStore');
295
+ expect(content).toContain('MyVueApp');
296
+ });
297
+
298
+ it('throws for unknown framework', () => {
299
+ expect(() =>
300
+ generator.scaffold({ framework: 'svelte' as never, outputDir: tmpDir })
301
+ ).toThrow('unknown framework');
302
+ });
303
+ });
304
+
305
+ // ---------------------------------------------------------------------------
306
+ // Metrics
307
+ // ---------------------------------------------------------------------------
308
+
309
+ describe('collectFrontendMetrics', () => {
310
+ it('M-01 passes when no large components', () => {
311
+ const results = collectFrontendMetrics({
312
+ largeComponentCount: 0,
313
+ totalComponentsChecked: 10,
314
+ inlineFetchCount: 0,
315
+ pagesWithErrorBoundary: 3,
316
+ totalPages: 3,
317
+ bundleConfigExists: true,
318
+ });
319
+ expect(results.find((r) => r.id === 'M-01')!.pass).toBe(true);
320
+ });
321
+
322
+ it('M-01 fails when large components exist', () => {
323
+ const results = collectFrontendMetrics({
324
+ largeComponentCount: 2,
325
+ totalComponentsChecked: 10,
326
+ inlineFetchCount: 0,
327
+ pagesWithErrorBoundary: 3,
328
+ totalPages: 3,
329
+ bundleConfigExists: true,
330
+ });
331
+ const m01 = results.find((r) => r.id === 'M-01')!;
332
+ expect(m01.pass).toBe(false);
333
+ expect(m01.detail).toContain('2/10');
334
+ });
335
+
336
+ it('M-02 passes with 0 inline fetch', () => {
337
+ const results = collectFrontendMetrics({
338
+ largeComponentCount: 0,
339
+ totalComponentsChecked: 5,
340
+ inlineFetchCount: 0,
341
+ pagesWithErrorBoundary: 2,
342
+ totalPages: 2,
343
+ bundleConfigExists: true,
344
+ });
345
+ expect(results.find((r) => r.id === 'M-02')!.pass).toBe(true);
346
+ });
347
+
348
+ it('M-02 fails with inline fetch', () => {
349
+ const results = collectFrontendMetrics({
350
+ largeComponentCount: 0,
351
+ totalComponentsChecked: 5,
352
+ inlineFetchCount: 3,
353
+ pagesWithErrorBoundary: 2,
354
+ totalPages: 2,
355
+ bundleConfigExists: true,
356
+ });
357
+ const m02 = results.find((r) => r.id === 'M-02')!;
358
+ expect(m02.pass).toBe(false);
359
+ expect(m02.detail).toContain('3 inline');
360
+ });
361
+
362
+ it('M-03 passes when all pages have error boundaries', () => {
363
+ const results = collectFrontendMetrics({
364
+ largeComponentCount: 0,
365
+ totalComponentsChecked: 5,
366
+ inlineFetchCount: 0,
367
+ pagesWithErrorBoundary: 4,
368
+ totalPages: 4,
369
+ bundleConfigExists: true,
370
+ });
371
+ expect(results.find((r) => r.id === 'M-03')!.pass).toBe(true);
372
+ });
373
+
374
+ it('M-03 fails when some pages missing error boundary', () => {
375
+ const results = collectFrontendMetrics({
376
+ largeComponentCount: 0,
377
+ totalComponentsChecked: 5,
378
+ inlineFetchCount: 0,
379
+ pagesWithErrorBoundary: 2,
380
+ totalPages: 4,
381
+ bundleConfigExists: true,
382
+ });
383
+ expect(results.find((r) => r.id === 'M-03')!.pass).toBe(false);
384
+ });
385
+
386
+ it('M-04 passes when bundle config exists', () => {
387
+ const results = collectFrontendMetrics({
388
+ largeComponentCount: 0,
389
+ totalComponentsChecked: 3,
390
+ inlineFetchCount: 0,
391
+ pagesWithErrorBoundary: 1,
392
+ totalPages: 1,
393
+ bundleConfigExists: true,
394
+ });
395
+ expect(results.find((r) => r.id === 'M-04')!.pass).toBe(true);
396
+ });
397
+
398
+ it('M-04 fails when no bundle config', () => {
399
+ const results = collectFrontendMetrics({
400
+ largeComponentCount: 0,
401
+ totalComponentsChecked: 3,
402
+ inlineFetchCount: 0,
403
+ pagesWithErrorBoundary: 1,
404
+ totalPages: 1,
405
+ bundleConfigExists: false,
406
+ });
407
+ expect(results.find((r) => r.id === 'M-04')!.pass).toBe(false);
408
+ });
409
+
410
+ it('returns exactly 4 metrics', () => {
411
+ const results = collectFrontendMetrics({
412
+ largeComponentCount: 0,
413
+ totalComponentsChecked: 0,
414
+ inlineFetchCount: 0,
415
+ pagesWithErrorBoundary: 0,
416
+ totalPages: 0,
417
+ bundleConfigExists: true,
418
+ });
419
+ expect(results).toHaveLength(4);
420
+ });
421
+
422
+ it('all pass with ideal config', () => {
423
+ const results = collectFrontendMetrics({
424
+ largeComponentCount: 0,
425
+ totalComponentsChecked: 10,
426
+ inlineFetchCount: 0,
427
+ pagesWithErrorBoundary: 5,
428
+ totalPages: 5,
429
+ bundleConfigExists: true,
430
+ });
431
+ for (const r of results) {
432
+ expect(r.pass).toBe(true);
433
+ }
434
+ });
435
+ });
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "../../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": ".",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true
9
+ },
10
+ "include": [
11
+ "*.ts",
12
+ "tests/**/*.ts"
13
+ ],
14
+ "exclude": [
15
+ "node_modules",
16
+ "dist"
17
+ ]
18
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * dare-frontend-design — shared types
3
+ * License: MIT
4
+ */
5
+
6
+ export type Framework = 'react' | 'vue';
7
+
8
+ export interface LinterViolation {
9
+ file: string;
10
+ line: number;
11
+ rule: LinterRule;
12
+ message: string;
13
+ severity: 'error' | 'warning';
14
+ }
15
+
16
+ export type LinterRule =
17
+ | 'component-too-large' // Component > 300 lines
18
+ | 'fetch-in-jsx'; // fetch() or axios. in JSX outside hooks/composables
19
+
20
+ export interface LinterResult {
21
+ violations: LinterViolation[];
22
+ filesChecked: number;
23
+ pass: boolean;
24
+ }
25
+
26
+ export interface ScaffoldOptions {
27
+ framework: Framework;
28
+ /** Project root directory */
29
+ outputDir: string;
30
+ /** Project name (used in templates) */
31
+ projectName?: string;
32
+ }
33
+
34
+ export interface ScaffoldResult {
35
+ /** All files created */
36
+ filesCreated: string[];
37
+ /** Directories created */
38
+ dirsCreated: string[];
39
+ framework: Framework;
40
+ }
41
+
42
+ export interface MetricResult {
43
+ id: string;
44
+ pass: boolean;
45
+ description: string;
46
+ detail?: string;
47
+ }
48
+
49
+ export interface FrontendMetricsInput {
50
+ /** M-01: number of components > 300 lines */
51
+ largeComponentCount: number;
52
+ /** M-01: total components checked */
53
+ totalComponentsChecked: number;
54
+ /** M-02: number of fetch() calls found inline in JSX/template */
55
+ inlineFetchCount: number;
56
+ /** M-03: number of pages with error boundaries */
57
+ pagesWithErrorBoundary: number;
58
+ /** M-03: total pages */
59
+ totalPages: number;
60
+ /** M-04: bundle config file exists */
61
+ bundleConfigExists: boolean;
62
+ }