@dewtech/dare-cli 3.11.0 → 3.13.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 (316) hide show
  1. package/README.md +2 -0
  2. package/dist/__tests__/cli-only-invariants.test.d.ts +2 -0
  3. package/dist/__tests__/cli-only-invariants.test.d.ts.map +1 -0
  4. package/dist/__tests__/cli-only-invariants.test.js +100 -0
  5. package/dist/__tests__/cli-only-invariants.test.js.map +1 -0
  6. package/dist/__tests__/cli-only-regression.test.d.ts +2 -0
  7. package/dist/__tests__/cli-only-regression.test.d.ts.map +1 -0
  8. package/dist/__tests__/cli-only-regression.test.js +29 -0
  9. package/dist/__tests__/cli-only-regression.test.js.map +1 -0
  10. package/dist/__tests__/ensure-skills.test.js +5 -0
  11. package/dist/__tests__/ensure-skills.test.js.map +1 -1
  12. package/dist/__tests__/ide-command-parity.test.js +1 -0
  13. package/dist/__tests__/ide-command-parity.test.js.map +1 -1
  14. package/dist/__tests__/project-generator.test.js +17 -0
  15. package/dist/__tests__/project-generator.test.js.map +1 -1
  16. package/dist/__tests__/reverse-facts.test.js +1 -0
  17. package/dist/__tests__/reverse-facts.test.js.map +1 -1
  18. package/dist/__tests__/terminal-parity-regression.test.d.ts +2 -0
  19. package/dist/__tests__/terminal-parity-regression.test.d.ts.map +1 -0
  20. package/dist/__tests__/terminal-parity-regression.test.js +116 -0
  21. package/dist/__tests__/terminal-parity-regression.test.js.map +1 -0
  22. package/dist/__tests__/terminal-parity.test.d.ts +2 -0
  23. package/dist/__tests__/terminal-parity.test.d.ts.map +1 -0
  24. package/dist/__tests__/terminal-parity.test.js +81 -0
  25. package/dist/__tests__/terminal-parity.test.js.map +1 -0
  26. package/dist/agent/__tests__/antigravity-driver.test.d.ts +2 -0
  27. package/dist/agent/__tests__/antigravity-driver.test.d.ts.map +1 -0
  28. package/dist/agent/__tests__/antigravity-driver.test.js +52 -0
  29. package/dist/agent/__tests__/antigravity-driver.test.js.map +1 -0
  30. package/dist/agent/__tests__/codex-driver.test.d.ts +2 -0
  31. package/dist/agent/__tests__/codex-driver.test.d.ts.map +1 -0
  32. package/dist/agent/__tests__/codex-driver.test.js +68 -0
  33. package/dist/agent/__tests__/codex-driver.test.js.map +1 -0
  34. package/dist/agent/__tests__/cursor-driver.test.d.ts +2 -0
  35. package/dist/agent/__tests__/cursor-driver.test.d.ts.map +1 -0
  36. package/dist/agent/__tests__/cursor-driver.test.js +52 -0
  37. package/dist/agent/__tests__/cursor-driver.test.js.map +1 -0
  38. package/dist/agent/driver.d.ts +1 -1
  39. package/dist/agent/driver.d.ts.map +1 -1
  40. package/dist/agent/drivers/antigravity.d.ts +8 -0
  41. package/dist/agent/drivers/antigravity.d.ts.map +1 -0
  42. package/dist/agent/drivers/antigravity.js +99 -0
  43. package/dist/agent/drivers/antigravity.js.map +1 -0
  44. package/dist/agent/drivers/codex.d.ts +12 -0
  45. package/dist/agent/drivers/codex.d.ts.map +1 -0
  46. package/dist/agent/drivers/codex.js +137 -0
  47. package/dist/agent/drivers/codex.js.map +1 -0
  48. package/dist/agent/drivers/cursor.d.ts +8 -0
  49. package/dist/agent/drivers/cursor.d.ts.map +1 -0
  50. package/dist/agent/drivers/cursor.js +99 -0
  51. package/dist/agent/drivers/cursor.js.map +1 -0
  52. package/dist/ai/__tests__/ai-core.test.d.ts +2 -0
  53. package/dist/ai/__tests__/ai-core.test.d.ts.map +1 -0
  54. package/dist/ai/__tests__/ai-core.test.js +41 -0
  55. package/dist/ai/__tests__/ai-core.test.js.map +1 -0
  56. package/dist/ai/__tests__/parity.test.d.ts +2 -0
  57. package/dist/ai/__tests__/parity.test.d.ts.map +1 -0
  58. package/dist/ai/__tests__/parity.test.js +36 -0
  59. package/dist/ai/__tests__/parity.test.js.map +1 -0
  60. package/dist/ai/__tests__/pipeline.test.d.ts +2 -0
  61. package/dist/ai/__tests__/pipeline.test.d.ts.map +1 -0
  62. package/dist/ai/__tests__/pipeline.test.js +147 -0
  63. package/dist/ai/__tests__/pipeline.test.js.map +1 -0
  64. package/dist/ai/__tests__/refine-bridge.test.d.ts +2 -0
  65. package/dist/ai/__tests__/refine-bridge.test.d.ts.map +1 -0
  66. package/dist/ai/__tests__/refine-bridge.test.js +17 -0
  67. package/dist/ai/__tests__/refine-bridge.test.js.map +1 -0
  68. package/dist/ai/__tests__/resolve.test.d.ts +2 -0
  69. package/dist/ai/__tests__/resolve.test.d.ts.map +1 -0
  70. package/dist/ai/__tests__/resolve.test.js +42 -0
  71. package/dist/ai/__tests__/resolve.test.js.map +1 -0
  72. package/dist/ai/capabilities.d.ts +3 -0
  73. package/dist/ai/capabilities.d.ts.map +1 -0
  74. package/dist/ai/capabilities.js +11 -0
  75. package/dist/ai/capabilities.js.map +1 -0
  76. package/dist/ai/command-options.d.ts +10 -0
  77. package/dist/ai/command-options.d.ts.map +1 -0
  78. package/dist/ai/command-options.js +15 -0
  79. package/dist/ai/command-options.js.map +1 -0
  80. package/dist/ai/config.d.ts +27 -0
  81. package/dist/ai/config.d.ts.map +1 -0
  82. package/dist/ai/config.js +89 -0
  83. package/dist/ai/config.js.map +1 -0
  84. package/dist/ai/parity.d.ts +13 -0
  85. package/dist/ai/parity.d.ts.map +1 -0
  86. package/dist/ai/parity.js +87 -0
  87. package/dist/ai/parity.js.map +1 -0
  88. package/dist/ai/parse-json-output.d.ts +5 -0
  89. package/dist/ai/parse-json-output.d.ts.map +1 -0
  90. package/dist/ai/parse-json-output.js +25 -0
  91. package/dist/ai/parse-json-output.js.map +1 -0
  92. package/dist/ai/pipeline.d.ts +20 -0
  93. package/dist/ai/pipeline.d.ts.map +1 -0
  94. package/dist/ai/pipeline.js +303 -0
  95. package/dist/ai/pipeline.js.map +1 -0
  96. package/dist/ai/prompts.d.ts +6 -0
  97. package/dist/ai/prompts.d.ts.map +1 -0
  98. package/dist/ai/prompts.js +49 -0
  99. package/dist/ai/prompts.js.map +1 -0
  100. package/dist/ai/providers.d.ts +63 -0
  101. package/dist/ai/providers.d.ts.map +1 -0
  102. package/dist/ai/providers.js +297 -0
  103. package/dist/ai/providers.js.map +1 -0
  104. package/dist/ai/refine-bridge.d.ts +5 -0
  105. package/dist/ai/refine-bridge.d.ts.map +1 -0
  106. package/dist/ai/refine-bridge.js +14 -0
  107. package/dist/ai/refine-bridge.js.map +1 -0
  108. package/dist/ai/registry.d.ts +12 -0
  109. package/dist/ai/registry.d.ts.map +1 -0
  110. package/dist/ai/registry.js +43 -0
  111. package/dist/ai/registry.js.map +1 -0
  112. package/dist/ai/resolve.d.ts +28 -0
  113. package/dist/ai/resolve.d.ts.map +1 -0
  114. package/dist/ai/resolve.js +83 -0
  115. package/dist/ai/resolve.js.map +1 -0
  116. package/dist/ai/schemas.d.ts +175 -0
  117. package/dist/ai/schemas.d.ts.map +1 -0
  118. package/dist/ai/schemas.js +199 -0
  119. package/dist/ai/schemas.js.map +1 -0
  120. package/dist/ai/types.d.ts +52 -0
  121. package/dist/ai/types.d.ts.map +1 -0
  122. package/dist/ai/types.js +8 -0
  123. package/dist/ai/types.js.map +1 -0
  124. package/dist/bin/dare.js +2 -0
  125. package/dist/bin/dare.js.map +1 -1
  126. package/dist/commands/__tests__/ai-command.test.d.ts +2 -0
  127. package/dist/commands/__tests__/ai-command.test.d.ts.map +1 -0
  128. package/dist/commands/__tests__/ai-command.test.js +68 -0
  129. package/dist/commands/__tests__/ai-command.test.js.map +1 -0
  130. package/dist/commands/__tests__/execute-agent.test.js +82 -0
  131. package/dist/commands/__tests__/execute-agent.test.js.map +1 -1
  132. package/dist/commands/ai.d.ts +3 -0
  133. package/dist/commands/ai.d.ts.map +1 -0
  134. package/dist/commands/ai.js +141 -0
  135. package/dist/commands/ai.js.map +1 -0
  136. package/dist/commands/blueprint.d.ts.map +1 -1
  137. package/dist/commands/blueprint.js +17 -3
  138. package/dist/commands/blueprint.js.map +1 -1
  139. package/dist/commands/design.d.ts.map +1 -1
  140. package/dist/commands/design.js +21 -2
  141. package/dist/commands/design.js.map +1 -1
  142. package/dist/commands/discover.d.ts.map +1 -1
  143. package/dist/commands/discover.js +9 -1
  144. package/dist/commands/discover.js.map +1 -1
  145. package/dist/commands/dna.d.ts.map +1 -1
  146. package/dist/commands/dna.js +23 -3
  147. package/dist/commands/dna.js.map +1 -1
  148. package/dist/commands/execute.d.ts +11 -0
  149. package/dist/commands/execute.d.ts.map +1 -1
  150. package/dist/commands/execute.js +111 -4
  151. package/dist/commands/execute.js.map +1 -1
  152. package/dist/commands/init.d.ts.map +1 -1
  153. package/dist/commands/init.js +1 -0
  154. package/dist/commands/init.js.map +1 -1
  155. package/dist/commands/migrate.d.ts.map +1 -1
  156. package/dist/commands/migrate.js +14 -2
  157. package/dist/commands/migrate.js.map +1 -1
  158. package/dist/commands/patterns.d.ts.map +1 -1
  159. package/dist/commands/patterns.js +14 -2
  160. package/dist/commands/patterns.js.map +1 -1
  161. package/dist/commands/refine.d.ts.map +1 -1
  162. package/dist/commands/refine.js +23 -2
  163. package/dist/commands/refine.js.map +1 -1
  164. package/dist/commands/reverse.d.ts.map +1 -1
  165. package/dist/commands/reverse.js +28 -3
  166. package/dist/commands/reverse.js.map +1 -1
  167. package/dist/commands/review.d.ts.map +1 -1
  168. package/dist/commands/review.js +25 -3
  169. package/dist/commands/review.js.map +1 -1
  170. package/dist/core/types/project.d.ts +1 -1
  171. package/dist/core/types/project.d.ts.map +1 -1
  172. package/dist/dag-runner/run_dag.d.ts +1 -1
  173. package/dist/dag-runner/run_dag.d.ts.map +1 -1
  174. package/dist/exec/safe-spawn.d.ts.map +1 -1
  175. package/dist/exec/safe-spawn.js +6 -1
  176. package/dist/exec/safe-spawn.js.map +1 -1
  177. package/dist/skills/bundled.d.ts +5 -0
  178. package/dist/skills/bundled.d.ts.map +1 -0
  179. package/dist/skills/bundled.js +34 -0
  180. package/dist/skills/bundled.js.map +1 -0
  181. package/dist/skills/commands/add.d.ts +1 -3
  182. package/dist/skills/commands/add.d.ts.map +1 -1
  183. package/dist/skills/commands/add.js +20 -3
  184. package/dist/skills/commands/add.js.map +1 -1
  185. package/dist/skills/tests/bundled.spec.d.ts +2 -0
  186. package/dist/skills/tests/bundled.spec.d.ts.map +1 -0
  187. package/dist/skills/tests/bundled.spec.js +24 -0
  188. package/dist/skills/tests/bundled.spec.js.map +1 -0
  189. package/dist/types/UpdateManifest.types.d.ts +1 -1
  190. package/dist/types/UpdateManifest.types.d.ts.map +1 -1
  191. package/dist/utils/dag-converter.js +1 -1
  192. package/dist/utils/dag-converter.js.map +1 -1
  193. package/dist/utils/project-detector.d.ts +1 -0
  194. package/dist/utils/project-detector.d.ts.map +1 -1
  195. package/dist/utils/project-detector.js +8 -0
  196. package/dist/utils/project-detector.js.map +1 -1
  197. package/dist/utils/project-generator.d.ts +1 -1
  198. package/dist/utils/project-generator.d.ts.map +1 -1
  199. package/dist/utils/project-generator.js +23 -2
  200. package/dist/utils/project-generator.js.map +1 -1
  201. package/dist/utils/templates.d.ts +2 -0
  202. package/dist/utils/templates.d.ts.map +1 -1
  203. package/dist/utils/templates.js +74 -0
  204. package/dist/utils/templates.js.map +1 -1
  205. package/dist/verification/__tests__/safe-spawn.test.js +12 -0
  206. package/dist/verification/__tests__/safe-spawn.test.js.map +1 -1
  207. package/package.json +2 -1
  208. package/skills/dare-ax/generator.ts +325 -0
  209. package/skills/dare-ax/index.ts +19 -0
  210. package/skills/dare-ax/metrics.ts +352 -0
  211. package/skills/dare-ax/package-lock.json +1855 -0
  212. package/skills/dare-ax/package.json +50 -0
  213. package/skills/dare-ax/secret-detector.ts +123 -0
  214. package/skills/dare-ax/skill.yml +19 -0
  215. package/skills/dare-ax/templates/llms.txt.jinja2 +80 -0
  216. package/skills/dare-ax/tests/generator.spec.ts +193 -0
  217. package/skills/dare-ax/tests/metrics.spec.ts +394 -0
  218. package/skills/dare-ax/tests/validator.spec.ts +298 -0
  219. package/skills/dare-ax/tsconfig.json +18 -0
  220. package/skills/dare-ax/types.ts +79 -0
  221. package/skills/dare-ax/validator.ts +238 -0
  222. package/skills/dare-frontend-design/generator.ts +616 -0
  223. package/skills/dare-frontend-design/index.ts +25 -0
  224. package/skills/dare-frontend-design/linter.ts +227 -0
  225. package/skills/dare-frontend-design/metrics.ts +82 -0
  226. package/skills/dare-frontend-design/package-lock.json +1855 -0
  227. package/skills/dare-frontend-design/package.json +43 -0
  228. package/skills/dare-frontend-design/skill.yml +20 -0
  229. package/skills/dare-frontend-design/tests/frontend_design.spec.ts +435 -0
  230. package/skills/dare-frontend-design/tsconfig.json +18 -0
  231. package/skills/dare-frontend-design/types.ts +62 -0
  232. package/skills/dare-layered-design/generator.ts +740 -0
  233. package/skills/dare-layered-design/index.ts +17 -0
  234. package/skills/dare-layered-design/linter.ts +462 -0
  235. package/skills/dare-layered-design/metrics.ts +409 -0
  236. package/skills/dare-layered-design/package-lock.json +1855 -0
  237. package/skills/dare-layered-design/package.json +50 -0
  238. package/skills/dare-layered-design/skill.yml +35 -0
  239. package/skills/dare-layered-design/tests/generator.spec.ts +156 -0
  240. package/skills/dare-layered-design/tests/linter.spec.ts +255 -0
  241. package/skills/dare-layered-design/tests/metrics.spec.ts +286 -0
  242. package/skills/dare-layered-design/tsconfig.json +18 -0
  243. package/skills/dare-layered-design/types.ts +48 -0
  244. package/skills/dare-llm-integration/cache/llm_cache.ts +122 -0
  245. package/skills/dare-llm-integration/index.ts +49 -0
  246. package/skills/dare-llm-integration/metrics.ts +107 -0
  247. package/skills/dare-llm-integration/package-lock.json +1855 -0
  248. package/skills/dare-llm-integration/package.json +49 -0
  249. package/skills/dare-llm-integration/prompts/prompt_loader.ts +258 -0
  250. package/skills/dare-llm-integration/providers/anthropic_provider.ts +159 -0
  251. package/skills/dare-llm-integration/providers/dummy_provider.ts +113 -0
  252. package/skills/dare-llm-integration/providers/llm_provider.ts +6 -0
  253. package/skills/dare-llm-integration/providers/openai_provider.ts +215 -0
  254. package/skills/dare-llm-integration/rate_limit/token_bucket.ts +86 -0
  255. package/skills/dare-llm-integration/skill.yml +23 -0
  256. package/skills/dare-llm-integration/tests/fixtures/greet_v1.jinja2 +1 -0
  257. package/skills/dare-llm-integration/tests/fixtures/summarize_v1.jinja2 +1 -0
  258. package/skills/dare-llm-integration/tests/fixtures/summarize_v2.jinja2 +3 -0
  259. package/skills/dare-llm-integration/tests/llm_integration.spec.ts +657 -0
  260. package/skills/dare-llm-integration/tsconfig.json +23 -0
  261. package/skills/dare-llm-integration/types.ts +91 -0
  262. package/skills/dare-llm-integration/validators/output_validator.ts +200 -0
  263. package/skills/dare-quality-telemetry/collect.ts +134 -0
  264. package/skills/dare-quality-telemetry/collectors/dare_ax_collector.ts +301 -0
  265. package/skills/dare-quality-telemetry/collectors/dare_layered_design_collector.ts +406 -0
  266. package/skills/dare-quality-telemetry/collectors/index.ts +24 -0
  267. package/skills/dare-quality-telemetry/github_actions_template.ts +25 -0
  268. package/skills/dare-quality-telemetry/index.ts +18 -0
  269. package/skills/dare-quality-telemetry/metrics.ts +137 -0
  270. package/skills/dare-quality-telemetry/package-lock.json +1855 -0
  271. package/skills/dare-quality-telemetry/package.json +48 -0
  272. package/skills/dare-quality-telemetry/regression.ts +60 -0
  273. package/skills/dare-quality-telemetry/reporter.ts +132 -0
  274. package/skills/dare-quality-telemetry/skill.yml +18 -0
  275. package/skills/dare-quality-telemetry/tests/quality_telemetry.spec.ts +885 -0
  276. package/skills/dare-quality-telemetry/tsconfig.json +19 -0
  277. package/skills/dare-quality-telemetry/types.ts +41 -0
  278. package/skills/dare-realtime/event_registry.ts +101 -0
  279. package/skills/dare-realtime/index.ts +30 -0
  280. package/skills/dare-realtime/metrics.ts +84 -0
  281. package/skills/dare-realtime/package-lock.json +1855 -0
  282. package/skills/dare-realtime/package.json +43 -0
  283. package/skills/dare-realtime/reconnect_strategy.ts +85 -0
  284. package/skills/dare-realtime/schema_validator.ts +80 -0
  285. package/skills/dare-realtime/skill.yml +21 -0
  286. package/skills/dare-realtime/subscription_manager.ts +106 -0
  287. package/skills/dare-realtime/tests/realtime.spec.ts +482 -0
  288. package/skills/dare-realtime/tsconfig.json +18 -0
  289. package/skills/dare-realtime/types.ts +51 -0
  290. package/templates/ide/antigravity/.agents/skills/dare-ai/SKILL.md +17 -0
  291. package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +2 -0
  292. package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +2 -0
  293. package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +3 -0
  294. package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +3 -0
  295. package/templates/ide/antigravity/.agents/skills/dare-patterns/SKILL.md +3 -0
  296. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +3 -0
  297. package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +3 -0
  298. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +3 -0
  299. package/templates/ide/claude/.claude/commands/dare-ai.md +17 -0
  300. package/templates/ide/claude/.claude/commands/dare-blueprint.md +2 -0
  301. package/templates/ide/claude/.claude/commands/dare-design.md +2 -0
  302. package/templates/ide/claude/.claude/commands/dare-dna.md +2 -0
  303. package/templates/ide/claude/.claude/commands/dare-migrate.md +2 -0
  304. package/templates/ide/claude/.claude/commands/dare-patterns.md +3 -0
  305. package/templates/ide/claude/.claude/commands/dare-refine.md +3 -0
  306. package/templates/ide/claude/.claude/commands/dare-reverse.md +2 -0
  307. package/templates/ide/claude/.claude/commands/dare-review.md +3 -0
  308. package/templates/ide/cursor/.cursor/commands/dare-ai.md +17 -0
  309. package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +3 -0
  310. package/templates/ide/cursor/.cursor/commands/dare-design.md +3 -0
  311. package/templates/ide/cursor/.cursor/commands/dare-dna.md +2 -0
  312. package/templates/ide/cursor/.cursor/commands/dare-migrate.md +2 -0
  313. package/templates/ide/cursor/.cursor/commands/dare-patterns.md +3 -0
  314. package/templates/ide/cursor/.cursor/commands/dare-refine.md +3 -0
  315. package/templates/ide/cursor/.cursor/commands/dare-reverse.md +2 -0
  316. package/templates/ide/cursor/.cursor/commands/dare-review.md +3 -0
@@ -0,0 +1,91 @@
1
+ /**
2
+ * dare-llm-integration — shared types
3
+ * License: MIT
4
+ */
5
+
6
+ export interface CompletionRequest {
7
+ model: string;
8
+ prompt: string;
9
+ temperature?: number;
10
+ maxTokens?: number;
11
+ systemPrompt?: string;
12
+ timeoutMs?: number;
13
+ }
14
+
15
+ export interface CompletionResponse {
16
+ text: string;
17
+ tokensUsed: {
18
+ input: number;
19
+ output: number;
20
+ total: number;
21
+ };
22
+ cached: boolean;
23
+ model: string;
24
+ latencyMs?: number;
25
+ }
26
+
27
+ export interface EmbedRequest {
28
+ model: string;
29
+ input: string | string[];
30
+ timeoutMs?: number;
31
+ }
32
+
33
+ export interface EmbeddingResponse {
34
+ embeddings: number[][];
35
+ tokensUsed: number;
36
+ model: string;
37
+ cached: boolean;
38
+ }
39
+
40
+ export interface LLMProvider {
41
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
42
+ embed(request: EmbedRequest): Promise<EmbeddingResponse>;
43
+ }
44
+
45
+ export interface PromptTemplate {
46
+ name: string;
47
+ version: string;
48
+ content: string;
49
+ variables: string[];
50
+ }
51
+
52
+ export interface CacheEntry {
53
+ value: CompletionResponse | EmbeddingResponse;
54
+ expiresAt: number;
55
+ createdAt: number;
56
+ hits: number;
57
+ }
58
+
59
+ export interface RateLimiterConfig {
60
+ rps: number;
61
+ maxBurst?: number;
62
+ }
63
+
64
+ export interface OutputValidationResult {
65
+ ok: boolean;
66
+ data?: unknown;
67
+ errors: OutputValidationError[];
68
+ }
69
+
70
+ export interface OutputValidationError {
71
+ field: string;
72
+ message: string;
73
+ value?: unknown;
74
+ }
75
+
76
+ export interface MetricResult {
77
+ id: string;
78
+ pass: boolean;
79
+ description: string;
80
+ detail?: string;
81
+ }
82
+
83
+ export interface LLMUsageStats {
84
+ totalRequests: number;
85
+ cacheHits: number;
86
+ cacheMisses: number;
87
+ rateLimitedRequests: number;
88
+ validatedResponses: number;
89
+ totalInputTokens: number;
90
+ totalOutputTokens: number;
91
+ }
@@ -0,0 +1,200 @@
1
+ /**
2
+ * dare-llm-integration — OutputValidator
3
+ * Validates LLM output against a JSON Schema.
4
+ * Zero external dependencies — uses a minimal built-in schema checker.
5
+ * License: MIT
6
+ */
7
+
8
+ import type { OutputValidationResult, OutputValidationError } from '../types.js';
9
+
10
+ type JsonSchemaType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'integer';
11
+
12
+ export interface JsonSchema {
13
+ type?: JsonSchemaType | JsonSchemaType[];
14
+ properties?: Record<string, JsonSchema>;
15
+ required?: string[];
16
+ items?: JsonSchema;
17
+ minLength?: number;
18
+ maxLength?: number;
19
+ minimum?: number;
20
+ maximum?: number;
21
+ enum?: unknown[];
22
+ format?: string;
23
+ additionalProperties?: boolean | JsonSchema;
24
+ [key: string]: unknown;
25
+ }
26
+
27
+ export class OutputValidator {
28
+ /**
29
+ * Parse the output string as JSON, then validate against schema.
30
+ *
31
+ * @param output - Raw string output from LLM
32
+ * @param schema - JSON Schema object to validate against
33
+ */
34
+ validate(output: string, schema: JsonSchema): OutputValidationResult {
35
+ // Step 1: Parse JSON
36
+ let parsed: unknown;
37
+ try {
38
+ parsed = JSON.parse(output);
39
+ } catch {
40
+ return {
41
+ ok: false,
42
+ errors: [
43
+ {
44
+ field: '$root',
45
+ message: `Output is not valid JSON: ${output.slice(0, 100)}`,
46
+ },
47
+ ],
48
+ };
49
+ }
50
+
51
+ // Step 2: Validate against schema
52
+ const errors: OutputValidationError[] = [];
53
+ validateValue(parsed, schema, '$', errors);
54
+
55
+ if (errors.length > 0) {
56
+ return { ok: false, errors };
57
+ }
58
+
59
+ return { ok: true, data: parsed, errors: [] };
60
+ }
61
+
62
+ /**
63
+ * Validate a pre-parsed value (skip JSON.parse step).
64
+ */
65
+ validateParsed(value: unknown, schema: JsonSchema): OutputValidationResult {
66
+ const errors: OutputValidationError[] = [];
67
+ validateValue(value, schema, '$', errors);
68
+
69
+ if (errors.length > 0) {
70
+ return { ok: false, errors };
71
+ }
72
+
73
+ return { ok: true, data: value, errors: [] };
74
+ }
75
+ }
76
+
77
+ function validateValue(
78
+ value: unknown,
79
+ schema: JsonSchema,
80
+ path: string,
81
+ errors: OutputValidationError[]
82
+ ): void {
83
+ // Type check
84
+ if (schema.type !== undefined) {
85
+ const types = Array.isArray(schema.type) ? schema.type : [schema.type];
86
+ const actualType = getJsonType(value);
87
+ const matches = types.some((t) => {
88
+ if (t === 'integer') return Number.isInteger(value);
89
+ return t === actualType;
90
+ });
91
+ if (!matches) {
92
+ errors.push({
93
+ field: path,
94
+ message: `Expected type ${types.join('|')}, got ${actualType}`,
95
+ value,
96
+ });
97
+ return; // No point checking further if wrong type
98
+ }
99
+ }
100
+
101
+ // Object-specific checks
102
+ if (schema.type === 'object' || (schema.properties !== undefined && typeof value === 'object' && value !== null && !Array.isArray(value))) {
103
+ const obj = value as Record<string, unknown>;
104
+
105
+ // Required fields
106
+ if (schema.required) {
107
+ for (const field of schema.required) {
108
+ if (!(field in obj) || obj[field] === undefined || obj[field] === null) {
109
+ errors.push({
110
+ field: `${path}.${field}`,
111
+ message: `Required field "${field}" is missing`,
112
+ });
113
+ }
114
+ }
115
+ }
116
+
117
+ // Properties
118
+ if (schema.properties) {
119
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
120
+ if (key in obj) {
121
+ validateValue(obj[key], propSchema, `${path}.${key}`, errors);
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ // Array-specific checks
128
+ if (schema.type === 'array' || (schema.items !== undefined && Array.isArray(value))) {
129
+ const arr = value as unknown[];
130
+ if (schema.items) {
131
+ arr.forEach((item, idx) => {
132
+ validateValue(item, schema.items!, `${path}[${idx}]`, errors);
133
+ });
134
+ }
135
+ }
136
+
137
+ // String constraints
138
+ if (typeof value === 'string') {
139
+ if (schema.minLength !== undefined && value.length < schema.minLength) {
140
+ errors.push({
141
+ field: path,
142
+ message: `String length ${value.length} is less than minLength ${schema.minLength}`,
143
+ value,
144
+ });
145
+ }
146
+ if (schema.maxLength !== undefined && value.length > schema.maxLength) {
147
+ errors.push({
148
+ field: path,
149
+ message: `String length ${value.length} exceeds maxLength ${schema.maxLength}`,
150
+ value,
151
+ });
152
+ }
153
+ }
154
+
155
+ // Number constraints
156
+ if (typeof value === 'number') {
157
+ if (schema.minimum !== undefined && value < schema.minimum) {
158
+ errors.push({
159
+ field: path,
160
+ message: `Value ${value} is less than minimum ${schema.minimum}`,
161
+ value,
162
+ });
163
+ }
164
+ if (schema.maximum !== undefined && value > schema.maximum) {
165
+ errors.push({
166
+ field: path,
167
+ message: `Value ${value} exceeds maximum ${schema.maximum}`,
168
+ value,
169
+ });
170
+ }
171
+ }
172
+
173
+ // Enum check
174
+ if (schema.enum !== undefined) {
175
+ const enumValues = schema.enum;
176
+ const found = enumValues.some((e) => deepEqual(e, value));
177
+ if (!found) {
178
+ errors.push({
179
+ field: path,
180
+ message: `Value not in enum: ${JSON.stringify(enumValues)}`,
181
+ value,
182
+ });
183
+ }
184
+ }
185
+ }
186
+
187
+ function getJsonType(value: unknown): JsonSchemaType {
188
+ if (value === null) return 'null';
189
+ if (Array.isArray(value)) return 'array';
190
+ return typeof value as JsonSchemaType;
191
+ }
192
+
193
+ function deepEqual(a: unknown, b: unknown): boolean {
194
+ if (a === b) return true;
195
+ if (typeof a !== typeof b) return false;
196
+ if (typeof a === 'object' && a !== null && b !== null) {
197
+ return JSON.stringify(a) === JSON.stringify(b);
198
+ }
199
+ return false;
200
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * dare-quality-telemetry — main collect function
3
+ * Orchestrates metric collection for all configured skills and saves results.
4
+ * License: MIT
5
+ */
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import { execSync } from 'child_process';
10
+ import {
11
+ CollectorConfig,
12
+ ProjectMetricReport,
13
+ SkillMetricReport,
14
+ MetricResult,
15
+ } from './types.js';
16
+ import { collectors } from './collectors/index.js';
17
+
18
+ /**
19
+ * Detects the current git commit SHA.
20
+ * Returns "unknown" if git is not available or the directory is not a repo.
21
+ */
22
+ export function detectCommit(projectPath: string): string {
23
+ try {
24
+ const result = execSync('git rev-parse --short HEAD', {
25
+ cwd: projectPath,
26
+ encoding: 'utf-8',
27
+ stdio: ['pipe', 'pipe', 'pipe'],
28
+ });
29
+ return result.trim();
30
+ } catch {
31
+ return 'unknown';
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Builds a summary object from a list of MetricResults.
37
+ */
38
+ export function buildSummary(metrics: MetricResult[]): {
39
+ passed: number;
40
+ total: number;
41
+ score: string;
42
+ allPass: boolean;
43
+ } {
44
+ const total = metrics.length;
45
+ const passed = metrics.filter((m) => m.pass).length;
46
+ const score = total === 0 ? '0/0' : `${passed}/${total}`;
47
+ const allPass = total > 0 && passed === total;
48
+ return { passed, total, score, allPass };
49
+ }
50
+
51
+ /**
52
+ * Main function: collects metrics for all configured skills in the project.
53
+ *
54
+ * @param config - CollectorConfig specifying project path and skills to validate.
55
+ * @returns ProjectMetricReport with all results.
56
+ *
57
+ * Side effect: writes result to <projectPath>/tmp/dare_metrics.json
58
+ */
59
+ export async function collectMetrics(config: CollectorConfig): Promise<ProjectMetricReport> {
60
+ const { projectPath, skills } = config;
61
+ const timestamp = new Date().toISOString();
62
+ const commit = detectCommit(projectPath);
63
+
64
+ const skillReports: SkillMetricReport[] = [];
65
+
66
+ for (const skillName of skills) {
67
+ const collector = collectors[skillName];
68
+
69
+ if (!collector) {
70
+ // Unknown skill — report it as a failed collector with a placeholder metric
71
+ skillReports.push({
72
+ skillName,
73
+ timestamp,
74
+ commit,
75
+ metrics: [
76
+ {
77
+ id: 'M-00',
78
+ pass: false,
79
+ description: 'Collector available',
80
+ details: `No collector registered for skill "${skillName}". Available: ${Object.keys(collectors).join(', ')}`,
81
+ },
82
+ ],
83
+ summary: { passed: 0, total: 1, score: '0/1', allPass: false },
84
+ });
85
+ continue;
86
+ }
87
+
88
+ let metrics: MetricResult[];
89
+ try {
90
+ metrics = await collector(projectPath);
91
+ } catch (err) {
92
+ metrics = [
93
+ {
94
+ id: 'M-00',
95
+ pass: false,
96
+ description: 'Collector executed without error',
97
+ details: `Collector for "${skillName}" threw: ${(err as Error).message}`,
98
+ },
99
+ ];
100
+ }
101
+
102
+ const summary = buildSummary(metrics);
103
+ skillReports.push({ skillName, timestamp, commit, metrics, summary });
104
+ }
105
+
106
+ // Calculate overall summary
107
+ const allMetrics = skillReports.flatMap((s) => s.metrics);
108
+ const overall = buildSummary(allMetrics);
109
+
110
+ const report: ProjectMetricReport = {
111
+ timestamp,
112
+ commit,
113
+ projectPath,
114
+ skills: skillReports,
115
+ overall,
116
+ };
117
+
118
+ // Save to tmp/dare_metrics.json
119
+ const tmpDir = path.join(projectPath, 'tmp');
120
+ try {
121
+ if (!fs.existsSync(tmpDir)) {
122
+ fs.mkdirSync(tmpDir, { recursive: true });
123
+ }
124
+ fs.writeFileSync(
125
+ path.join(tmpDir, 'dare_metrics.json'),
126
+ JSON.stringify(report, null, 2),
127
+ 'utf-8'
128
+ );
129
+ } catch {
130
+ // Non-fatal: log failure but return the report regardless
131
+ }
132
+
133
+ return report;
134
+ }