compact-agent 1.1.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 (324) hide show
  1. package/README.md +394 -0
  2. package/bin/anycode.js +2 -0
  3. package/bin/crowcoder.js +19 -0
  4. package/bin/ecc-hooks.cjs +138 -0
  5. package/dist/agents.d.ts +17 -0
  6. package/dist/agents.js +1603 -0
  7. package/dist/agents.js.map +1 -0
  8. package/dist/api.d.ts +16 -0
  9. package/dist/api.js +115 -0
  10. package/dist/api.js.map +1 -0
  11. package/dist/autonomous-loops.d.ts +108 -0
  12. package/dist/autonomous-loops.js +526 -0
  13. package/dist/autonomous-loops.js.map +1 -0
  14. package/dist/codemaps.d.ts +53 -0
  15. package/dist/codemaps.js +325 -0
  16. package/dist/codemaps.js.map +1 -0
  17. package/dist/compaction.d.ts +30 -0
  18. package/dist/compaction.js +125 -0
  19. package/dist/compaction.js.map +1 -0
  20. package/dist/config.d.ts +5 -0
  21. package/dist/config.js +79 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/content-engine.d.ts +97 -0
  24. package/dist/content-engine.js +721 -0
  25. package/dist/content-engine.js.map +1 -0
  26. package/dist/cost-tracker.d.ts +49 -0
  27. package/dist/cost-tracker.js +150 -0
  28. package/dist/cost-tracker.js.map +1 -0
  29. package/dist/counter-button.d.ts +35 -0
  30. package/dist/counter-button.js +48 -0
  31. package/dist/counter-button.js.map +1 -0
  32. package/dist/counter.d.ts +21 -0
  33. package/dist/counter.js +31 -0
  34. package/dist/counter.js.map +1 -0
  35. package/dist/coverage.d.ts +23 -0
  36. package/dist/coverage.js +215 -0
  37. package/dist/coverage.js.map +1 -0
  38. package/dist/docs-sync.d.ts +23 -0
  39. package/dist/docs-sync.js +266 -0
  40. package/dist/docs-sync.js.map +1 -0
  41. package/dist/ecc.d.ts +41 -0
  42. package/dist/ecc.js +644 -0
  43. package/dist/ecc.js.map +1 -0
  44. package/dist/evaluation.d.ts +24 -0
  45. package/dist/evaluation.js +412 -0
  46. package/dist/evaluation.js.map +1 -0
  47. package/dist/export.d.ts +22 -0
  48. package/dist/export.js +109 -0
  49. package/dist/export.js.map +1 -0
  50. package/dist/git-workflow.d.ts +22 -0
  51. package/dist/git-workflow.js +197 -0
  52. package/dist/git-workflow.js.map +1 -0
  53. package/dist/hook-controls.d.ts +34 -0
  54. package/dist/hook-controls.js +90 -0
  55. package/dist/hook-controls.js.map +1 -0
  56. package/dist/hooks.d.ts +30 -0
  57. package/dist/hooks.js +130 -0
  58. package/dist/hooks.js.map +1 -0
  59. package/dist/html-parser.d.ts +18 -0
  60. package/dist/html-parser.js +101 -0
  61. package/dist/html-parser.js.map +1 -0
  62. package/dist/index.d.ts +12 -0
  63. package/dist/index.js +1230 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/learning.d.ts +35 -0
  66. package/dist/learning.js +238 -0
  67. package/dist/learning.js.map +1 -0
  68. package/dist/login.d.ts +37 -0
  69. package/dist/login.js +191 -0
  70. package/dist/login.js.map +1 -0
  71. package/dist/memory.d.ts +39 -0
  72. package/dist/memory.js +183 -0
  73. package/dist/memory.js.map +1 -0
  74. package/dist/model-router.d.ts +23 -0
  75. package/dist/model-router.js +145 -0
  76. package/dist/model-router.js.map +1 -0
  77. package/dist/modes.d.ts +17 -0
  78. package/dist/modes.js +217 -0
  79. package/dist/modes.js.map +1 -0
  80. package/dist/orchestration.d.ts +37 -0
  81. package/dist/orchestration.js +139 -0
  82. package/dist/orchestration.js.map +1 -0
  83. package/dist/package-detect.d.ts +36 -0
  84. package/dist/package-detect.js +529 -0
  85. package/dist/package-detect.js.map +1 -0
  86. package/dist/permissions.d.ts +25 -0
  87. package/dist/permissions.js +50 -0
  88. package/dist/permissions.js.map +1 -0
  89. package/dist/pm2-manager.d.ts +40 -0
  90. package/dist/pm2-manager.js +127 -0
  91. package/dist/pm2-manager.js.map +1 -0
  92. package/dist/query.d.ts +15 -0
  93. package/dist/query.js +278 -0
  94. package/dist/query.js.map +1 -0
  95. package/dist/refactor.d.ts +22 -0
  96. package/dist/refactor.js +226 -0
  97. package/dist/refactor.js.map +1 -0
  98. package/dist/retry.d.ts +20 -0
  99. package/dist/retry.js +88 -0
  100. package/dist/retry.js.map +1 -0
  101. package/dist/rules.d.ts +34 -0
  102. package/dist/rules.js +942 -0
  103. package/dist/rules.js.map +1 -0
  104. package/dist/schema.d.ts +23 -0
  105. package/dist/schema.js +12 -0
  106. package/dist/schema.js.map +1 -0
  107. package/dist/search-first.d.ts +17 -0
  108. package/dist/search-first.js +301 -0
  109. package/dist/search-first.js.map +1 -0
  110. package/dist/security.d.ts +10 -0
  111. package/dist/security.js +145 -0
  112. package/dist/security.js.map +1 -0
  113. package/dist/sessions.d.ts +21 -0
  114. package/dist/sessions.js +112 -0
  115. package/dist/sessions.js.map +1 -0
  116. package/dist/skill-create.d.ts +38 -0
  117. package/dist/skill-create.js +389 -0
  118. package/dist/skill-create.js.map +1 -0
  119. package/dist/skills.d.ts +34 -0
  120. package/dist/skills.js +161 -0
  121. package/dist/skills.js.map +1 -0
  122. package/dist/strategic-compaction.d.ts +24 -0
  123. package/dist/strategic-compaction.js +144 -0
  124. package/dist/strategic-compaction.js.map +1 -0
  125. package/dist/system-prompt.d.ts +3 -0
  126. package/dist/system-prompt.js +101 -0
  127. package/dist/system-prompt.js.map +1 -0
  128. package/dist/theme.d.ts +60 -0
  129. package/dist/theme.js +220 -0
  130. package/dist/theme.js.map +1 -0
  131. package/dist/tools/bash.d.ts +2 -0
  132. package/dist/tools/bash.js +49 -0
  133. package/dist/tools/bash.js.map +1 -0
  134. package/dist/tools/edit.d.ts +2 -0
  135. package/dist/tools/edit.js +76 -0
  136. package/dist/tools/edit.js.map +1 -0
  137. package/dist/tools/glob.d.ts +2 -0
  138. package/dist/tools/glob.js +54 -0
  139. package/dist/tools/glob.js.map +1 -0
  140. package/dist/tools/grep.d.ts +2 -0
  141. package/dist/tools/grep.js +64 -0
  142. package/dist/tools/grep.js.map +1 -0
  143. package/dist/tools/index.d.ts +5 -0
  144. package/dist/tools/index.js +27 -0
  145. package/dist/tools/index.js.map +1 -0
  146. package/dist/tools/list-dir.d.ts +2 -0
  147. package/dist/tools/list-dir.js +51 -0
  148. package/dist/tools/list-dir.js.map +1 -0
  149. package/dist/tools/read.d.ts +2 -0
  150. package/dist/tools/read.js +56 -0
  151. package/dist/tools/read.js.map +1 -0
  152. package/dist/tools/types.d.ts +45 -0
  153. package/dist/tools/types.js +2 -0
  154. package/dist/tools/types.js.map +1 -0
  155. package/dist/tools/web-fetch.d.ts +2 -0
  156. package/dist/tools/web-fetch.js +41 -0
  157. package/dist/tools/web-fetch.js.map +1 -0
  158. package/dist/tools/web-search.d.ts +27 -0
  159. package/dist/tools/web-search.js +139 -0
  160. package/dist/tools/web-search.js.map +1 -0
  161. package/dist/tools/write.d.ts +2 -0
  162. package/dist/tools/write.js +36 -0
  163. package/dist/tools/write.js.map +1 -0
  164. package/dist/types.d.ts +28 -0
  165. package/dist/types.js +57 -0
  166. package/dist/types.js.map +1 -0
  167. package/dist/users.d.ts +51 -0
  168. package/dist/users.js +193 -0
  169. package/dist/users.js.map +1 -0
  170. package/dist/verification.d.ts +73 -0
  171. package/dist/verification.js +269 -0
  172. package/dist/verification.js.map +1 -0
  173. package/dist/walkthrough.d.ts +10 -0
  174. package/dist/walkthrough.js +121 -0
  175. package/dist/walkthrough.js.map +1 -0
  176. package/package.json +58 -0
  177. package/resources/ecc/agents/architect.json +16 -0
  178. package/resources/ecc/agents/architect.md +212 -0
  179. package/resources/ecc/agents/build-error-resolver.json +17 -0
  180. package/resources/ecc/agents/build-error-resolver.md +116 -0
  181. package/resources/ecc/agents/chief-of-staff.json +17 -0
  182. package/resources/ecc/agents/chief-of-staff.md +153 -0
  183. package/resources/ecc/agents/code-reviewer.json +16 -0
  184. package/resources/ecc/agents/code-reviewer.md +238 -0
  185. package/resources/ecc/agents/database-reviewer.json +16 -0
  186. package/resources/ecc/agents/database-reviewer.md +92 -0
  187. package/resources/ecc/agents/doc-updater.json +16 -0
  188. package/resources/ecc/agents/doc-updater.md +108 -0
  189. package/resources/ecc/agents/e2e-runner.json +17 -0
  190. package/resources/ecc/agents/e2e-runner.md +109 -0
  191. package/resources/ecc/agents/go-build-resolver.json +17 -0
  192. package/resources/ecc/agents/go-build-resolver.md +96 -0
  193. package/resources/ecc/agents/go-reviewer.json +16 -0
  194. package/resources/ecc/agents/go-reviewer.md +77 -0
  195. package/resources/ecc/agents/harness-optimizer.json +15 -0
  196. package/resources/ecc/agents/harness-optimizer.md +34 -0
  197. package/resources/ecc/agents/loop-operator.json +16 -0
  198. package/resources/ecc/agents/loop-operator.md +36 -0
  199. package/resources/ecc/agents/planner.json +15 -0
  200. package/resources/ecc/agents/planner.md +212 -0
  201. package/resources/ecc/agents/python-reviewer.json +16 -0
  202. package/resources/ecc/agents/python-reviewer.md +99 -0
  203. package/resources/ecc/agents/refactor-cleaner.json +17 -0
  204. package/resources/ecc/agents/refactor-cleaner.md +87 -0
  205. package/resources/ecc/agents/security-reviewer.json +16 -0
  206. package/resources/ecc/agents/security-reviewer.md +109 -0
  207. package/resources/ecc/agents/tdd-guide.json +17 -0
  208. package/resources/ecc/agents/tdd-guide.md +93 -0
  209. package/resources/ecc/commands/add-language-rules.md +39 -0
  210. package/resources/ecc/commands/database-migration.md +36 -0
  211. package/resources/ecc/commands/feature-development.md +38 -0
  212. package/resources/ecc/prompts/build-fix.prompt.md +47 -0
  213. package/resources/ecc/prompts/code-review.prompt.md +56 -0
  214. package/resources/ecc/prompts/plan.prompt.md +52 -0
  215. package/resources/ecc/prompts/refactor.prompt.md +50 -0
  216. package/resources/ecc/prompts/security-review.prompt.md +70 -0
  217. package/resources/ecc/prompts/tdd.prompt.md +47 -0
  218. package/resources/ecc/rules/common-agents.md +53 -0
  219. package/resources/ecc/rules/common-coding-style.md +52 -0
  220. package/resources/ecc/rules/common-development-workflow.md +33 -0
  221. package/resources/ecc/rules/common-git-workflow.md +28 -0
  222. package/resources/ecc/rules/common-hooks.md +34 -0
  223. package/resources/ecc/rules/common-patterns.md +35 -0
  224. package/resources/ecc/rules/common-performance.md +59 -0
  225. package/resources/ecc/rules/common-security.md +33 -0
  226. package/resources/ecc/rules/common-testing.md +33 -0
  227. package/resources/ecc/rules/golang-coding-style.md +31 -0
  228. package/resources/ecc/rules/golang-hooks.md +16 -0
  229. package/resources/ecc/rules/golang-patterns.md +44 -0
  230. package/resources/ecc/rules/golang-security.md +33 -0
  231. package/resources/ecc/rules/golang-testing.md +30 -0
  232. package/resources/ecc/rules/kotlin-coding-style.md +39 -0
  233. package/resources/ecc/rules/kotlin-hooks.md +16 -0
  234. package/resources/ecc/rules/kotlin-patterns.md +50 -0
  235. package/resources/ecc/rules/kotlin-security.md +58 -0
  236. package/resources/ecc/rules/kotlin-testing.md +38 -0
  237. package/resources/ecc/rules/php-coding-style.md +25 -0
  238. package/resources/ecc/rules/php-hooks.md +21 -0
  239. package/resources/ecc/rules/php-patterns.md +23 -0
  240. package/resources/ecc/rules/php-security.md +24 -0
  241. package/resources/ecc/rules/php-testing.md +26 -0
  242. package/resources/ecc/rules/python-coding-style.md +42 -0
  243. package/resources/ecc/rules/python-hooks.md +19 -0
  244. package/resources/ecc/rules/python-patterns.md +39 -0
  245. package/resources/ecc/rules/python-security.md +30 -0
  246. package/resources/ecc/rules/python-testing.md +38 -0
  247. package/resources/ecc/rules/swift-coding-style.md +47 -0
  248. package/resources/ecc/rules/swift-hooks.md +20 -0
  249. package/resources/ecc/rules/swift-patterns.md +66 -0
  250. package/resources/ecc/rules/swift-security.md +33 -0
  251. package/resources/ecc/rules/swift-testing.md +45 -0
  252. package/resources/ecc/rules/typescript-coding-style.md +63 -0
  253. package/resources/ecc/rules/typescript-hooks.md +20 -0
  254. package/resources/ecc/rules/typescript-patterns.md +50 -0
  255. package/resources/ecc/rules/typescript-security.md +26 -0
  256. package/resources/ecc/rules/typescript-testing.md +16 -0
  257. package/resources/ecc/skills/agent-introspection-debugging/SKILL.md +152 -0
  258. package/resources/ecc/skills/agent-introspection-debugging/agents/openai.yaml +7 -0
  259. package/resources/ecc/skills/agent-sort/SKILL.md +214 -0
  260. package/resources/ecc/skills/agent-sort/agents/openai.yaml +7 -0
  261. package/resources/ecc/skills/api-design/SKILL.md +522 -0
  262. package/resources/ecc/skills/api-design/agents/openai.yaml +7 -0
  263. package/resources/ecc/skills/article-writing/SKILL.md +78 -0
  264. package/resources/ecc/skills/article-writing/agents/openai.yaml +7 -0
  265. package/resources/ecc/skills/backend-patterns/SKILL.md +597 -0
  266. package/resources/ecc/skills/backend-patterns/agents/openai.yaml +7 -0
  267. package/resources/ecc/skills/brand-voice/SKILL.md +96 -0
  268. package/resources/ecc/skills/brand-voice/agents/openai.yaml +7 -0
  269. package/resources/ecc/skills/brand-voice/references/voice-profile-schema.md +55 -0
  270. package/resources/ecc/skills/bun-runtime/SKILL.md +83 -0
  271. package/resources/ecc/skills/bun-runtime/agents/openai.yaml +7 -0
  272. package/resources/ecc/skills/coding-standards/SKILL.md +548 -0
  273. package/resources/ecc/skills/coding-standards/agents/openai.yaml +7 -0
  274. package/resources/ecc/skills/content-engine/SKILL.md +130 -0
  275. package/resources/ecc/skills/content-engine/agents/openai.yaml +7 -0
  276. package/resources/ecc/skills/crosspost/SKILL.md +110 -0
  277. package/resources/ecc/skills/crosspost/agents/openai.yaml +7 -0
  278. package/resources/ecc/skills/deep-research/SKILL.md +154 -0
  279. package/resources/ecc/skills/deep-research/agents/openai.yaml +7 -0
  280. package/resources/ecc/skills/dmux-workflows/SKILL.md +143 -0
  281. package/resources/ecc/skills/dmux-workflows/agents/openai.yaml +7 -0
  282. package/resources/ecc/skills/documentation-lookup/SKILL.md +89 -0
  283. package/resources/ecc/skills/documentation-lookup/agents/openai.yaml +7 -0
  284. package/resources/ecc/skills/e2e-testing/SKILL.md +325 -0
  285. package/resources/ecc/skills/e2e-testing/agents/openai.yaml +7 -0
  286. package/resources/ecc/skills/eval-harness/SKILL.md +235 -0
  287. package/resources/ecc/skills/eval-harness/agents/openai.yaml +7 -0
  288. package/resources/ecc/skills/everything-claude-code/SKILL.md +442 -0
  289. package/resources/ecc/skills/everything-claude-code/agents/openai.yaml +7 -0
  290. package/resources/ecc/skills/exa-search/SKILL.md +169 -0
  291. package/resources/ecc/skills/exa-search/agents/openai.yaml +7 -0
  292. package/resources/ecc/skills/fal-ai-media/SKILL.md +276 -0
  293. package/resources/ecc/skills/fal-ai-media/agents/openai.yaml +7 -0
  294. package/resources/ecc/skills/frontend-patterns/SKILL.md +647 -0
  295. package/resources/ecc/skills/frontend-patterns/agents/openai.yaml +7 -0
  296. package/resources/ecc/skills/frontend-slides/SKILL.md +183 -0
  297. package/resources/ecc/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  298. package/resources/ecc/skills/frontend-slides/agents/openai.yaml +7 -0
  299. package/resources/ecc/skills/investor-materials/SKILL.md +95 -0
  300. package/resources/ecc/skills/investor-materials/agents/openai.yaml +7 -0
  301. package/resources/ecc/skills/investor-outreach/SKILL.md +90 -0
  302. package/resources/ecc/skills/investor-outreach/agents/openai.yaml +7 -0
  303. package/resources/ecc/skills/market-research/SKILL.md +74 -0
  304. package/resources/ecc/skills/market-research/agents/openai.yaml +7 -0
  305. package/resources/ecc/skills/mcp-server-patterns/SKILL.md +66 -0
  306. package/resources/ecc/skills/mcp-server-patterns/agents/openai.yaml +7 -0
  307. package/resources/ecc/skills/mle-workflow/SKILL.md +346 -0
  308. package/resources/ecc/skills/mle-workflow/agents/openai.yaml +7 -0
  309. package/resources/ecc/skills/nextjs-turbopack/SKILL.md +43 -0
  310. package/resources/ecc/skills/nextjs-turbopack/agents/openai.yaml +7 -0
  311. package/resources/ecc/skills/product-capability/SKILL.md +140 -0
  312. package/resources/ecc/skills/product-capability/agents/openai.yaml +7 -0
  313. package/resources/ecc/skills/security-review/SKILL.md +494 -0
  314. package/resources/ecc/skills/security-review/agents/openai.yaml +7 -0
  315. package/resources/ecc/skills/strategic-compact/SKILL.md +102 -0
  316. package/resources/ecc/skills/strategic-compact/agents/openai.yaml +7 -0
  317. package/resources/ecc/skills/tdd-workflow/SKILL.md +409 -0
  318. package/resources/ecc/skills/tdd-workflow/agents/openai.yaml +7 -0
  319. package/resources/ecc/skills/verification-loop/SKILL.md +125 -0
  320. package/resources/ecc/skills/verification-loop/agents/openai.yaml +7 -0
  321. package/resources/ecc/skills/video-editing/SKILL.md +307 -0
  322. package/resources/ecc/skills/video-editing/agents/openai.yaml +7 -0
  323. package/resources/ecc/skills/x-api/SKILL.md +229 -0
  324. package/resources/ecc/skills/x-api/agents/openai.yaml +7 -0
@@ -0,0 +1,597 @@
1
+ ---
2
+ name: backend-patterns
3
+ description: Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes.
4
+ ---
5
+
6
+ # Backend Development Patterns
7
+
8
+ Backend architecture patterns and best practices for scalable server-side applications.
9
+
10
+ ## When to Activate
11
+
12
+ - Designing REST or GraphQL API endpoints
13
+ - Implementing repository, service, or controller layers
14
+ - Optimizing database queries (N+1, indexing, connection pooling)
15
+ - Adding caching (Redis, in-memory, HTTP cache headers)
16
+ - Setting up background jobs or async processing
17
+ - Structuring error handling and validation for APIs
18
+ - Building middleware (auth, logging, rate limiting)
19
+
20
+ ## API Design Patterns
21
+
22
+ ### RESTful API Structure
23
+
24
+ ```typescript
25
+ // PASS: Resource-based URLs
26
+ GET /api/markets # List resources
27
+ GET /api/markets/:id # Get single resource
28
+ POST /api/markets # Create resource
29
+ PUT /api/markets/:id # Replace resource
30
+ PATCH /api/markets/:id # Update resource
31
+ DELETE /api/markets/:id # Delete resource
32
+
33
+ // PASS: Query parameters for filtering, sorting, pagination
34
+ GET /api/markets?status=active&sort=volume&limit=20&offset=0
35
+ ```
36
+
37
+ ### Repository Pattern
38
+
39
+ ```typescript
40
+ // Abstract data access logic
41
+ interface MarketRepository {
42
+ findAll(filters?: MarketFilters): Promise<Market[]>
43
+ findById(id: string): Promise<Market | null>
44
+ create(data: CreateMarketDto): Promise<Market>
45
+ update(id: string, data: UpdateMarketDto): Promise<Market>
46
+ delete(id: string): Promise<void>
47
+ }
48
+
49
+ class SupabaseMarketRepository implements MarketRepository {
50
+ async findAll(filters?: MarketFilters): Promise<Market[]> {
51
+ let query = supabase.from('markets').select('*')
52
+
53
+ if (filters?.status) {
54
+ query = query.eq('status', filters.status)
55
+ }
56
+
57
+ if (filters?.limit) {
58
+ query = query.limit(filters.limit)
59
+ }
60
+
61
+ const { data, error } = await query
62
+
63
+ if (error) throw new Error(error.message)
64
+ return data
65
+ }
66
+
67
+ // Other methods...
68
+ }
69
+ ```
70
+
71
+ ### Service Layer Pattern
72
+
73
+ ```typescript
74
+ // Business logic separated from data access
75
+ class MarketService {
76
+ constructor(private marketRepo: MarketRepository) {}
77
+
78
+ async searchMarkets(query: string, limit: number = 10): Promise<Market[]> {
79
+ // Business logic
80
+ const embedding = await generateEmbedding(query)
81
+ const results = await this.vectorSearch(embedding, limit)
82
+
83
+ // Fetch full data
84
+ const markets = await this.marketRepo.findByIds(results.map(r => r.id))
85
+
86
+ // Sort by similarity
87
+ return markets.sort((a, b) => {
88
+ const scoreA = results.find(r => r.id === a.id)?.score || 0
89
+ const scoreB = results.find(r => r.id === b.id)?.score || 0
90
+ return scoreA - scoreB
91
+ })
92
+ }
93
+
94
+ private async vectorSearch(embedding: number[], limit: number) {
95
+ // Vector search implementation
96
+ }
97
+ }
98
+ ```
99
+
100
+ ### Middleware Pattern
101
+
102
+ ```typescript
103
+ // Request/response processing pipeline
104
+ export function withAuth(handler: NextApiHandler): NextApiHandler {
105
+ return async (req, res) => {
106
+ const token = req.headers.authorization?.replace('Bearer ', '')
107
+
108
+ if (!token) {
109
+ return res.status(401).json({ error: 'Unauthorized' })
110
+ }
111
+
112
+ try {
113
+ const user = await verifyToken(token)
114
+ req.user = user
115
+ return handler(req, res)
116
+ } catch (error) {
117
+ return res.status(401).json({ error: 'Invalid token' })
118
+ }
119
+ }
120
+ }
121
+
122
+ // Usage
123
+ export default withAuth(async (req, res) => {
124
+ // Handler has access to req.user
125
+ })
126
+ ```
127
+
128
+ ## Database Patterns
129
+
130
+ ### Query Optimization
131
+
132
+ ```typescript
133
+ // PASS: GOOD: Select only needed columns
134
+ const { data } = await supabase
135
+ .from('markets')
136
+ .select('id, name, status, volume')
137
+ .eq('status', 'active')
138
+ .order('volume', { ascending: false })
139
+ .limit(10)
140
+
141
+ // FAIL: BAD: Select everything
142
+ const { data } = await supabase
143
+ .from('markets')
144
+ .select('*')
145
+ ```
146
+
147
+ ### N+1 Query Prevention
148
+
149
+ ```typescript
150
+ // FAIL: BAD: N+1 query problem
151
+ const markets = await getMarkets()
152
+ for (const market of markets) {
153
+ market.creator = await getUser(market.creator_id) // N queries
154
+ }
155
+
156
+ // PASS: GOOD: Batch fetch
157
+ const markets = await getMarkets()
158
+ const creatorIds = markets.map(m => m.creator_id)
159
+ const creators = await getUsers(creatorIds) // 1 query
160
+ const creatorMap = new Map(creators.map(c => [c.id, c]))
161
+
162
+ markets.forEach(market => {
163
+ market.creator = creatorMap.get(market.creator_id)
164
+ })
165
+ ```
166
+
167
+ ### Transaction Pattern
168
+
169
+ ```typescript
170
+ async function createMarketWithPosition(
171
+ marketData: CreateMarketDto,
172
+ positionData: CreatePositionDto
173
+ ) {
174
+ // Use Supabase transaction
175
+ const { data, error } = await supabase.rpc('create_market_with_position', {
176
+ market_data: marketData,
177
+ position_data: positionData
178
+ })
179
+
180
+ if (error) throw new Error('Transaction failed')
181
+ return data
182
+ }
183
+
184
+ // SQL function in Supabase
185
+ CREATE OR REPLACE FUNCTION create_market_with_position(
186
+ market_data jsonb,
187
+ position_data jsonb
188
+ )
189
+ RETURNS jsonb
190
+ LANGUAGE plpgsql
191
+ AS $$
192
+ BEGIN
193
+ -- Start transaction automatically
194
+ INSERT INTO markets VALUES (market_data);
195
+ INSERT INTO positions VALUES (position_data);
196
+ RETURN jsonb_build_object('success', true);
197
+ EXCEPTION
198
+ WHEN OTHERS THEN
199
+ -- Rollback happens automatically
200
+ RETURN jsonb_build_object('success', false, 'error', SQLERRM);
201
+ END;
202
+ $$;
203
+ ```
204
+
205
+ ## Caching Strategies
206
+
207
+ ### Redis Caching Layer
208
+
209
+ ```typescript
210
+ class CachedMarketRepository implements MarketRepository {
211
+ constructor(
212
+ private baseRepo: MarketRepository,
213
+ private redis: RedisClient
214
+ ) {}
215
+
216
+ async findById(id: string): Promise<Market | null> {
217
+ // Check cache first
218
+ const cached = await this.redis.get(`market:${id}`)
219
+
220
+ if (cached) {
221
+ return JSON.parse(cached)
222
+ }
223
+
224
+ // Cache miss - fetch from database
225
+ const market = await this.baseRepo.findById(id)
226
+
227
+ if (market) {
228
+ // Cache for 5 minutes
229
+ await this.redis.setex(`market:${id}`, 300, JSON.stringify(market))
230
+ }
231
+
232
+ return market
233
+ }
234
+
235
+ async invalidateCache(id: string): Promise<void> {
236
+ await this.redis.del(`market:${id}`)
237
+ }
238
+ }
239
+ ```
240
+
241
+ ### Cache-Aside Pattern
242
+
243
+ ```typescript
244
+ async function getMarketWithCache(id: string): Promise<Market> {
245
+ const cacheKey = `market:${id}`
246
+
247
+ // Try cache
248
+ const cached = await redis.get(cacheKey)
249
+ if (cached) return JSON.parse(cached)
250
+
251
+ // Cache miss - fetch from DB
252
+ const market = await db.markets.findUnique({ where: { id } })
253
+
254
+ if (!market) throw new Error('Market not found')
255
+
256
+ // Update cache
257
+ await redis.setex(cacheKey, 300, JSON.stringify(market))
258
+
259
+ return market
260
+ }
261
+ ```
262
+
263
+ ## Error Handling Patterns
264
+
265
+ ### Centralized Error Handler
266
+
267
+ ```typescript
268
+ class ApiError extends Error {
269
+ constructor(
270
+ public statusCode: number,
271
+ public message: string,
272
+ public isOperational = true
273
+ ) {
274
+ super(message)
275
+ Object.setPrototypeOf(this, ApiError.prototype)
276
+ }
277
+ }
278
+
279
+ export function errorHandler(error: unknown, req: Request): Response {
280
+ if (error instanceof ApiError) {
281
+ return NextResponse.json({
282
+ success: false,
283
+ error: error.message
284
+ }, { status: error.statusCode })
285
+ }
286
+
287
+ if (error instanceof z.ZodError) {
288
+ return NextResponse.json({
289
+ success: false,
290
+ error: 'Validation failed',
291
+ details: error.errors
292
+ }, { status: 400 })
293
+ }
294
+
295
+ // Log unexpected errors
296
+ console.error('Unexpected error:', error)
297
+
298
+ return NextResponse.json({
299
+ success: false,
300
+ error: 'Internal server error'
301
+ }, { status: 500 })
302
+ }
303
+
304
+ // Usage
305
+ export async function GET(request: Request) {
306
+ try {
307
+ const data = await fetchData()
308
+ return NextResponse.json({ success: true, data })
309
+ } catch (error) {
310
+ return errorHandler(error, request)
311
+ }
312
+ }
313
+ ```
314
+
315
+ ### Retry with Exponential Backoff
316
+
317
+ ```typescript
318
+ async function fetchWithRetry<T>(
319
+ fn: () => Promise<T>,
320
+ maxRetries = 3
321
+ ): Promise<T> {
322
+ let lastError: Error
323
+
324
+ for (let i = 0; i < maxRetries; i++) {
325
+ try {
326
+ return await fn()
327
+ } catch (error) {
328
+ lastError = error as Error
329
+
330
+ if (i < maxRetries - 1) {
331
+ // Exponential backoff: 1s, 2s, 4s
332
+ const delay = Math.pow(2, i) * 1000
333
+ await new Promise(resolve => setTimeout(resolve, delay))
334
+ }
335
+ }
336
+ }
337
+
338
+ throw lastError!
339
+ }
340
+
341
+ // Usage
342
+ const data = await fetchWithRetry(() => fetchFromAPI())
343
+ ```
344
+
345
+ ## Authentication & Authorization
346
+
347
+ ### JWT Token Validation
348
+
349
+ ```typescript
350
+ import jwt from 'jsonwebtoken'
351
+
352
+ interface JWTPayload {
353
+ userId: string
354
+ email: string
355
+ role: 'admin' | 'user'
356
+ }
357
+
358
+ export function verifyToken(token: string): JWTPayload {
359
+ try {
360
+ const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload
361
+ return payload
362
+ } catch (error) {
363
+ throw new ApiError(401, 'Invalid token')
364
+ }
365
+ }
366
+
367
+ export async function requireAuth(request: Request) {
368
+ const token = request.headers.get('authorization')?.replace('Bearer ', '')
369
+
370
+ if (!token) {
371
+ throw new ApiError(401, 'Missing authorization token')
372
+ }
373
+
374
+ return verifyToken(token)
375
+ }
376
+
377
+ // Usage in API route
378
+ export async function GET(request: Request) {
379
+ const user = await requireAuth(request)
380
+
381
+ const data = await getDataForUser(user.userId)
382
+
383
+ return NextResponse.json({ success: true, data })
384
+ }
385
+ ```
386
+
387
+ ### Role-Based Access Control
388
+
389
+ ```typescript
390
+ type Permission = 'read' | 'write' | 'delete' | 'admin'
391
+
392
+ interface User {
393
+ id: string
394
+ role: 'admin' | 'moderator' | 'user'
395
+ }
396
+
397
+ const rolePermissions: Record<User['role'], Permission[]> = {
398
+ admin: ['read', 'write', 'delete', 'admin'],
399
+ moderator: ['read', 'write', 'delete'],
400
+ user: ['read', 'write']
401
+ }
402
+
403
+ export function hasPermission(user: User, permission: Permission): boolean {
404
+ return rolePermissions[user.role].includes(permission)
405
+ }
406
+
407
+ export function requirePermission(permission: Permission) {
408
+ return (handler: (request: Request, user: User) => Promise<Response>) => {
409
+ return async (request: Request) => {
410
+ const user = await requireAuth(request)
411
+
412
+ if (!hasPermission(user, permission)) {
413
+ throw new ApiError(403, 'Insufficient permissions')
414
+ }
415
+
416
+ return handler(request, user)
417
+ }
418
+ }
419
+ }
420
+
421
+ // Usage - HOF wraps the handler
422
+ export const DELETE = requirePermission('delete')(
423
+ async (request: Request, user: User) => {
424
+ // Handler receives authenticated user with verified permission
425
+ return new Response('Deleted', { status: 200 })
426
+ }
427
+ )
428
+ ```
429
+
430
+ ## Rate Limiting
431
+
432
+ ### Simple In-Memory Rate Limiter
433
+
434
+ ```typescript
435
+ class RateLimiter {
436
+ private requests = new Map<string, number[]>()
437
+
438
+ async checkLimit(
439
+ identifier: string,
440
+ maxRequests: number,
441
+ windowMs: number
442
+ ): Promise<boolean> {
443
+ const now = Date.now()
444
+ const requests = this.requests.get(identifier) || []
445
+
446
+ // Remove old requests outside window
447
+ const recentRequests = requests.filter(time => now - time < windowMs)
448
+
449
+ if (recentRequests.length >= maxRequests) {
450
+ return false // Rate limit exceeded
451
+ }
452
+
453
+ // Add current request
454
+ recentRequests.push(now)
455
+ this.requests.set(identifier, recentRequests)
456
+
457
+ return true
458
+ }
459
+ }
460
+
461
+ const limiter = new RateLimiter()
462
+
463
+ export async function GET(request: Request) {
464
+ const ip = request.headers.get('x-forwarded-for') || 'unknown'
465
+
466
+ const allowed = await limiter.checkLimit(ip, 100, 60000) // 100 req/min
467
+
468
+ if (!allowed) {
469
+ return NextResponse.json({
470
+ error: 'Rate limit exceeded'
471
+ }, { status: 429 })
472
+ }
473
+
474
+ // Continue with request
475
+ }
476
+ ```
477
+
478
+ ## Background Jobs & Queues
479
+
480
+ ### Simple Queue Pattern
481
+
482
+ ```typescript
483
+ class JobQueue<T> {
484
+ private queue: T[] = []
485
+ private processing = false
486
+
487
+ async add(job: T): Promise<void> {
488
+ this.queue.push(job)
489
+
490
+ if (!this.processing) {
491
+ this.process()
492
+ }
493
+ }
494
+
495
+ private async process(): Promise<void> {
496
+ this.processing = true
497
+
498
+ while (this.queue.length > 0) {
499
+ const job = this.queue.shift()!
500
+
501
+ try {
502
+ await this.execute(job)
503
+ } catch (error) {
504
+ console.error('Job failed:', error)
505
+ }
506
+ }
507
+
508
+ this.processing = false
509
+ }
510
+
511
+ private async execute(job: T): Promise<void> {
512
+ // Job execution logic
513
+ }
514
+ }
515
+
516
+ // Usage for indexing markets
517
+ interface IndexJob {
518
+ marketId: string
519
+ }
520
+
521
+ const indexQueue = new JobQueue<IndexJob>()
522
+
523
+ export async function POST(request: Request) {
524
+ const { marketId } = await request.json()
525
+
526
+ // Add to queue instead of blocking
527
+ await indexQueue.add({ marketId })
528
+
529
+ return NextResponse.json({ success: true, message: 'Job queued' })
530
+ }
531
+ ```
532
+
533
+ ## Logging & Monitoring
534
+
535
+ ### Structured Logging
536
+
537
+ ```typescript
538
+ interface LogContext {
539
+ userId?: string
540
+ requestId?: string
541
+ method?: string
542
+ path?: string
543
+ [key: string]: unknown
544
+ }
545
+
546
+ class Logger {
547
+ log(level: 'info' | 'warn' | 'error', message: string, context?: LogContext) {
548
+ const entry = {
549
+ timestamp: new Date().toISOString(),
550
+ level,
551
+ message,
552
+ ...context
553
+ }
554
+
555
+ console.log(JSON.stringify(entry))
556
+ }
557
+
558
+ info(message: string, context?: LogContext) {
559
+ this.log('info', message, context)
560
+ }
561
+
562
+ warn(message: string, context?: LogContext) {
563
+ this.log('warn', message, context)
564
+ }
565
+
566
+ error(message: string, error: Error, context?: LogContext) {
567
+ this.log('error', message, {
568
+ ...context,
569
+ error: error.message,
570
+ stack: error.stack
571
+ })
572
+ }
573
+ }
574
+
575
+ const logger = new Logger()
576
+
577
+ // Usage
578
+ export async function GET(request: Request) {
579
+ const requestId = crypto.randomUUID()
580
+
581
+ logger.info('Fetching markets', {
582
+ requestId,
583
+ method: 'GET',
584
+ path: '/api/markets'
585
+ })
586
+
587
+ try {
588
+ const markets = await fetchMarkets()
589
+ return NextResponse.json({ success: true, data: markets })
590
+ } catch (error) {
591
+ logger.error('Failed to fetch markets', error as Error, { requestId })
592
+ return NextResponse.json({ error: 'Internal error' }, { status: 500 })
593
+ }
594
+ }
595
+ ```
596
+
597
+ **Remember**: Backend patterns enable scalable, maintainable server-side applications. Choose patterns that fit your complexity level.
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: "Backend Patterns"
3
+ short_description: "API, database, and server-side patterns"
4
+ brand_color: "#F59E0B"
5
+ default_prompt: "Use $backend-patterns to apply backend architecture and API patterns."
6
+ policy:
7
+ allow_implicit_invocation: true
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: brand-voice
3
+ description: Build a source-derived writing style profile from real posts, essays, launch notes, docs, or site copy, then reuse that profile across content, outreach, and social workflows. Use when the user wants voice consistency without generic AI writing tropes.
4
+ ---
5
+
6
+ # Brand Voice
7
+
8
+ Build a durable voice profile from real source material, then use that profile everywhere instead of re-deriving style from scratch or defaulting to generic AI copy.
9
+
10
+ ## When to Activate
11
+
12
+ - the user wants content or outreach in a specific voice
13
+ - writing for X, LinkedIn, email, launch posts, threads, or product updates
14
+ - adapting a known author's tone across channels
15
+ - the existing content lane needs a reusable style system instead of one-off mimicry
16
+
17
+ ## Source Priority
18
+
19
+ Use the strongest real source set available, in this order:
20
+
21
+ 1. recent original X posts and threads
22
+ 2. articles, essays, memos, launch notes, or newsletters
23
+ 3. real outbound emails or DMs that worked
24
+ 4. product docs, changelogs, README framing, and site copy
25
+
26
+ Do not use generic platform exemplars as source material.
27
+
28
+ ## Collection Workflow
29
+
30
+ 1. Gather 5 to 20 representative samples when available.
31
+ 2. Prefer recent material over old material unless the user says the older writing is more canonical.
32
+ 3. Separate "public launch voice" from "private working voice" if the source set clearly splits.
33
+ 4. If live X access is available, use `x-api` to pull recent original posts before drafting.
34
+ 5. If site copy matters, include the current ECC landing page and repo/plugin framing.
35
+
36
+ ## What to Extract
37
+
38
+ - rhythm and sentence length
39
+ - compression vs explanation
40
+ - capitalization norms
41
+ - parenthetical use
42
+ - question frequency and purpose
43
+ - how sharply claims are made
44
+ - how often numbers, mechanisms, or receipts show up
45
+ - how transitions work
46
+ - what the author never does
47
+
48
+ ## Output Contract
49
+
50
+ Produce a reusable `VOICE PROFILE` block that downstream skills can consume directly. Use the schema in [references/voice-profile-schema.md](references/voice-profile-schema.md).
51
+
52
+ Keep the profile structured and short enough to reuse in session context. The point is not literary criticism. The point is operational reuse.
53
+
54
+ ## Affaan / ECC Defaults
55
+
56
+ If the user wants Affaan / ECC voice and live sources are thin, start here unless newer source material overrides it:
57
+
58
+ - direct, compressed, concrete
59
+ - specifics, mechanisms, receipts, and numbers beat adjectives
60
+ - parentheticals are for qualification, narrowing, or over-clarification
61
+ - capitalization is conventional unless there is a real reason to break it
62
+ - questions are rare and should not be used as bait
63
+ - tone can be sharp, blunt, skeptical, or dry
64
+ - transitions should feel earned, not smoothed over
65
+
66
+ ## Hard Bans
67
+
68
+ Delete and rewrite any of these:
69
+
70
+ - fake curiosity hooks
71
+ - "not X, just Y"
72
+ - "no fluff"
73
+ - forced lowercase
74
+ - LinkedIn thought-leader cadence
75
+ - bait questions
76
+ - "Excited to share"
77
+ - generic founder-journey filler
78
+ - corny parentheticals
79
+
80
+ ## Persistence Rules
81
+
82
+ - Reuse the latest confirmed `VOICE PROFILE` across related tasks in the same session.
83
+ - If the user asks for a durable artifact, save the profile in the requested workspace location or memory surface.
84
+ - Do not create repo-tracked files that store personal voice fingerprints unless the user explicitly asks for that.
85
+
86
+ ## Downstream Use
87
+
88
+ Use this skill before or inside:
89
+
90
+ - `content-engine`
91
+ - `crosspost`
92
+ - `lead-intelligence`
93
+ - article or launch writing
94
+ - cold or warm outbound across X, LinkedIn, and email
95
+
96
+ If another skill already has a partial voice capture section, this skill is the canonical source of truth.
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: "Brand Voice"
3
+ short_description: "Source-derived writing style profiles"
4
+ brand_color: "#0EA5E9"
5
+ default_prompt: "Use $brand-voice to derive and reuse a source-grounded writing style."
6
+ policy:
7
+ allow_implicit_invocation: true