@botlearn/doc-gen 0.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.
- package/LICENSE +21 -0
- package/README.md +35 -0
- package/knowledge/anti-patterns.md +70 -0
- package/knowledge/best-practices.md +154 -0
- package/knowledge/domain.md +354 -0
- package/manifest.json +28 -0
- package/package.json +38 -0
- package/skill.md +48 -0
- package/strategies/main.md +147 -0
- package/tests/benchmark.json +506 -0
- package/tests/smoke.json +54 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1",
|
|
3
|
+
"dimension": "code-generation",
|
|
4
|
+
"tasks": [
|
|
5
|
+
{
|
|
6
|
+
"id": "bench-easy-01",
|
|
7
|
+
"difficulty": "easy",
|
|
8
|
+
"description": "Generate JSDoc for a single exported function with clear signature",
|
|
9
|
+
"input": "Generate complete JSDoc documentation for this function:\n\n```typescript\nexport async function sendEmail(\n to: string,\n subject: string,\n body: string,\n options?: { cc?: string[]; bcc?: string[]; replyTo?: string }\n): Promise<{ messageId: string; status: 'sent' | 'queued' }> {\n if (!to.includes('@')) throw new ValidationError('Invalid recipient email');\n if (!subject.trim()) throw new ValidationError('Subject cannot be empty');\n const result = await mailer.send({ to, subject, body, ...options });\n return { messageId: result.id, status: result.queued ? 'queued' : 'sent' };\n}\n```",
|
|
10
|
+
"rubric": [
|
|
11
|
+
{
|
|
12
|
+
"criterion": "Completeness",
|
|
13
|
+
"weight": 0.4,
|
|
14
|
+
"scoring": {
|
|
15
|
+
"5": "Summary, all params (to, subject, body, options with sub-properties), return type with both status values, both ValidationErrors documented with trigger conditions",
|
|
16
|
+
"3": "Summary and params documented but missing error conditions or options sub-properties",
|
|
17
|
+
"1": "Only summary and basic param types",
|
|
18
|
+
"0": "No meaningful documentation"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"criterion": "Example",
|
|
23
|
+
"weight": 0.3,
|
|
24
|
+
"scoring": {
|
|
25
|
+
"5": "At least one basic usage example and one with options; shows expected return value; uses realistic email data",
|
|
26
|
+
"3": "One example but missing options usage or expected output",
|
|
27
|
+
"1": "Trivial or non-runnable example",
|
|
28
|
+
"0": "No example"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"criterion": "Formatting",
|
|
33
|
+
"weight": 0.3,
|
|
34
|
+
"scoring": {
|
|
35
|
+
"5": "Proper JSDoc tags (@param, @returns, @throws, @example); consistent formatting; options sub-properties documented with @property or nested description",
|
|
36
|
+
"3": "Correct tags but inconsistent formatting",
|
|
37
|
+
"1": "Missing or incorrect JSDoc tags",
|
|
38
|
+
"0": "No JSDoc structure"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"expectedScoreWithout": 35,
|
|
43
|
+
"expectedScoreWith": 80
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "bench-easy-02",
|
|
47
|
+
"difficulty": "easy",
|
|
48
|
+
"description": "Generate a changelog entry from a set of commit messages",
|
|
49
|
+
"input": "Generate a Keep a Changelog entry for version 2.3.0 (release date: 2024-09-20) from these commit messages:\n\n- feat: add batch import endpoint for CSV files (#312)\n- feat: add export to PDF functionality (#318)\n- fix: correct timezone handling in scheduled reports (#305)\n- fix: prevent duplicate webhook deliveries on retry (#309)\n- refactor: extract validation logic into shared middleware\n- chore: update CI pipeline to Node 20\n- fix: resolve memory leak in long-running WebSocket connections (#315)\n- feat(api): add pagination support to /events endpoint (#320)\n- deprecated: mark /v1/reports endpoint for removal in 3.0 (#322)\n- security: patch SSRF vulnerability in URL preview feature (CVE-2024-98765)",
|
|
50
|
+
"rubric": [
|
|
51
|
+
{
|
|
52
|
+
"criterion": "Categorization",
|
|
53
|
+
"weight": 0.4,
|
|
54
|
+
"scoring": {
|
|
55
|
+
"5": "Correctly maps all commits to Keep a Changelog categories (Added, Changed, Fixed, Deprecated, Security); excludes non-user-facing changes (refactor, chore)",
|
|
56
|
+
"3": "Most commits correctly categorized but includes internal changes or miscategorizes some",
|
|
57
|
+
"1": "Categories present but many commits misplaced",
|
|
58
|
+
"0": "No categorization or raw commit dump"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"criterion": "Entry Quality",
|
|
63
|
+
"weight": 0.35,
|
|
64
|
+
"scoring": {
|
|
65
|
+
"5": "Entries rewritten in imperative mood, human-readable, with issue/PR references preserved; security entry includes CVE reference",
|
|
66
|
+
"3": "Entries are readable but some are just cleaned-up commit messages",
|
|
67
|
+
"1": "Raw commit messages copied without rewriting",
|
|
68
|
+
"0": "Unusable entries"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"criterion": "Format Compliance",
|
|
73
|
+
"weight": 0.25,
|
|
74
|
+
"scoring": {
|
|
75
|
+
"5": "Follows Keep a Changelog format exactly: version heading with date, category headings, bulleted entries, comparison link placeholder",
|
|
76
|
+
"3": "Mostly correct format but missing date or comparison link",
|
|
77
|
+
"1": "Partial format compliance",
|
|
78
|
+
"0": "No standard format"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"expectedScoreWithout": 30,
|
|
83
|
+
"expectedScoreWith": 75
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "bench-easy-03",
|
|
87
|
+
"difficulty": "easy",
|
|
88
|
+
"description": "Generate a README Quick Start section for a simple npm package",
|
|
89
|
+
"input": "Generate a complete README for this npm package based on the following information:\n\n- Package name: @acme/rate-limiter\n- Description: A lightweight, in-memory rate limiter for Node.js applications with sliding window support\n- Install: npm/yarn/pnpm\n- Main export: `createLimiter(options)` returns a limiter instance\n- Options: { maxRequests: number (default 100), windowMs: number (default 60000), keyGenerator?: (req) => string }\n- Methods: `limiter.check(key): { allowed: boolean, remaining: number, resetAt: Date }`, `limiter.reset(key): void`\n- Requires Node.js >= 18\n- License: MIT\n- Author: Acme Corp",
|
|
90
|
+
"rubric": [
|
|
91
|
+
{
|
|
92
|
+
"criterion": "Structure",
|
|
93
|
+
"weight": 0.35,
|
|
94
|
+
"scoring": {
|
|
95
|
+
"5": "Complete README with title, description, installation (all 3 managers), quick start, API reference, configuration table, license; proper heading hierarchy",
|
|
96
|
+
"3": "Most sections present but missing one of install/quick-start/API",
|
|
97
|
+
"1": "Only partial sections; no clear structure",
|
|
98
|
+
"0": "Unstructured text"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"criterion": "Quick Start Quality",
|
|
103
|
+
"weight": 0.35,
|
|
104
|
+
"scoring": {
|
|
105
|
+
"5": "Copy-pasteable example under 10 lines showing createLimiter + check; includes import, setup, and usage with realistic data and expected output",
|
|
106
|
+
"3": "Example present but not immediately runnable or missing expected output",
|
|
107
|
+
"1": "Pseudocode or overly simplified example",
|
|
108
|
+
"0": "No quick start"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"criterion": "API Reference",
|
|
113
|
+
"weight": 0.3,
|
|
114
|
+
"scoring": {
|
|
115
|
+
"5": "All options and methods documented in tables with types, defaults, and descriptions; return types clearly specified",
|
|
116
|
+
"3": "API documented but missing some defaults or type information",
|
|
117
|
+
"1": "Incomplete API listing",
|
|
118
|
+
"0": "No API reference"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"expectedScoreWithout": 35,
|
|
123
|
+
"expectedScoreWith": 80
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"id": "bench-med-01",
|
|
127
|
+
"difficulty": "medium",
|
|
128
|
+
"description": "Generate OpenAPI 3.x specification from Express route handlers",
|
|
129
|
+
"input": "Generate a complete OpenAPI 3.0.3 specification for these Express route handlers:\n\n```typescript\nconst router = express.Router();\n\nrouter.post('/api/projects', authenticate, async (req, res) => {\n const { name, description, visibility } = req.body;\n // name: string (required, 1-100 chars)\n // description: string (optional, max 500 chars)\n // visibility: 'public' | 'private' | 'internal' (default: 'private')\n const project = await ProjectService.create(req.user.id, { name, description, visibility });\n res.status(201).json(project);\n});\n\nrouter.get('/api/projects/:projectId', optionalAuth, async (req, res) => {\n const project = await ProjectService.findById(req.params.projectId);\n if (!project) return res.status(404).json({ error: 'PROJECT_NOT_FOUND', message: 'Project not found' });\n if (project.visibility === 'private' && project.ownerId !== req.user?.id) {\n return res.status(403).json({ error: 'FORBIDDEN', message: 'Access denied' });\n }\n res.json(project);\n});\n\nrouter.get('/api/projects', optionalAuth, async (req, res) => {\n // Query params: page (default 1), limit (default 20, max 100), visibility, search\n const results = await ProjectService.list(req.query);\n res.json({ data: results.items, pagination: { page: results.page, limit: results.limit, total: results.total } });\n});\n\nrouter.patch('/api/projects/:projectId', authenticate, async (req, res) => {\n const project = await ProjectService.findById(req.params.projectId);\n if (!project) return res.status(404).json({ error: 'PROJECT_NOT_FOUND' });\n if (project.ownerId !== req.user.id) return res.status(403).json({ error: 'FORBIDDEN' });\n const updated = await ProjectService.update(req.params.projectId, req.body);\n res.json(updated);\n});\n\nrouter.delete('/api/projects/:projectId', authenticate, async (req, res) => {\n const project = await ProjectService.findById(req.params.projectId);\n if (!project) return res.status(404).json({ error: 'PROJECT_NOT_FOUND' });\n if (project.ownerId !== req.user.id) return res.status(403).json({ error: 'FORBIDDEN' });\n await ProjectService.delete(req.params.projectId);\n res.status(204).send();\n});\n```",
|
|
130
|
+
"rubric": [
|
|
131
|
+
{
|
|
132
|
+
"criterion": "Endpoint Coverage",
|
|
133
|
+
"weight": 0.3,
|
|
134
|
+
"scoring": {
|
|
135
|
+
"5": "All 5 endpoints documented with correct HTTP methods, paths, and operationIds; authentication requirements (authenticate vs optionalAuth) correctly mapped to security schemes",
|
|
136
|
+
"3": "All endpoints present but authentication requirements not differentiated",
|
|
137
|
+
"1": "Some endpoints missing or incorrect methods",
|
|
138
|
+
"0": "Incomplete or incorrect endpoint listing"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"criterion": "Schema Accuracy",
|
|
143
|
+
"weight": 0.3,
|
|
144
|
+
"scoring": {
|
|
145
|
+
"5": "Request bodies and response schemas fully defined with correct types, required fields, constraints (minLength, maxLength, enum), and defaults; pagination response schema included; Error schema defined",
|
|
146
|
+
"3": "Schemas present but missing constraints or defaults",
|
|
147
|
+
"1": "Basic schemas without proper typing",
|
|
148
|
+
"0": "No schemas defined"
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"criterion": "Response Documentation",
|
|
153
|
+
"weight": 0.2,
|
|
154
|
+
"scoring": {
|
|
155
|
+
"5": "All response codes documented (200, 201, 204, 400, 401, 403, 404) with appropriate schemas and examples for each endpoint",
|
|
156
|
+
"3": "Success responses documented but error responses incomplete",
|
|
157
|
+
"1": "Only success responses documented",
|
|
158
|
+
"0": "Responses not properly documented"
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"criterion": "Examples",
|
|
163
|
+
"weight": 0.2,
|
|
164
|
+
"scoring": {
|
|
165
|
+
"5": "Request and response examples with realistic data for each endpoint; includes cURL examples",
|
|
166
|
+
"3": "Some examples present but not for all endpoints",
|
|
167
|
+
"1": "Minimal or unrealistic examples",
|
|
168
|
+
"0": "No examples"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"expectedScoreWithout": 25,
|
|
173
|
+
"expectedScoreWith": 70
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"id": "bench-med-02",
|
|
177
|
+
"difficulty": "medium",
|
|
178
|
+
"description": "Document an undocumented class with inheritance and complex method signatures",
|
|
179
|
+
"input": "Generate complete TSDoc documentation for this class hierarchy. Cover all public methods, constructor, generics, and inheritance behavior:\n\n```typescript\nexport abstract class BaseRepository<T extends { id: string }> {\n constructor(protected collection: Collection<T>) {}\n\n async findById(id: string): Promise<T | null> {\n return this.collection.findOne({ id } as any);\n }\n\n async findMany(filter: Partial<T>, options?: { limit?: number; offset?: number; sort?: Record<string, 1 | -1> }): Promise<T[]> {\n let query = this.collection.find(filter as any);\n if (options?.sort) query = query.sort(options.sort);\n if (options?.offset) query = query.skip(options.offset);\n if (options?.limit) query = query.limit(options.limit);\n return query.toArray();\n }\n\n async count(filter?: Partial<T>): Promise<number> {\n return this.collection.countDocuments(filter as any ?? {});\n }\n\n abstract validate(entity: Omit<T, 'id'>): Promise<void>;\n\n async create(data: Omit<T, 'id'>): Promise<T> {\n await this.validate(data);\n const entity = { ...data, id: generateId() } as T;\n await this.collection.insertOne(entity as any);\n return entity;\n }\n\n async update(id: string, data: Partial<Omit<T, 'id'>>): Promise<T | null> {\n const result = await this.collection.findOneAndUpdate(\n { id } as any,\n { $set: data } as any,\n { returnDocument: 'after' }\n );\n return result ?? null;\n }\n\n async delete(id: string): Promise<boolean> {\n const result = await this.collection.deleteOne({ id } as any);\n return result.deletedCount > 0;\n }\n}\n\nexport class OrderRepository extends BaseRepository<Order> {\n async validate(data: Omit<Order, 'id'>): Promise<void> {\n if (!data.customerId) throw new ValidationError('Customer ID is required');\n if (!data.items?.length) throw new ValidationError('Order must have at least one item');\n if (data.items.some(i => i.quantity <= 0)) throw new ValidationError('Item quantity must be positive');\n }\n\n async findByCustomer(customerId: string, status?: OrderStatus): Promise<Order[]> {\n const filter: Partial<Order> = { customerId };\n if (status) filter.status = status;\n return this.findMany(filter, { sort: { createdAt: -1 } });\n }\n\n async calculateTotal(orderId: string): Promise<number> {\n const order = await this.findById(orderId);\n if (!order) throw new NotFoundError(`Order ${orderId} not found`);\n return order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);\n }\n}\n```",
|
|
180
|
+
"rubric": [
|
|
181
|
+
{
|
|
182
|
+
"criterion": "Class-Level Documentation",
|
|
183
|
+
"weight": 0.25,
|
|
184
|
+
"scoring": {
|
|
185
|
+
"5": "Both classes have class-level TSDoc: purpose, generic constraints explained, design pattern noted (Repository), inheritance relationship documented; abstract method contract explained",
|
|
186
|
+
"3": "Class-level docs present but missing generic explanation or inheritance notes",
|
|
187
|
+
"1": "Minimal class descriptions",
|
|
188
|
+
"0": "No class-level documentation"
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"criterion": "Method Documentation",
|
|
193
|
+
"weight": 0.3,
|
|
194
|
+
"scoring": {
|
|
195
|
+
"5": "All 10 methods fully documented: summary, params with semantic meaning, return values including null/false cases, all thrown errors with conditions; abstract validate contract specified",
|
|
196
|
+
"3": "Most methods documented but some missing error conditions or null return cases",
|
|
197
|
+
"1": "Only basic summaries without param/return details",
|
|
198
|
+
"0": "Methods not documented"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"criterion": "Generics and Types",
|
|
203
|
+
"weight": 0.2,
|
|
204
|
+
"scoring": {
|
|
205
|
+
"5": "Generic type parameter T documented with @typeParam; constraint `{ id: string }` explained; Partial<T>, Omit<T, 'id'> utility types explained in context; OrderStatus type referenced",
|
|
206
|
+
"3": "Generics mentioned but not fully explained",
|
|
207
|
+
"1": "Generics not addressed in documentation",
|
|
208
|
+
"0": "Type information ignored"
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"criterion": "Examples",
|
|
213
|
+
"weight": 0.25,
|
|
214
|
+
"scoring": {
|
|
215
|
+
"5": "Usage examples for both BaseRepository (via OrderRepository) and OrderRepository-specific methods; shows creation, querying, updating, error handling",
|
|
216
|
+
"3": "Some examples but not covering key methods",
|
|
217
|
+
"1": "One minimal example",
|
|
218
|
+
"0": "No examples"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
"expectedScoreWithout": 25,
|
|
223
|
+
"expectedScoreWith": 70
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "bench-med-03",
|
|
227
|
+
"difficulty": "medium",
|
|
228
|
+
"description": "Update stale documentation to match refactored code",
|
|
229
|
+
"input": "The following function was refactored but its JSDoc was not updated. Update the documentation to accurately reflect the current code. Identify all inaccuracies in the existing docs.\n\nExisting (stale) documentation:\n```typescript\n/**\n * Fetch a user by their username.\n *\n * @param username - The user's unique username\n * @param includeProfile - Whether to include the full profile (default: false)\n * @returns The user object with optional profile\n * @throws {NotFoundError} If the username does not exist\n */\n```\n\nCurrent code:\n```typescript\nexport async function fetchUser(\n identifier: string | { email: string },\n options: {\n includeProfile?: boolean;\n includePermissions?: boolean;\n cache?: boolean;\n } = {}\n): Promise<UserResponse | null> {\n const cacheKey = typeof identifier === 'string' ? identifier : identifier.email;\n\n if (options.cache !== false) {\n const cached = await redis.get(`user:${cacheKey}`);\n if (cached) return JSON.parse(cached);\n }\n\n const user = typeof identifier === 'string'\n ? await db.users.findOne({ id: identifier })\n : await db.users.findOne({ email: identifier.email });\n\n if (!user) return null;\n\n const response: UserResponse = { ...user };\n if (options.includeProfile) response.profile = await db.profiles.findOne({ userId: user.id });\n if (options.includePermissions) response.permissions = await getPermissions(user.id);\n\n if (options.cache !== false) {\n await redis.setex(`user:${cacheKey}`, 300, JSON.stringify(response));\n }\n\n return response;\n}\n```",
|
|
230
|
+
"rubric": [
|
|
231
|
+
{
|
|
232
|
+
"criterion": "Inaccuracy Identification",
|
|
233
|
+
"weight": 0.3,
|
|
234
|
+
"scoring": {
|
|
235
|
+
"5": "Identifies all inaccuracies: (1) param changed from username to identifier with union type, (2) second param restructured from boolean to options object, (3) new includePermissions and cache options, (4) returns null instead of throwing NotFoundError, (5) caching behavior added",
|
|
236
|
+
"3": "Identifies 3-4 inaccuracies",
|
|
237
|
+
"1": "Identifies 1-2 inaccuracies",
|
|
238
|
+
"0": "Fails to identify major inaccuracies"
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"criterion": "Updated Documentation",
|
|
243
|
+
"weight": 0.35,
|
|
244
|
+
"scoring": {
|
|
245
|
+
"5": "Complete updated JSDoc reflecting all current behavior: union type identifier, full options object with all 3 properties and defaults, null return case, caching behavior, no false NotFoundError @throws",
|
|
246
|
+
"3": "Updated docs mostly correct but missing some new behavior",
|
|
247
|
+
"1": "Partially updated; still contains stale information",
|
|
248
|
+
"0": "Documentation not meaningfully updated"
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"criterion": "Added Context",
|
|
253
|
+
"weight": 0.2,
|
|
254
|
+
"scoring": {
|
|
255
|
+
"5": "Documents caching behavior (TTL, key strategy), explains identifier union type usage (string ID vs email object), describes what includeProfile and includePermissions add to the response",
|
|
256
|
+
"3": "Some new behavior documented but caching or union type not fully explained",
|
|
257
|
+
"1": "Minimal additional context",
|
|
258
|
+
"0": "No new context added"
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"criterion": "Examples",
|
|
263
|
+
"weight": 0.15,
|
|
264
|
+
"scoring": {
|
|
265
|
+
"5": "Examples showing both identifier forms (string and {email}), with and without options, demonstrating null return",
|
|
266
|
+
"3": "One example showing basic usage",
|
|
267
|
+
"1": "Example present but outdated",
|
|
268
|
+
"0": "No examples"
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
],
|
|
272
|
+
"expectedScoreWithout": 25,
|
|
273
|
+
"expectedScoreWith": 70
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"id": "bench-med-04",
|
|
277
|
+
"difficulty": "medium",
|
|
278
|
+
"description": "Generate documentation for a configuration-heavy module with many options",
|
|
279
|
+
"input": "Generate complete documentation (JSDoc + README section) for this configuration system:\n\n```typescript\nexport interface LoggerConfig {\n level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n format: 'json' | 'pretty' | 'compact';\n output: 'stdout' | 'stderr' | 'file';\n filePath?: string;\n maxFileSize?: number;\n maxFiles?: number;\n includeTimestamp?: boolean;\n includeHostname?: boolean;\n includePid?: boolean;\n redactPaths?: string[];\n customLevels?: Record<string, number>;\n hooks?: {\n onLog?: (entry: LogEntry) => void;\n onError?: (error: Error) => void;\n onRotate?: (oldPath: string, newPath: string) => void;\n };\n}\n\nexport function createLogger(config: Partial<LoggerConfig> = {}): Logger {\n const defaults: LoggerConfig = {\n level: 'info',\n format: 'json',\n output: 'stdout',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 5,\n includeTimestamp: true,\n includeHostname: false,\n includePid: false,\n redactPaths: [],\n };\n // merges config with defaults, validates, returns Logger instance\n}\n\nexport class Logger {\n trace(msg: string, data?: Record<string, unknown>): void;\n debug(msg: string, data?: Record<string, unknown>): void;\n info(msg: string, data?: Record<string, unknown>): void;\n warn(msg: string, data?: Record<string, unknown>): void;\n error(msg: string, data?: Record<string, unknown>): void;\n fatal(msg: string, data?: Record<string, unknown>): void;\n child(bindings: Record<string, unknown>): Logger;\n flush(): Promise<void>;\n}\n```",
|
|
280
|
+
"rubric": [
|
|
281
|
+
{
|
|
282
|
+
"criterion": "Configuration Table",
|
|
283
|
+
"weight": 0.3,
|
|
284
|
+
"scoring": {
|
|
285
|
+
"5": "Complete configuration table with all options: name, type, default, required/optional, description; including nested hooks properties; constraints documented (file output requires filePath)",
|
|
286
|
+
"3": "Most options documented but missing some defaults or nested properties",
|
|
287
|
+
"1": "Partial option listing",
|
|
288
|
+
"0": "No configuration documentation"
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"criterion": "JSDoc Quality",
|
|
293
|
+
"weight": 0.25,
|
|
294
|
+
"scoring": {
|
|
295
|
+
"5": "LoggerConfig interface, createLogger function, and all Logger methods fully documented with proper tags; Partial<LoggerConfig> explained; redactPaths behavior described",
|
|
296
|
+
"3": "Most symbols documented but some methods or properties lack detail",
|
|
297
|
+
"1": "Only surface-level documentation",
|
|
298
|
+
"0": "Missing JSDoc"
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"criterion": "Examples",
|
|
303
|
+
"weight": 0.25,
|
|
304
|
+
"scoring": {
|
|
305
|
+
"5": "Multiple examples: basic setup, file output with rotation, pretty format for development, custom levels, child loggers, redaction usage; each example is runnable",
|
|
306
|
+
"3": "2-3 examples covering basic and one advanced scenario",
|
|
307
|
+
"1": "Single basic example",
|
|
308
|
+
"0": "No examples"
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"criterion": "README Format",
|
|
313
|
+
"weight": 0.2,
|
|
314
|
+
"scoring": {
|
|
315
|
+
"5": "README section with configuration table, quick start, example configurations for common use cases (development, production, testing)",
|
|
316
|
+
"3": "README section present but not organized for different use cases",
|
|
317
|
+
"1": "Raw text without README formatting",
|
|
318
|
+
"0": "No README content"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
],
|
|
322
|
+
"expectedScoreWithout": 25,
|
|
323
|
+
"expectedScoreWith": 70
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"id": "bench-hard-01",
|
|
327
|
+
"difficulty": "hard",
|
|
328
|
+
"description": "Generate a complete documentation suite for an undocumented microservice",
|
|
329
|
+
"input": "Generate a complete documentation suite (README, API reference with OpenAPI spec, and changelog from commits) for this undocumented payment processing microservice:\n\n```typescript\n// src/routes/payments.ts\nrouter.post('/payments', authenticate, async (req, res) => {\n // Creates a payment intent. Body: { amount: number (cents), currency: string (ISO 4217), customerId: string, metadata?: Record<string,string> }\n // Returns 201 with PaymentIntent { id, amount, currency, status: 'pending', createdAt }\n // Errors: 400 (validation), 402 (insufficient_funds), 409 (duplicate idempotency key)\n // Header: Idempotency-Key (required)\n});\n\nrouter.get('/payments/:paymentId', authenticate, async (req, res) => {\n // Returns PaymentIntent or 404\n});\n\nrouter.post('/payments/:paymentId/capture', authenticate, async (req, res) => {\n // Captures a pending payment. Optional body: { amount?: number } for partial capture\n // Returns updated PaymentIntent with status: 'captured'\n // Errors: 400 (already captured), 404, 409 (payment expired)\n});\n\nrouter.post('/payments/:paymentId/refund', authenticate, async (req, res) => {\n // Refunds a captured payment. Body: { amount?: number, reason?: string }\n // Full refund if amount omitted. Returns Refund { id, paymentId, amount, status, createdAt }\n // Errors: 400 (exceeds captured amount), 404, 409 (already fully refunded)\n});\n\nrouter.get('/payments', authenticate, async (req, res) => {\n // List payments. Query: customerId, status, from, to, limit (default 20), cursor\n // Returns { data: PaymentIntent[], cursor?: string, hasMore: boolean }\n});\n\n// Recent commits:\n// feat: add idempotency key support for payment creation (#45)\n// feat: implement partial capture for payment intents (#42)\n// feat: add cursor-based pagination to list endpoint (#40)\n// fix: correct currency validation to accept lowercase ISO codes (#38)\n// fix: race condition in concurrent refund requests (#36)\n// security: add rate limiting to payment creation endpoint\n// feat: add metadata field to payment intents (#33)\n// fix: handle webhook timeout gracefully with exponential backoff (#30)\n```\n\nThe service has no existing documentation. Generate README (with install, config, API overview), full OpenAPI spec, and changelog for version 1.3.0.",
|
|
330
|
+
"rubric": [
|
|
331
|
+
{
|
|
332
|
+
"criterion": "README Completeness",
|
|
333
|
+
"weight": 0.25,
|
|
334
|
+
"scoring": {
|
|
335
|
+
"5": "Full README with: project description, prerequisites, installation, environment configuration (API keys, database URL, etc.), API overview with endpoint table, authentication section, error handling conventions, link to full API spec",
|
|
336
|
+
"3": "README covers basics but missing configuration or error handling sections",
|
|
337
|
+
"1": "Minimal README with just endpoint listing",
|
|
338
|
+
"0": "No README or unusable README"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"criterion": "OpenAPI Specification",
|
|
343
|
+
"weight": 0.3,
|
|
344
|
+
"scoring": {
|
|
345
|
+
"5": "Complete OpenAPI 3.x spec with all 5 endpoints, correct schemas (PaymentIntent, Refund, Error, PaginatedResponse), all response codes, Idempotency-Key header, authentication scheme, request/response examples, proper use of $ref for shared schemas",
|
|
346
|
+
"3": "All endpoints documented but schemas incomplete or missing some response codes",
|
|
347
|
+
"1": "Partial endpoint coverage or incorrect schemas",
|
|
348
|
+
"0": "No OpenAPI spec or fundamentally incorrect"
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"criterion": "Changelog Quality",
|
|
353
|
+
"weight": 0.2,
|
|
354
|
+
"scoring": {
|
|
355
|
+
"5": "Keep a Changelog format for v1.3.0; commits correctly categorized (Added, Fixed, Security); entries rewritten for user clarity; internal changes excluded; issue refs preserved",
|
|
356
|
+
"3": "Correct format but some miscategorization or commit messages not rewritten",
|
|
357
|
+
"1": "Raw commit list or wrong format",
|
|
358
|
+
"0": "No changelog"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"criterion": "Cross-Document Consistency",
|
|
363
|
+
"weight": 0.15,
|
|
364
|
+
"scoring": {
|
|
365
|
+
"5": "Schemas, endpoint names, and field descriptions are consistent across README, OpenAPI spec, and changelog; no contradictions between documents",
|
|
366
|
+
"3": "Mostly consistent but minor discrepancies",
|
|
367
|
+
"1": "Significant inconsistencies between documents",
|
|
368
|
+
"0": "Documents contradict each other"
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"criterion": "Domain Accuracy",
|
|
373
|
+
"weight": 0.1,
|
|
374
|
+
"scoring": {
|
|
375
|
+
"5": "Payment processing concepts correctly applied: idempotency for creation, partial capture semantics, refund limits, ISO 4217 currency codes, amounts in cents",
|
|
376
|
+
"3": "Basic payment concepts correct but some nuances missed",
|
|
377
|
+
"1": "Payment domain terminology misused",
|
|
378
|
+
"0": "Fundamental misunderstanding of payment concepts"
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
],
|
|
382
|
+
"expectedScoreWithout": 20,
|
|
383
|
+
"expectedScoreWith": 65
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"id": "bench-hard-02",
|
|
387
|
+
"difficulty": "hard",
|
|
388
|
+
"description": "Generate documentation for a complex event-driven system with multiple interacting components",
|
|
389
|
+
"input": "Generate complete documentation for this event-driven notification system. The documentation must cover the public API, event flow, configuration, and error handling across all components:\n\n```typescript\n// src/events.ts\nexport type NotificationEvent =\n | { type: 'user.signup'; payload: { userId: string; email: string; name: string } }\n | { type: 'order.completed'; payload: { orderId: string; userId: string; total: number; items: number } }\n | { type: 'payment.failed'; payload: { paymentId: string; userId: string; reason: string; retryable: boolean } }\n | { type: 'subscription.expiring'; payload: { subscriptionId: string; userId: string; expiresAt: Date; plan: string } };\n\n// src/channels.ts\nexport interface NotificationChannel {\n name: string;\n send(userId: string, message: RenderedMessage): Promise<DeliveryResult>;\n checkHealth(): Promise<boolean>;\n}\n\nexport class EmailChannel implements NotificationChannel { /* uses SendGrid */ }\nexport class SmsChannel implements NotificationChannel { /* uses Twilio */ }\nexport class PushChannel implements NotificationChannel { /* uses Firebase FCM */ }\nexport class SlackChannel implements NotificationChannel { /* uses Slack API */ }\n\n// src/router.ts\nexport class NotificationRouter {\n constructor(channels: NotificationChannel[], rules: RoutingRule[]);\n async route(event: NotificationEvent): Promise<RoutingResult>;\n addRule(rule: RoutingRule): void;\n removeRule(ruleId: string): void;\n}\n\nexport interface RoutingRule {\n id: string;\n eventType: string;\n channels: string[];\n condition?: (payload: any) => boolean;\n priority: 'critical' | 'high' | 'normal' | 'low';\n throttle?: { maxPerHour: number; key: string };\n template: string;\n}\n\n// src/templates.ts\nexport class TemplateEngine {\n constructor(templateDir: string);\n render(templateName: string, data: Record<string, unknown>): Promise<RenderedMessage>;\n registerHelper(name: string, fn: (...args: any[]) => string): void;\n validateTemplate(templateName: string): Promise<ValidationResult>;\n}\n\n// src/index.ts\nexport class NotificationService {\n constructor(config: NotificationConfig);\n async emit(event: NotificationEvent): Promise<EmitResult>;\n async getDeliveryStatus(notificationId: string): Promise<DeliveryStatus>;\n async getUserPreferences(userId: string): Promise<UserPreferences>;\n async updateUserPreferences(userId: string, prefs: Partial<UserPreferences>): Promise<void>;\n on(event: 'delivered' | 'failed' | 'bounced', handler: (detail: EventDetail) => void): void;\n shutdown(): Promise<void>;\n}\n```",
|
|
390
|
+
"rubric": [
|
|
391
|
+
{
|
|
392
|
+
"criterion": "Architecture Documentation",
|
|
393
|
+
"weight": 0.25,
|
|
394
|
+
"scoring": {
|
|
395
|
+
"5": "Documents the event flow: Event emitted -> Router matches rules -> Template rendered -> Channel delivers; explains component relationships; includes flow diagram or clear textual description of the pipeline",
|
|
396
|
+
"3": "Components individually documented but interaction flow not clear",
|
|
397
|
+
"1": "Partial component documentation without flow",
|
|
398
|
+
"0": "No architecture description"
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"criterion": "API Completeness",
|
|
403
|
+
"weight": 0.25,
|
|
404
|
+
"scoring": {
|
|
405
|
+
"5": "Every class, interface, type, and method documented: NotificationService (all 6 methods), NotificationRouter (3 methods), TemplateEngine (3 methods), NotificationChannel interface, all event types, RoutingRule fields; @typeParam and generics explained",
|
|
406
|
+
"3": "Main classes documented but some methods or types missing",
|
|
407
|
+
"1": "Only NotificationService documented",
|
|
408
|
+
"0": "Severely incomplete"
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"criterion": "Configuration and Setup",
|
|
413
|
+
"weight": 0.2,
|
|
414
|
+
"scoring": {
|
|
415
|
+
"5": "Full configuration guide: NotificationConfig options, channel setup (API keys, credentials), routing rules creation, template directory structure, user preferences schema; includes example configuration for common setups",
|
|
416
|
+
"3": "Basic configuration covered but missing channel-specific setup",
|
|
417
|
+
"1": "Minimal configuration notes",
|
|
418
|
+
"0": "No configuration documentation"
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"criterion": "Examples",
|
|
423
|
+
"weight": 0.2,
|
|
424
|
+
"scoring": {
|
|
425
|
+
"5": "End-to-end example: creating service, configuring channels, defining routing rules, emitting events, handling delivery callbacks; plus individual examples for each component; error handling demonstrated",
|
|
426
|
+
"3": "Basic setup and emit example but missing component-level examples",
|
|
427
|
+
"1": "Single trivial example",
|
|
428
|
+
"0": "No examples"
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
"criterion": "Error and Edge Cases",
|
|
433
|
+
"weight": 0.1,
|
|
434
|
+
"scoring": {
|
|
435
|
+
"5": "Documents: channel health check failures, delivery retries, throttle behavior, template validation errors, graceful shutdown behavior, bounced notification handling",
|
|
436
|
+
"3": "Some error cases documented but missing edge cases",
|
|
437
|
+
"1": "Only basic errors mentioned",
|
|
438
|
+
"0": "No error documentation"
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
],
|
|
442
|
+
"expectedScoreWithout": 15,
|
|
443
|
+
"expectedScoreWith": 60
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"id": "bench-hard-03",
|
|
447
|
+
"difficulty": "hard",
|
|
448
|
+
"description": "Generate documentation that bridges code-level and user-level understanding for a CLI tool",
|
|
449
|
+
"input": "Generate a complete documentation suite for this CLI database migration tool. Include: (1) User-facing README with install, commands, and examples, (2) API documentation for programmatic usage, (3) Contributing guide for the migration file format. The tool has zero existing documentation.\n\n```typescript\n// src/cli.ts — Command interface\n// Commands:\n// migrate up [--to <version>] [--dry-run] — Run pending migrations\n// migrate down [--to <version>] [--steps <n>] — Rollback migrations\n// migrate status — Show migration status table\n// migrate create <name> — Create new migration file\n// migrate validate — Check all migrations for errors\n// migrate reset --confirm — Rollback all and re-run from scratch\n\n// src/index.ts — Programmatic API\nexport class Migrator {\n constructor(config: MigratorConfig);\n async up(options?: { to?: string; dryRun?: boolean }): Promise<MigrationResult[]>;\n async down(options?: { to?: string; steps?: number }): Promise<MigrationResult[]>;\n async status(): Promise<MigrationStatus[]>;\n async validate(): Promise<ValidationResult[]>;\n async reset(): Promise<MigrationResult[]>;\n async create(name: string): Promise<string>; // returns file path\n async lock(): Promise<void>; // distributed lock for multi-instance\n async unlock(): Promise<void>;\n}\n\nexport interface MigratorConfig {\n directory: string; // path to migration files\n connection: DatabaseConfig; // { host, port, database, user, password, ssl? }\n table?: string; // migration tracking table (default: '_migrations')\n lockTimeout?: number; // lock wait timeout in ms (default: 30000)\n transactionMode?: 'per-migration' | 'all-or-nothing'; // default: 'per-migration'\n}\n\n// Migration file format: migrations/20240815_120000_add_users_table.ts\nexport interface Migration {\n name: string;\n up(db: DatabaseClient): Promise<void>;\n down(db: DatabaseClient): Promise<void>;\n}\n\n// Example migration file\nexport default {\n name: '20240815_120000_add_users_table',\n async up(db) {\n await db.query(`CREATE TABLE users (id UUID PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT NOW())`);\n await db.query(`CREATE INDEX idx_users_email ON users(email)`);\n },\n async down(db) {\n await db.query(`DROP TABLE IF EXISTS users`);\n },\n};\n```",
|
|
450
|
+
"rubric": [
|
|
451
|
+
{
|
|
452
|
+
"criterion": "User-Facing README",
|
|
453
|
+
"weight": 0.25,
|
|
454
|
+
"scoring": {
|
|
455
|
+
"5": "Complete CLI documentation: installation, all 6 commands with flags and descriptions, workflow examples (creating first migration, running up, checking status, rolling back), configuration file example, prerequisites (database setup)",
|
|
456
|
+
"3": "Commands listed but missing workflow examples or configuration guide",
|
|
457
|
+
"1": "Partial command listing",
|
|
458
|
+
"0": "No CLI documentation"
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"criterion": "Programmatic API Docs",
|
|
463
|
+
"weight": 0.25,
|
|
464
|
+
"scoring": {
|
|
465
|
+
"5": "Full Migrator class API: constructor with config documentation, all 8 methods with params/returns/errors, MigratorConfig interface with all options and defaults, MigrationResult and MigrationStatus types described; distributed locking behavior explained",
|
|
466
|
+
"3": "Main methods documented but missing config details or lock behavior",
|
|
467
|
+
"1": "Partial API coverage",
|
|
468
|
+
"0": "No API documentation"
|
|
469
|
+
}
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
"criterion": "Migration File Format Guide",
|
|
473
|
+
"weight": 0.2,
|
|
474
|
+
"scoring": {
|
|
475
|
+
"5": "Clear guide on: naming convention (timestamp_name), file structure (Migration interface), up/down contract (idempotency, reversibility), DatabaseClient methods available, examples for common operations (create table, add column, create index, data migration)",
|
|
476
|
+
"3": "Basic format explained but missing common operation examples",
|
|
477
|
+
"1": "Only the interface shown without guidance",
|
|
478
|
+
"0": "No format guide"
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"criterion": "Edge Cases and Safety",
|
|
483
|
+
"weight": 0.15,
|
|
484
|
+
"scoring": {
|
|
485
|
+
"5": "Documents: dry-run behavior, transaction modes and when to use each, distributed locking for multi-instance deployments, reset safety (--confirm flag), what happens on migration failure, partial migration recovery",
|
|
486
|
+
"3": "Some safety topics covered",
|
|
487
|
+
"1": "Safety considerations not addressed",
|
|
488
|
+
"0": "No safety documentation"
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
"criterion": "Examples Quality",
|
|
493
|
+
"weight": 0.15,
|
|
494
|
+
"scoring": {
|
|
495
|
+
"5": "Real-world examples throughout: CLI command sequences for common workflows, programmatic usage with error handling, 3+ migration file examples (DDL, data migration, index), configuration for different environments (dev, staging, prod)",
|
|
496
|
+
"3": "Some examples present but not covering real workflows",
|
|
497
|
+
"1": "Minimal trivial examples",
|
|
498
|
+
"0": "No examples"
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
],
|
|
502
|
+
"expectedScoreWithout": 15,
|
|
503
|
+
"expectedScoreWith": 60
|
|
504
|
+
}
|
|
505
|
+
]
|
|
506
|
+
}
|
package/tests/smoke.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1",
|
|
3
|
+
"timeout": 60,
|
|
4
|
+
"tasks": [
|
|
5
|
+
{
|
|
6
|
+
"id": "smoke-01",
|
|
7
|
+
"description": "Generate JSDoc documentation for an undocumented TypeScript module with multiple exported functions",
|
|
8
|
+
"input": "Generate complete documentation for the following TypeScript module. It has no existing docs. Produce JSDoc comments for every exported function, including parameter descriptions, return types, thrown errors, and at least one usage example per function.\n\n```typescript\nexport interface UserCreateInput {\n name: string;\n email: string;\n role?: 'admin' | 'member' | 'viewer';\n}\n\nexport interface User {\n id: string;\n name: string;\n email: string;\n role: string;\n createdAt: Date;\n}\n\nexport class UserService {\n constructor(private db: Database) {}\n\n async create(input: UserCreateInput): Promise<User> {\n if (!input.email.includes('@')) throw new ValidationError('Invalid email');\n const existing = await this.db.users.findByEmail(input.email);\n if (existing) throw new ConflictError('Email already registered');\n return this.db.users.insert({ ...input, role: input.role ?? 'member' });\n }\n\n async findById(id: string): Promise<User | null> {\n if (!id) throw new ValidationError('ID is required');\n return this.db.users.findOne({ id });\n }\n\n async updateRole(id: string, role: 'admin' | 'member' | 'viewer'): Promise<User> {\n const user = await this.findById(id);\n if (!user) throw new NotFoundError(`User ${id} not found`);\n return this.db.users.update(id, { role });\n }\n\n async delete(id: string): Promise<void> {\n const user = await this.findById(id);\n if (!user) throw new NotFoundError(`User ${id} not found`);\n await this.db.users.softDelete(id);\n }\n\n async list(options?: { role?: string; limit?: number; offset?: number }): Promise<User[]> {\n return this.db.users.find(options ?? {});\n }\n}\n```",
|
|
9
|
+
"rubric": [
|
|
10
|
+
{
|
|
11
|
+
"criterion": "Documentation Completeness",
|
|
12
|
+
"weight": 0.3,
|
|
13
|
+
"scoring": {
|
|
14
|
+
"5": "Every exported symbol (UserCreateInput, User, UserService, all 5 methods) has complete JSDoc with summary, param descriptions, return type, and thrown errors documented",
|
|
15
|
+
"3": "Most exports documented but some methods missing param descriptions or error documentation",
|
|
16
|
+
"1": "Only function signatures restated as comments; minimal added information",
|
|
17
|
+
"0": "No documentation generated or only partial coverage"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"criterion": "Example Quality",
|
|
22
|
+
"weight": 0.25,
|
|
23
|
+
"scoring": {
|
|
24
|
+
"5": "Each method has at least one runnable example with realistic data, proper imports/setup, and expected output shown; error handling examples included for methods that throw",
|
|
25
|
+
"3": "Examples present for most methods but use placeholder data or lack expected output",
|
|
26
|
+
"1": "Only one or two trivial examples for the entire class",
|
|
27
|
+
"0": "No examples provided"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"criterion": "Error Documentation",
|
|
32
|
+
"weight": 0.25,
|
|
33
|
+
"scoring": {
|
|
34
|
+
"5": "All thrown errors (ValidationError, ConflictError, NotFoundError) documented with specific trigger conditions for each method; @throws tags used correctly",
|
|
35
|
+
"3": "Some errors documented but missing trigger conditions or not all error types covered",
|
|
36
|
+
"1": "Errors mentioned generically without specifics",
|
|
37
|
+
"0": "No error documentation"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"criterion": "Style and Formatting",
|
|
42
|
+
"weight": 0.2,
|
|
43
|
+
"scoring": {
|
|
44
|
+
"5": "Consistent JSDoc/TSDoc formatting throughout; proper tag usage; descriptions add value beyond the type signature; interface properties documented",
|
|
45
|
+
"3": "Mostly consistent but some inconsistencies in formatting or tag usage",
|
|
46
|
+
"1": "Inconsistent style; mixes JSDoc conventions",
|
|
47
|
+
"0": "No consistent formatting"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"passThreshold": 60
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|