@dewtech/dare-cli 3.11.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 (308) hide show
  1. package/README.md +2 -0
  2. package/dist/__tests__/ensure-skills.test.js +5 -0
  3. package/dist/__tests__/ensure-skills.test.js.map +1 -1
  4. package/dist/__tests__/ide-command-parity.test.js +1 -0
  5. package/dist/__tests__/ide-command-parity.test.js.map +1 -1
  6. package/dist/__tests__/project-generator.test.js +17 -0
  7. package/dist/__tests__/project-generator.test.js.map +1 -1
  8. package/dist/__tests__/reverse-facts.test.js +1 -0
  9. package/dist/__tests__/reverse-facts.test.js.map +1 -1
  10. package/dist/__tests__/terminal-parity-regression.test.d.ts +2 -0
  11. package/dist/__tests__/terminal-parity-regression.test.d.ts.map +1 -0
  12. package/dist/__tests__/terminal-parity-regression.test.js +116 -0
  13. package/dist/__tests__/terminal-parity-regression.test.js.map +1 -0
  14. package/dist/__tests__/terminal-parity.test.d.ts +2 -0
  15. package/dist/__tests__/terminal-parity.test.d.ts.map +1 -0
  16. package/dist/__tests__/terminal-parity.test.js +81 -0
  17. package/dist/__tests__/terminal-parity.test.js.map +1 -0
  18. package/dist/agent/__tests__/antigravity-driver.test.d.ts +2 -0
  19. package/dist/agent/__tests__/antigravity-driver.test.d.ts.map +1 -0
  20. package/dist/agent/__tests__/antigravity-driver.test.js +52 -0
  21. package/dist/agent/__tests__/antigravity-driver.test.js.map +1 -0
  22. package/dist/agent/__tests__/codex-driver.test.d.ts +2 -0
  23. package/dist/agent/__tests__/codex-driver.test.d.ts.map +1 -0
  24. package/dist/agent/__tests__/codex-driver.test.js +68 -0
  25. package/dist/agent/__tests__/codex-driver.test.js.map +1 -0
  26. package/dist/agent/__tests__/cursor-driver.test.d.ts +2 -0
  27. package/dist/agent/__tests__/cursor-driver.test.d.ts.map +1 -0
  28. package/dist/agent/__tests__/cursor-driver.test.js +52 -0
  29. package/dist/agent/__tests__/cursor-driver.test.js.map +1 -0
  30. package/dist/agent/driver.d.ts +1 -1
  31. package/dist/agent/driver.d.ts.map +1 -1
  32. package/dist/agent/drivers/antigravity.d.ts +8 -0
  33. package/dist/agent/drivers/antigravity.d.ts.map +1 -0
  34. package/dist/agent/drivers/antigravity.js +99 -0
  35. package/dist/agent/drivers/antigravity.js.map +1 -0
  36. package/dist/agent/drivers/codex.d.ts +12 -0
  37. package/dist/agent/drivers/codex.d.ts.map +1 -0
  38. package/dist/agent/drivers/codex.js +137 -0
  39. package/dist/agent/drivers/codex.js.map +1 -0
  40. package/dist/agent/drivers/cursor.d.ts +8 -0
  41. package/dist/agent/drivers/cursor.d.ts.map +1 -0
  42. package/dist/agent/drivers/cursor.js +99 -0
  43. package/dist/agent/drivers/cursor.js.map +1 -0
  44. package/dist/ai/__tests__/ai-core.test.d.ts +2 -0
  45. package/dist/ai/__tests__/ai-core.test.d.ts.map +1 -0
  46. package/dist/ai/__tests__/ai-core.test.js +41 -0
  47. package/dist/ai/__tests__/ai-core.test.js.map +1 -0
  48. package/dist/ai/__tests__/parity.test.d.ts +2 -0
  49. package/dist/ai/__tests__/parity.test.d.ts.map +1 -0
  50. package/dist/ai/__tests__/parity.test.js +36 -0
  51. package/dist/ai/__tests__/parity.test.js.map +1 -0
  52. package/dist/ai/__tests__/pipeline.test.d.ts +2 -0
  53. package/dist/ai/__tests__/pipeline.test.d.ts.map +1 -0
  54. package/dist/ai/__tests__/pipeline.test.js +147 -0
  55. package/dist/ai/__tests__/pipeline.test.js.map +1 -0
  56. package/dist/ai/__tests__/refine-bridge.test.d.ts +2 -0
  57. package/dist/ai/__tests__/refine-bridge.test.d.ts.map +1 -0
  58. package/dist/ai/__tests__/refine-bridge.test.js +17 -0
  59. package/dist/ai/__tests__/refine-bridge.test.js.map +1 -0
  60. package/dist/ai/__tests__/resolve.test.d.ts +2 -0
  61. package/dist/ai/__tests__/resolve.test.d.ts.map +1 -0
  62. package/dist/ai/__tests__/resolve.test.js +42 -0
  63. package/dist/ai/__tests__/resolve.test.js.map +1 -0
  64. package/dist/ai/capabilities.d.ts +3 -0
  65. package/dist/ai/capabilities.d.ts.map +1 -0
  66. package/dist/ai/capabilities.js +11 -0
  67. package/dist/ai/capabilities.js.map +1 -0
  68. package/dist/ai/command-options.d.ts +10 -0
  69. package/dist/ai/command-options.d.ts.map +1 -0
  70. package/dist/ai/command-options.js +15 -0
  71. package/dist/ai/command-options.js.map +1 -0
  72. package/dist/ai/config.d.ts +27 -0
  73. package/dist/ai/config.d.ts.map +1 -0
  74. package/dist/ai/config.js +89 -0
  75. package/dist/ai/config.js.map +1 -0
  76. package/dist/ai/parity.d.ts +13 -0
  77. package/dist/ai/parity.d.ts.map +1 -0
  78. package/dist/ai/parity.js +87 -0
  79. package/dist/ai/parity.js.map +1 -0
  80. package/dist/ai/parse-json-output.d.ts +5 -0
  81. package/dist/ai/parse-json-output.d.ts.map +1 -0
  82. package/dist/ai/parse-json-output.js +25 -0
  83. package/dist/ai/parse-json-output.js.map +1 -0
  84. package/dist/ai/pipeline.d.ts +20 -0
  85. package/dist/ai/pipeline.d.ts.map +1 -0
  86. package/dist/ai/pipeline.js +303 -0
  87. package/dist/ai/pipeline.js.map +1 -0
  88. package/dist/ai/prompts.d.ts +6 -0
  89. package/dist/ai/prompts.d.ts.map +1 -0
  90. package/dist/ai/prompts.js +49 -0
  91. package/dist/ai/prompts.js.map +1 -0
  92. package/dist/ai/providers.d.ts +63 -0
  93. package/dist/ai/providers.d.ts.map +1 -0
  94. package/dist/ai/providers.js +297 -0
  95. package/dist/ai/providers.js.map +1 -0
  96. package/dist/ai/refine-bridge.d.ts +5 -0
  97. package/dist/ai/refine-bridge.d.ts.map +1 -0
  98. package/dist/ai/refine-bridge.js +14 -0
  99. package/dist/ai/refine-bridge.js.map +1 -0
  100. package/dist/ai/registry.d.ts +12 -0
  101. package/dist/ai/registry.d.ts.map +1 -0
  102. package/dist/ai/registry.js +43 -0
  103. package/dist/ai/registry.js.map +1 -0
  104. package/dist/ai/resolve.d.ts +28 -0
  105. package/dist/ai/resolve.d.ts.map +1 -0
  106. package/dist/ai/resolve.js +83 -0
  107. package/dist/ai/resolve.js.map +1 -0
  108. package/dist/ai/schemas.d.ts +175 -0
  109. package/dist/ai/schemas.d.ts.map +1 -0
  110. package/dist/ai/schemas.js +199 -0
  111. package/dist/ai/schemas.js.map +1 -0
  112. package/dist/ai/types.d.ts +52 -0
  113. package/dist/ai/types.d.ts.map +1 -0
  114. package/dist/ai/types.js +8 -0
  115. package/dist/ai/types.js.map +1 -0
  116. package/dist/bin/dare.js +2 -0
  117. package/dist/bin/dare.js.map +1 -1
  118. package/dist/commands/__tests__/ai-command.test.d.ts +2 -0
  119. package/dist/commands/__tests__/ai-command.test.d.ts.map +1 -0
  120. package/dist/commands/__tests__/ai-command.test.js +68 -0
  121. package/dist/commands/__tests__/ai-command.test.js.map +1 -0
  122. package/dist/commands/__tests__/execute-agent.test.js +82 -0
  123. package/dist/commands/__tests__/execute-agent.test.js.map +1 -1
  124. package/dist/commands/ai.d.ts +3 -0
  125. package/dist/commands/ai.d.ts.map +1 -0
  126. package/dist/commands/ai.js +141 -0
  127. package/dist/commands/ai.js.map +1 -0
  128. package/dist/commands/blueprint.d.ts.map +1 -1
  129. package/dist/commands/blueprint.js +17 -3
  130. package/dist/commands/blueprint.js.map +1 -1
  131. package/dist/commands/design.d.ts.map +1 -1
  132. package/dist/commands/design.js +21 -2
  133. package/dist/commands/design.js.map +1 -1
  134. package/dist/commands/discover.d.ts.map +1 -1
  135. package/dist/commands/discover.js +9 -1
  136. package/dist/commands/discover.js.map +1 -1
  137. package/dist/commands/dna.d.ts.map +1 -1
  138. package/dist/commands/dna.js +23 -3
  139. package/dist/commands/dna.js.map +1 -1
  140. package/dist/commands/execute.d.ts +11 -0
  141. package/dist/commands/execute.d.ts.map +1 -1
  142. package/dist/commands/execute.js +111 -4
  143. package/dist/commands/execute.js.map +1 -1
  144. package/dist/commands/init.d.ts.map +1 -1
  145. package/dist/commands/init.js +1 -0
  146. package/dist/commands/init.js.map +1 -1
  147. package/dist/commands/migrate.d.ts.map +1 -1
  148. package/dist/commands/migrate.js +14 -2
  149. package/dist/commands/migrate.js.map +1 -1
  150. package/dist/commands/patterns.d.ts.map +1 -1
  151. package/dist/commands/patterns.js +14 -2
  152. package/dist/commands/patterns.js.map +1 -1
  153. package/dist/commands/refine.d.ts.map +1 -1
  154. package/dist/commands/refine.js +23 -2
  155. package/dist/commands/refine.js.map +1 -1
  156. package/dist/commands/reverse.d.ts.map +1 -1
  157. package/dist/commands/reverse.js +28 -3
  158. package/dist/commands/reverse.js.map +1 -1
  159. package/dist/commands/review.d.ts.map +1 -1
  160. package/dist/commands/review.js +25 -3
  161. package/dist/commands/review.js.map +1 -1
  162. package/dist/core/types/project.d.ts +1 -1
  163. package/dist/core/types/project.d.ts.map +1 -1
  164. package/dist/dag-runner/run_dag.d.ts +1 -1
  165. package/dist/dag-runner/run_dag.d.ts.map +1 -1
  166. package/dist/exec/safe-spawn.d.ts.map +1 -1
  167. package/dist/exec/safe-spawn.js +6 -1
  168. package/dist/exec/safe-spawn.js.map +1 -1
  169. package/dist/skills/bundled.d.ts +5 -0
  170. package/dist/skills/bundled.d.ts.map +1 -0
  171. package/dist/skills/bundled.js +34 -0
  172. package/dist/skills/bundled.js.map +1 -0
  173. package/dist/skills/commands/add.d.ts +1 -3
  174. package/dist/skills/commands/add.d.ts.map +1 -1
  175. package/dist/skills/commands/add.js +20 -3
  176. package/dist/skills/commands/add.js.map +1 -1
  177. package/dist/skills/tests/bundled.spec.d.ts +2 -0
  178. package/dist/skills/tests/bundled.spec.d.ts.map +1 -0
  179. package/dist/skills/tests/bundled.spec.js +24 -0
  180. package/dist/skills/tests/bundled.spec.js.map +1 -0
  181. package/dist/types/UpdateManifest.types.d.ts +1 -1
  182. package/dist/types/UpdateManifest.types.d.ts.map +1 -1
  183. package/dist/utils/dag-converter.js +1 -1
  184. package/dist/utils/dag-converter.js.map +1 -1
  185. package/dist/utils/project-detector.d.ts +1 -0
  186. package/dist/utils/project-detector.d.ts.map +1 -1
  187. package/dist/utils/project-detector.js +8 -0
  188. package/dist/utils/project-detector.js.map +1 -1
  189. package/dist/utils/project-generator.d.ts +1 -1
  190. package/dist/utils/project-generator.d.ts.map +1 -1
  191. package/dist/utils/project-generator.js +23 -2
  192. package/dist/utils/project-generator.js.map +1 -1
  193. package/dist/utils/templates.d.ts +2 -0
  194. package/dist/utils/templates.d.ts.map +1 -1
  195. package/dist/utils/templates.js +74 -0
  196. package/dist/utils/templates.js.map +1 -1
  197. package/dist/verification/__tests__/safe-spawn.test.js +12 -0
  198. package/dist/verification/__tests__/safe-spawn.test.js.map +1 -1
  199. package/package.json +2 -1
  200. package/skills/dare-ax/generator.ts +325 -0
  201. package/skills/dare-ax/index.ts +19 -0
  202. package/skills/dare-ax/metrics.ts +352 -0
  203. package/skills/dare-ax/package-lock.json +1855 -0
  204. package/skills/dare-ax/package.json +50 -0
  205. package/skills/dare-ax/secret-detector.ts +123 -0
  206. package/skills/dare-ax/skill.yml +19 -0
  207. package/skills/dare-ax/templates/llms.txt.jinja2 +80 -0
  208. package/skills/dare-ax/tests/generator.spec.ts +193 -0
  209. package/skills/dare-ax/tests/metrics.spec.ts +394 -0
  210. package/skills/dare-ax/tests/validator.spec.ts +298 -0
  211. package/skills/dare-ax/tsconfig.json +18 -0
  212. package/skills/dare-ax/types.ts +79 -0
  213. package/skills/dare-ax/validator.ts +238 -0
  214. package/skills/dare-frontend-design/generator.ts +616 -0
  215. package/skills/dare-frontend-design/index.ts +25 -0
  216. package/skills/dare-frontend-design/linter.ts +227 -0
  217. package/skills/dare-frontend-design/metrics.ts +82 -0
  218. package/skills/dare-frontend-design/package-lock.json +1855 -0
  219. package/skills/dare-frontend-design/package.json +43 -0
  220. package/skills/dare-frontend-design/skill.yml +20 -0
  221. package/skills/dare-frontend-design/tests/frontend_design.spec.ts +435 -0
  222. package/skills/dare-frontend-design/tsconfig.json +18 -0
  223. package/skills/dare-frontend-design/types.ts +62 -0
  224. package/skills/dare-layered-design/generator.ts +740 -0
  225. package/skills/dare-layered-design/index.ts +17 -0
  226. package/skills/dare-layered-design/linter.ts +462 -0
  227. package/skills/dare-layered-design/metrics.ts +409 -0
  228. package/skills/dare-layered-design/package-lock.json +1855 -0
  229. package/skills/dare-layered-design/package.json +50 -0
  230. package/skills/dare-layered-design/skill.yml +35 -0
  231. package/skills/dare-layered-design/tests/generator.spec.ts +156 -0
  232. package/skills/dare-layered-design/tests/linter.spec.ts +255 -0
  233. package/skills/dare-layered-design/tests/metrics.spec.ts +286 -0
  234. package/skills/dare-layered-design/tsconfig.json +18 -0
  235. package/skills/dare-layered-design/types.ts +48 -0
  236. package/skills/dare-llm-integration/cache/llm_cache.ts +122 -0
  237. package/skills/dare-llm-integration/index.ts +49 -0
  238. package/skills/dare-llm-integration/metrics.ts +107 -0
  239. package/skills/dare-llm-integration/package-lock.json +1855 -0
  240. package/skills/dare-llm-integration/package.json +49 -0
  241. package/skills/dare-llm-integration/prompts/prompt_loader.ts +258 -0
  242. package/skills/dare-llm-integration/providers/anthropic_provider.ts +159 -0
  243. package/skills/dare-llm-integration/providers/dummy_provider.ts +113 -0
  244. package/skills/dare-llm-integration/providers/llm_provider.ts +6 -0
  245. package/skills/dare-llm-integration/providers/openai_provider.ts +215 -0
  246. package/skills/dare-llm-integration/rate_limit/token_bucket.ts +86 -0
  247. package/skills/dare-llm-integration/skill.yml +23 -0
  248. package/skills/dare-llm-integration/tests/fixtures/greet_v1.jinja2 +1 -0
  249. package/skills/dare-llm-integration/tests/fixtures/summarize_v1.jinja2 +1 -0
  250. package/skills/dare-llm-integration/tests/fixtures/summarize_v2.jinja2 +3 -0
  251. package/skills/dare-llm-integration/tests/llm_integration.spec.ts +657 -0
  252. package/skills/dare-llm-integration/tsconfig.json +23 -0
  253. package/skills/dare-llm-integration/types.ts +91 -0
  254. package/skills/dare-llm-integration/validators/output_validator.ts +200 -0
  255. package/skills/dare-quality-telemetry/collect.ts +134 -0
  256. package/skills/dare-quality-telemetry/collectors/dare_ax_collector.ts +301 -0
  257. package/skills/dare-quality-telemetry/collectors/dare_layered_design_collector.ts +406 -0
  258. package/skills/dare-quality-telemetry/collectors/index.ts +24 -0
  259. package/skills/dare-quality-telemetry/github_actions_template.ts +25 -0
  260. package/skills/dare-quality-telemetry/index.ts +18 -0
  261. package/skills/dare-quality-telemetry/metrics.ts +137 -0
  262. package/skills/dare-quality-telemetry/package-lock.json +1855 -0
  263. package/skills/dare-quality-telemetry/package.json +48 -0
  264. package/skills/dare-quality-telemetry/regression.ts +60 -0
  265. package/skills/dare-quality-telemetry/reporter.ts +132 -0
  266. package/skills/dare-quality-telemetry/skill.yml +18 -0
  267. package/skills/dare-quality-telemetry/tests/quality_telemetry.spec.ts +885 -0
  268. package/skills/dare-quality-telemetry/tsconfig.json +19 -0
  269. package/skills/dare-quality-telemetry/types.ts +41 -0
  270. package/skills/dare-realtime/event_registry.ts +101 -0
  271. package/skills/dare-realtime/index.ts +30 -0
  272. package/skills/dare-realtime/metrics.ts +84 -0
  273. package/skills/dare-realtime/package-lock.json +1855 -0
  274. package/skills/dare-realtime/package.json +43 -0
  275. package/skills/dare-realtime/reconnect_strategy.ts +85 -0
  276. package/skills/dare-realtime/schema_validator.ts +80 -0
  277. package/skills/dare-realtime/skill.yml +21 -0
  278. package/skills/dare-realtime/subscription_manager.ts +106 -0
  279. package/skills/dare-realtime/tests/realtime.spec.ts +482 -0
  280. package/skills/dare-realtime/tsconfig.json +18 -0
  281. package/skills/dare-realtime/types.ts +51 -0
  282. package/templates/ide/antigravity/.agents/skills/dare-ai/SKILL.md +17 -0
  283. package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +2 -0
  284. package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +2 -0
  285. package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +3 -0
  286. package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +3 -0
  287. package/templates/ide/antigravity/.agents/skills/dare-patterns/SKILL.md +3 -0
  288. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +3 -0
  289. package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +3 -0
  290. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +3 -0
  291. package/templates/ide/claude/.claude/commands/dare-ai.md +17 -0
  292. package/templates/ide/claude/.claude/commands/dare-blueprint.md +2 -0
  293. package/templates/ide/claude/.claude/commands/dare-design.md +2 -0
  294. package/templates/ide/claude/.claude/commands/dare-dna.md +2 -0
  295. package/templates/ide/claude/.claude/commands/dare-migrate.md +2 -0
  296. package/templates/ide/claude/.claude/commands/dare-patterns.md +3 -0
  297. package/templates/ide/claude/.claude/commands/dare-refine.md +3 -0
  298. package/templates/ide/claude/.claude/commands/dare-reverse.md +2 -0
  299. package/templates/ide/claude/.claude/commands/dare-review.md +3 -0
  300. package/templates/ide/cursor/.cursor/commands/dare-ai.md +17 -0
  301. package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +3 -0
  302. package/templates/ide/cursor/.cursor/commands/dare-design.md +3 -0
  303. package/templates/ide/cursor/.cursor/commands/dare-dna.md +2 -0
  304. package/templates/ide/cursor/.cursor/commands/dare-migrate.md +2 -0
  305. package/templates/ide/cursor/.cursor/commands/dare-patterns.md +3 -0
  306. package/templates/ide/cursor/.cursor/commands/dare-refine.md +3 -0
  307. package/templates/ide/cursor/.cursor/commands/dare-reverse.md +2 -0
  308. package/templates/ide/cursor/.cursor/commands/dare-review.md +3 -0
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@dewtech/dare-ax",
3
+ "version": "1.0.0",
4
+ "description": "dare-ax — Agent Experience (AX) 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
+ "templates",
17
+ "skill.yml"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
23
+ "lint": "eslint src --ext .ts",
24
+ "typecheck": "tsc --noEmit"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^20.19.41",
28
+ "typescript": "^5.9.3",
29
+ "vitest": "^1.6.1"
30
+ },
31
+ "keywords": [
32
+ "dare",
33
+ "dare-method",
34
+ "dare-ax",
35
+ "agent-experience",
36
+ "llms-txt",
37
+ "ai-agents",
38
+ "openapi"
39
+ ],
40
+ "author": "Dewtech Technologies",
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/dewtech-technologies/dare-method.git",
45
+ "directory": "packages/skills/dare-ax"
46
+ },
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ }
50
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * dare-ax — secret-detector
3
+ * Detects API keys, tokens, passwords, and other secrets in text content.
4
+ * License: MIT
5
+ */
6
+
7
+ export interface SecretCheckResult {
8
+ found: boolean;
9
+ pattern?: string;
10
+ line?: number;
11
+ }
12
+
13
+ /** Patterns that indicate the presence of a secret. */
14
+ const SECRET_PATTERNS: Array<{ name: string; pattern: RegExp }> = [
15
+ // Generic high-entropy secrets
16
+ { name: 'Generic API Key assignment', pattern: /(?:api[_-]?key|apikey)\s*[:=]\s*["']?[A-Za-z0-9\-_]{16,}["']?/i },
17
+ { name: 'Generic Secret assignment', pattern: /(?:secret|access[_-]?secret|client[_-]?secret)\s*[:=]\s*["']?[A-Za-z0-9\-_]{16,}["']?/i },
18
+ { name: 'Generic Token assignment', pattern: /(?:token|access[_-]?token|auth[_-]?token|bearer)\s*[:=]\s*["']?[A-Za-z0-9\-_.]{20,}["']?/i },
19
+ { name: 'Password assignment', pattern: /(?:password|passwd|pwd)\s*[:=]\s*["'][^"']{4,}["']/i },
20
+
21
+ // AWS
22
+ { name: 'AWS Access Key ID', pattern: /AKIA[0-9A-Z]{16}/ },
23
+ { name: 'AWS Secret Access Key', pattern: /[Aa][Ww][Ss][_\-\s]?[Ss][Ee][Cc][Rr][Ee][Tt]\s*[:=]\s*["']?[A-Za-z0-9+/]{40}["']?/ },
24
+
25
+ // GitHub
26
+ { name: 'GitHub Token', pattern: /gh[pousr]_[A-Za-z0-9_]{36,}/ },
27
+ { name: 'GitHub Fine-grained Token', pattern: /github_pat_[A-Za-z0-9_]{82}/ },
28
+
29
+ // Stripe
30
+ { name: 'Stripe Secret Key', pattern: /sk_(live|test)_[A-Za-z0-9]{24,}/ },
31
+
32
+ // Google
33
+ { name: 'Google API Key', pattern: /AIza[0-9A-Za-z_\-]{35}/ },
34
+ { name: 'Google OAuth Token', pattern: /ya29\.[0-9A-Za-z_\-]{68,}/ },
35
+
36
+ // Anthropic
37
+ { name: 'Anthropic API Key', pattern: /sk-ant-[A-Za-z0-9\-]{40,}/ },
38
+
39
+ // OpenAI
40
+ { name: 'OpenAI API Key', pattern: /sk-[A-Za-z0-9]{48}/ },
41
+
42
+ // Slack
43
+ { name: 'Slack Bot Token', pattern: /xoxb-[0-9]{11}-[0-9]{11}-[0-9A-Za-z]{24}/ },
44
+ { name: 'Slack User Token', pattern: /xoxp-[0-9]{11}-[0-9]{11}-[0-9A-Za-z]{24}/ },
45
+
46
+ // Generic PEM private key header
47
+ { name: 'Private Key', pattern: /-----BEGIN\s+(RSA|EC|OPENSSH|DSA)?\s*PRIVATE KEY-----/ },
48
+
49
+ // Database connection strings with credentials
50
+ {
51
+ name: 'Database URL with credentials',
52
+ pattern: /(?:postgres|postgresql|mysql|mongodb|redis):\/\/[^:]+:[^@]+@/i,
53
+ },
54
+ ];
55
+
56
+ /**
57
+ * Checks a text string for secrets.
58
+ * Returns found=true and the pattern name if any secret is detected.
59
+ */
60
+ export function containsSecrets(content: string): SecretCheckResult {
61
+ const lines = content.split('\n');
62
+
63
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
64
+ const line = lines[lineIndex];
65
+
66
+ // Skip comments and template placeholders
67
+ if (line.trim().startsWith('#') && !line.includes('=') && !line.includes(':')) {
68
+ continue;
69
+ }
70
+
71
+ // Skip Jinja2 template placeholders like {{ variable }}
72
+ if (/\{\{.*?\}\}/.test(line)) {
73
+ continue;
74
+ }
75
+
76
+ for (const { name, pattern } of SECRET_PATTERNS) {
77
+ if (pattern.test(line)) {
78
+ return {
79
+ found: true,
80
+ pattern: name,
81
+ line: lineIndex + 1,
82
+ };
83
+ }
84
+ }
85
+ }
86
+
87
+ return { found: false };
88
+ }
89
+
90
+ /**
91
+ * Returns all secret matches found in content, not just the first one.
92
+ * Useful for detailed reporting.
93
+ */
94
+ export function findAllSecrets(
95
+ content: string
96
+ ): Array<{ pattern: string; line: number; lineContent: string }> {
97
+ const results: Array<{ pattern: string; line: number; lineContent: string }> = [];
98
+ const lines = content.split('\n');
99
+
100
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
101
+ const line = lines[lineIndex];
102
+
103
+ if (line.trim().startsWith('#') && !line.includes('=') && !line.includes(':')) {
104
+ continue;
105
+ }
106
+
107
+ if (/\{\{.*?\}\}/.test(line)) {
108
+ continue;
109
+ }
110
+
111
+ for (const { name, pattern } of SECRET_PATTERNS) {
112
+ if (pattern.test(line)) {
113
+ results.push({
114
+ pattern: name,
115
+ line: lineIndex + 1,
116
+ lineContent: line.trim(),
117
+ });
118
+ }
119
+ }
120
+ }
121
+
122
+ return results;
123
+ }
@@ -0,0 +1,19 @@
1
+ name: dare-ax
2
+ version: 1.0.0
3
+ description: >
4
+ Agent Experience (AX) skill — codifies best practices for AI-assisted development
5
+ in three planes: Discovery, Usage, and Defense. Ensures projects expose structured
6
+ signals (llms.txt, OpenAPI, --json CLI, rate limits) that code agents need to work
7
+ correctly without unnecessary refactoring.
8
+ author: Dewtech Technologies
9
+ license: MIT
10
+ dependencies: {}
11
+ metrics:
12
+ - id: M-01
13
+ description: llms.txt exists and is valid (no secrets, required sections present)
14
+ - id: M-02
15
+ description: public/openapi.json or openapi.json exists
16
+ - id: M-03
17
+ description: CLI supports --json flag
18
+ - id: M-04
19
+ description: Rate limit configuration is present (rack-attack, express-rate-limit, tower-governor, etc.)
@@ -0,0 +1,80 @@
1
+ # llms.txt — Project Context for AI Agents
2
+ # Generated by dare-ax v1.0.0 — DO NOT add secrets to this file
3
+
4
+ ## Project Overview
5
+ {{ project_overview }}
6
+
7
+ ## Tech Stack
8
+ - Language: {{ language }}
9
+ - Framework: {{ framework }}
10
+ - Database: {{ database }}
11
+ - Key Dependencies:
12
+ {% for dep in key_dependencies %}
13
+ - {{ dep }}
14
+ {% endfor %}
15
+
16
+ ## Architecture
17
+ {{ architecture_description }}
18
+
19
+ ## Directory Structure
20
+ ```
21
+ {{ directory_structure }}
22
+ ```
23
+
24
+ ## Key Endpoints
25
+ {% if endpoints %}
26
+ {% for endpoint in endpoints %}
27
+ - {{ endpoint.method }} {{ endpoint.path }}{% if endpoint.description %} — {{ endpoint.description }}{% endif %}
28
+
29
+ {% endfor %}
30
+ {% else %}
31
+ - See OpenAPI spec: GET /openapi.json
32
+ {% endif %}
33
+
34
+ ## Important Files
35
+ - `{{ config_file }}` — application configuration
36
+ {% if has_docker %}
37
+ - `docker-compose.yml` — local dev environment
38
+ {% endif %}
39
+ {% if has_makefile %}
40
+ - `Makefile` — common commands (make dev, make test, make build)
41
+ {% endif %}
42
+ {% if has_taskfile %}
43
+ - `tasks.json` or `Taskfile.yml` — common commands
44
+ {% endif %}
45
+
46
+ ## Getting Started
47
+ ```bash
48
+ {{ getting_started_command }}
49
+ ```
50
+
51
+ ## Rate Limits
52
+ {% if rate_limits %}
53
+ {% for limit in rate_limits %}
54
+ - {{ limit.scope }}: {{ limit.limit }} req/min per IP
55
+ {% endfor %}
56
+ {% else %}
57
+ - Public endpoints: 100 req/min per IP
58
+ - Auth endpoints: 10 req/min per IP
59
+ {% endif %}
60
+
61
+ ## Security Notes
62
+ - All user input validated in handlers
63
+ - SQL queries use parameterized queries
64
+ - Environment variables: see `.env.example`
65
+ {% if extra_security_notes %}
66
+ {% for note in extra_security_notes %}
67
+ - {{ note }}
68
+ {% endfor %}
69
+ {% endif %}
70
+
71
+ ## For AI Agents
72
+ - OpenAPI: `GET /openapi.json`
73
+ - CLI: `{{ cli_binary }} --help`, `{{ cli_binary }} --json`
74
+ - No secrets in this file or in any `llms.txt`
75
+ - Architecture: Handler → Service → Repository → Model (no direct Handler→Repository calls)
76
+ {% if agent_notes %}
77
+ {% for note in agent_notes %}
78
+ - {{ note }}
79
+ {% endfor %}
80
+ {% endif %}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * dare-ax — generator tests
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import fs from 'fs';
7
+ import os from 'os';
8
+ import path from 'path';
9
+ import { DareAxGenerator } from '../generator.js';
10
+ import { ProjectConfig } from '../types.js';
11
+
12
+ const MINIMAL_CONFIG: ProjectConfig = {
13
+ name: 'test-project',
14
+ projectOverview: 'A test project for dare-ax generator tests.',
15
+ language: 'TypeScript',
16
+ framework: 'NestJS',
17
+ database: 'Postgres',
18
+ keyDependencies: ['nestjs', 'typeorm', 'pg', 'class-validator', 'rxjs'],
19
+ architectureDescription:
20
+ 'Layered architecture: Handlers → Services → Repositories → Models. ' +
21
+ 'HTTP handlers in controllers, business logic in services, DB access in repositories.',
22
+ };
23
+
24
+ describe('DareAxGenerator', () => {
25
+ let tmpDir: string;
26
+ let generator: DareAxGenerator;
27
+
28
+ beforeEach(() => {
29
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dare-ax-test-'));
30
+ generator = new DareAxGenerator();
31
+ });
32
+
33
+ afterEach(() => {
34
+ fs.rmSync(tmpDir, { recursive: true, force: true });
35
+ });
36
+
37
+ describe('generateLlmsTxt', () => {
38
+ it('creates llms.txt at project root', () => {
39
+ const outputPath = generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
40
+
41
+ expect(fs.existsSync(outputPath)).toBe(true);
42
+ expect(outputPath).toBe(path.join(tmpDir, 'llms.txt'));
43
+ });
44
+
45
+ it('generated file contains required sections', () => {
46
+ generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
47
+
48
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
49
+
50
+ expect(content).toContain('## Project Overview');
51
+ expect(content).toContain('## Tech Stack');
52
+ expect(content).toContain('## Architecture');
53
+ expect(content).toContain('## Key Endpoints');
54
+ expect(content).toContain('## For AI Agents');
55
+ });
56
+
57
+ it('inserts project overview text', () => {
58
+ generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
59
+
60
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
61
+ expect(content).toContain('A test project for dare-ax generator tests.');
62
+ });
63
+
64
+ it('inserts tech stack fields', () => {
65
+ generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
66
+
67
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
68
+ expect(content).toContain('Language: TypeScript');
69
+ expect(content).toContain('Framework: NestJS');
70
+ expect(content).toContain('Database: Postgres');
71
+ });
72
+
73
+ it('lists key dependencies', () => {
74
+ generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
75
+
76
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
77
+ expect(content).toContain('nestjs');
78
+ expect(content).toContain('typeorm');
79
+ expect(content).toContain('pg');
80
+ });
81
+
82
+ it('uses custom cli binary name', () => {
83
+ const config: ProjectConfig = { ...MINIMAL_CONFIG, cliBinary: 'my-cli' };
84
+ generator.generateLlmsTxt(tmpDir, config);
85
+
86
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
87
+ expect(content).toContain('my-cli --help');
88
+ expect(content).toContain('my-cli --json');
89
+ });
90
+
91
+ it('uses project name as cli binary by default', () => {
92
+ generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
93
+
94
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
95
+ expect(content).toContain('test-project --help');
96
+ });
97
+
98
+ it('includes custom rate limits when specified', () => {
99
+ const config: ProjectConfig = {
100
+ ...MINIMAL_CONFIG,
101
+ rateLimits: [
102
+ { scope: 'Public API', limit: 60 },
103
+ { scope: 'Admin API', limit: 20 },
104
+ ],
105
+ };
106
+ generator.generateLlmsTxt(tmpDir, config);
107
+
108
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
109
+ expect(content).toContain('Public API');
110
+ expect(content).toContain('60 req/min');
111
+ expect(content).toContain('Admin API');
112
+ expect(content).toContain('20 req/min');
113
+ });
114
+
115
+ it('includes default rate limits when none specified', () => {
116
+ generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
117
+
118
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
119
+ expect(content).toContain('100 req/min');
120
+ expect(content).toContain('10 req/min');
121
+ });
122
+
123
+ it('renders endpoints section when endpoints provided', () => {
124
+ const config: ProjectConfig = {
125
+ ...MINIMAL_CONFIG,
126
+ endpoints: [
127
+ { method: 'GET', path: '/api/v1/users', description: 'List users' },
128
+ { method: 'POST', path: '/api/v1/users', description: 'Create user' },
129
+ ],
130
+ };
131
+ generator.generateLlmsTxt(tmpDir, config);
132
+
133
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
134
+ expect(content).toContain('GET /api/v1/users');
135
+ expect(content).toContain('POST /api/v1/users');
136
+ expect(content).toContain('List users');
137
+ });
138
+
139
+ it('throws when secret detected in generated content', () => {
140
+ // Inject a fake AWS key into the project overview
141
+ const evilConfig: ProjectConfig = {
142
+ ...MINIMAL_CONFIG,
143
+ projectOverview: 'Project with key ' + 'AKIA' + 'IOSFODNN7EXAMPLE embedded.',
144
+ };
145
+
146
+ expect(() => generator.generateLlmsTxt(tmpDir, evilConfig)).toThrow(
147
+ /Secret detected/
148
+ );
149
+
150
+ // File should NOT have been written
151
+ expect(fs.existsSync(path.join(tmpDir, 'llms.txt'))).toBe(false);
152
+ });
153
+
154
+ it('throws when axNotApplicable is true', () => {
155
+ const config: ProjectConfig = { ...MINIMAL_CONFIG, axNotApplicable: true };
156
+
157
+ expect(() => generator.generateLlmsTxt(tmpDir, config)).toThrow(
158
+ /ax: not-applicable/
159
+ );
160
+ });
161
+
162
+ it('overwrites existing llms.txt on re-run', () => {
163
+ generator.generateLlmsTxt(tmpDir, MINIMAL_CONFIG);
164
+
165
+ const updated: ProjectConfig = {
166
+ ...MINIMAL_CONFIG,
167
+ projectOverview: 'Updated description after second run.',
168
+ };
169
+ generator.generateLlmsTxt(tmpDir, updated);
170
+
171
+ const content = fs.readFileSync(path.join(tmpDir, 'llms.txt'), 'utf-8');
172
+ expect(content).toContain('Updated description after second run.');
173
+ expect(content).not.toContain('A test project for dare-ax generator tests.');
174
+ });
175
+ });
176
+
177
+ describe('renderLlmsTxt', () => {
178
+ it('returns rendered content without writing to disk', () => {
179
+ const content = generator.renderLlmsTxt(MINIMAL_CONFIG);
180
+
181
+ expect(typeof content).toBe('string');
182
+ expect(content).toContain('## Project Overview');
183
+ expect(content).toContain('## For AI Agents');
184
+ expect(fs.readdirSync(tmpDir)).toHaveLength(0);
185
+ });
186
+
187
+ it('throws when axNotApplicable is true', () => {
188
+ const config: ProjectConfig = { ...MINIMAL_CONFIG, axNotApplicable: true };
189
+
190
+ expect(() => generator.renderLlmsTxt(config)).toThrow(/ax: not-applicable/);
191
+ });
192
+ });
193
+ });